@tangle-network/agent-eval 0.180.0 → 0.181.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 (221) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +119 -159
  3. package/dist/adapters/http.d.ts +2 -2
  4. package/dist/{agent-profile-B7yErX0q.d.ts → agent-profile-CivaSsSy.d.ts} +4 -4
  5. package/dist/{agent-profile-B7yErX0q.d.ts.map → agent-profile-CivaSsSy.d.ts.map} +1 -1
  6. package/dist/{agent-profile-cell-0gSi5ffD.js → agent-profile-cell-Cv6UA-W_.js} +20 -57
  7. package/dist/agent-profile-cell-Cv6UA-W_.js.map +1 -0
  8. package/dist/{agent-profile-cell-CTOZJUuE.d.ts → agent-profile-cell-s__adRnK.d.ts} +3 -3
  9. package/dist/agent-profile-cell-s__adRnK.d.ts.map +1 -0
  10. package/dist/analyst/index.d.ts +10 -10
  11. package/dist/analyst/index.js +3 -3
  12. package/dist/ast-CP9ae9B0.js +557 -0
  13. package/dist/ast-CP9ae9B0.js.map +1 -0
  14. package/dist/ast-hI-vjW6J.d.ts +457 -0
  15. package/dist/ast-hI-vjW6J.d.ts.map +1 -0
  16. package/dist/{benchmark-command-D4vpnAdO.js → benchmark-command-B57n9vjz.js} +7 -6
  17. package/dist/{benchmark-command-D4vpnAdO.js.map → benchmark-command-B57n9vjz.js.map} +1 -1
  18. package/dist/benchmarks/index.d.ts +4 -4
  19. package/dist/benchmarks/index.js +3 -3
  20. package/dist/campaign/index.d.ts +6 -6
  21. package/dist/campaign/index.js +8 -8
  22. package/dist/{campaign-BGEurASO.js → campaign-4_ppJW5X.js} +12 -12
  23. package/dist/{campaign-BGEurASO.js.map → campaign-4_ppJW5X.js.map} +1 -1
  24. package/dist/{campaign-evidence-D8DBLqLI.js → campaign-evidence-B8oF9xQ6.js} +515 -471
  25. package/dist/campaign-evidence-B8oF9xQ6.js.map +1 -0
  26. package/dist/cli.js +4 -7
  27. package/dist/cli.js.map +1 -1
  28. package/dist/{client-BlLY6o2w.js → client-CXE-U1SA.js} +3 -1
  29. package/dist/client-CXE-U1SA.js.map +1 -0
  30. package/dist/{client-CuQgX33c.d.ts → client-kh2jOjTK.d.ts} +4 -4
  31. package/dist/{client-CuQgX33c.d.ts.map → client-kh2jOjTK.d.ts.map} +1 -1
  32. package/dist/contract/index.d.ts +13 -13
  33. package/dist/contract/index.js +10 -9
  34. package/dist/contract/index.js.map +1 -1
  35. package/dist/{default-registry-IGDE9XIC.d.ts → default-registry-BwDSWVzg.d.ts} +6 -6
  36. package/dist/{default-registry-IGDE9XIC.d.ts.map → default-registry-BwDSWVzg.d.ts.map} +1 -1
  37. package/dist/{define-agent-eval-Cx4Ls9ta.d.ts → define-agent-eval-CwOWWQt_.d.ts} +33 -12
  38. package/dist/define-agent-eval-CwOWWQt_.d.ts.map +1 -0
  39. package/dist/{define-agent-eval-Dzidv34q.js → define-agent-eval-Ddu33JH9.js} +134 -67
  40. package/dist/define-agent-eval-Ddu33JH9.js.map +1 -0
  41. package/dist/{dspy-rlm-engine-xKiWmj_G.js → dspy-rlm-engine-S53V0HhE.js} +2 -2
  42. package/dist/{dspy-rlm-engine-xKiWmj_G.js.map → dspy-rlm-engine-S53V0HhE.js.map} +1 -1
  43. package/dist/{engine-CX8ReXkn.d.ts → engine-DS1cysJy.d.ts} +10 -7
  44. package/dist/engine-DS1cysJy.d.ts.map +1 -0
  45. package/dist/{eval-campaign-Cs-7MiCs.js → eval-campaign-aYdtjtJR.js} +4 -4
  46. package/dist/{eval-campaign-Cs-7MiCs.js.map → eval-campaign-aYdtjtJR.js.map} +1 -1
  47. package/dist/{exact-types-B7LC1EyX.d.ts → exact-types-BZDe0W2D.d.ts} +2 -2
  48. package/dist/{exact-types-B7LC1EyX.d.ts.map → exact-types-BZDe0W2D.d.ts.map} +1 -1
  49. package/dist/experiment/index.d.ts +27 -477
  50. package/dist/experiment/index.d.ts.map +1 -1
  51. package/dist/experiment/index.js +95 -559
  52. package/dist/experiment/index.js.map +1 -1
  53. package/dist/{experiment-tracker-B3TiF5-u.d.ts → experiment-tracker-C7PfnF4b.d.ts} +2 -2
  54. package/dist/{experiment-tracker-B3TiF5-u.d.ts.map → experiment-tracker-C7PfnF4b.d.ts.map} +1 -1
  55. package/dist/{external-optimizer-process-Dlz8YxrT.js → external-optimizer-process-QDRURJAM.js} +3 -3
  56. package/dist/{external-optimizer-process-Dlz8YxrT.js.map → external-optimizer-process-QDRURJAM.js.map} +1 -1
  57. package/dist/{external-optimizer-subprocess-q3VzlGAO.js → external-optimizer-subprocess-D4dzUBZI.js} +3 -2
  58. package/dist/{external-optimizer-subprocess-q3VzlGAO.js.map → external-optimizer-subprocess-D4dzUBZI.js.map} +1 -1
  59. package/dist/{feedback-trajectory-eHWNv5Aj.d.ts → feedback-trajectory-CXmtITBo.d.ts} +3 -3
  60. package/dist/{feedback-trajectory-eHWNv5Aj.d.ts.map → feedback-trajectory-CXmtITBo.d.ts.map} +1 -1
  61. package/dist/hosted/index.d.ts +2 -2
  62. package/dist/hosted/index.d.ts.map +1 -1
  63. package/dist/hosted/index.js +1 -1
  64. package/dist/{index-BxWvILU8.d.ts → index-Bp_6sj3x.d.ts} +109 -56
  65. package/dist/index-Bp_6sj3x.d.ts.map +1 -0
  66. package/dist/{index-e7LXeRVa.d.ts → index-CJ3LhKIX.d.ts} +2 -2
  67. package/dist/{index-e7LXeRVa.d.ts.map → index-CJ3LhKIX.d.ts.map} +1 -1
  68. package/dist/{index-CiUjjEIa.d.ts → index-DNntP4ch.d.ts} +7 -7
  69. package/dist/{index-CiUjjEIa.d.ts.map → index-DNntP4ch.d.ts.map} +1 -1
  70. package/dist/{index-DxNYmx4a.d.ts → index-DoykkxW0.d.ts} +11 -11
  71. package/dist/{index-DxNYmx4a.d.ts.map → index-DoykkxW0.d.ts.map} +1 -1
  72. package/dist/index.d.ts +28 -28
  73. package/dist/index.js +24 -15
  74. package/dist/index.js.map +1 -1
  75. package/dist/{insight-report-DETqPc_A.d.ts → insight-report-D1qa0HWs.d.ts} +9 -5
  76. package/dist/{insight-report-DETqPc_A.d.ts.map → insight-report-D1qa0HWs.d.ts.map} +1 -1
  77. package/dist/{integrity-BKTcA-HP.d.ts → integrity-rGOfSUle.d.ts} +2 -2
  78. package/dist/{integrity-BKTcA-HP.d.ts.map → integrity-rGOfSUle.d.ts.map} +1 -1
  79. package/dist/{ledger-core-Cs9f7385.js → journal-Cs9f7385.js} +1 -1
  80. package/dist/journal-Cs9f7385.js.map +1 -0
  81. package/dist/{judge-calibration-C5CbMYce.d.ts → judge-calibration-DFtEMlde.d.ts} +31 -2
  82. package/dist/judge-calibration-DFtEMlde.d.ts.map +1 -0
  83. package/dist/{judge-calibration-BnpVKtnb.js → judge-calibration-DYmaBtJr.js} +48 -2
  84. package/dist/{judge-calibration-BnpVKtnb.js.map → judge-calibration-DYmaBtJr.js.map} +1 -1
  85. package/dist/ledger-core/index.d.ts +1 -1
  86. package/dist/ledger-core/index.js +1 -1
  87. package/dist/{llm-judge-v80Kmu9g.js → llm-judge-DEFZeSiu.js} +645 -456
  88. package/dist/llm-judge-DEFZeSiu.js.map +1 -0
  89. package/dist/{matrix-DeMmnWrP.d.ts → matrix-CyhW-vgJ.d.ts} +2 -2
  90. package/dist/{matrix-DeMmnWrP.d.ts.map → matrix-CyhW-vgJ.d.ts.map} +1 -1
  91. package/dist/meta-eval/index.d.ts +138 -7
  92. package/dist/meta-eval/index.d.ts.map +1 -1
  93. package/dist/meta-eval/index.js +245 -97
  94. package/dist/meta-eval/index.js.map +1 -1
  95. package/dist/{mint-Cc1_zwRQ.js → mint-ySIIkKlV.js} +2 -2
  96. package/dist/{mint-Cc1_zwRQ.js.map → mint-ySIIkKlV.js.map} +1 -1
  97. package/dist/multishot/golden/index.d.ts +1 -1
  98. package/dist/multishot/index.d.ts +2 -2
  99. package/dist/openapi.json +1 -1
  100. package/dist/outcome-store-BXlkwMPR.js +131 -0
  101. package/dist/outcome-store-BXlkwMPR.js.map +1 -0
  102. package/dist/{outcome-store-BYHIuO0e.d.ts → outcome-store-CNt4iZ67.d.ts} +18 -25
  103. package/dist/outcome-store-CNt4iZ67.d.ts.map +1 -0
  104. package/dist/{paired-promotion-decision-CGzg0cI_.d.ts → paired-promotion-decision-DPsMQm-0.d.ts} +13 -7
  105. package/dist/{paired-promotion-decision-CGzg0cI_.d.ts.map → paired-promotion-decision-DPsMQm-0.d.ts.map} +1 -1
  106. package/dist/pipelines/index.js +1 -1
  107. package/dist/{produced-state-Cv0kJJuP.js → produced-state-BHboMaab.js} +3 -3
  108. package/dist/{produced-state-Cv0kJJuP.js.map → produced-state-BHboMaab.js.map} +1 -1
  109. package/dist/profile-cell.d.ts +1 -1
  110. package/dist/profile-cell.js +1 -1
  111. package/dist/{promotion-policy-DWOm70gx.js → promotion-policy-CDMMxzb6.js} +28 -40
  112. package/dist/promotion-policy-CDMMxzb6.js.map +1 -0
  113. package/dist/{registry-ByVld1-5.d.ts → registry-BRbB6Y0v.d.ts} +4 -4
  114. package/dist/{registry-ByVld1-5.d.ts.map → registry-BRbB6Y0v.d.ts.map} +1 -1
  115. package/dist/{release-confidence-BAcNYOf1.d.ts → release-confidence-BcqeQTHW.d.ts} +3 -3
  116. package/dist/{release-confidence-BAcNYOf1.d.ts.map → release-confidence-BcqeQTHW.d.ts.map} +1 -1
  117. package/dist/{release-confidence-BcGCclTB.js → release-confidence-DMg8n18l.js} +2 -2
  118. package/dist/{release-confidence-BcGCclTB.js.map → release-confidence-DMg8n18l.js.map} +1 -1
  119. package/dist/reporting.d.ts +4 -4
  120. package/dist/reporting.js +3 -3
  121. package/dist/{researcher-jsW1X94L.d.ts → researcher-64T49THL.d.ts} +6 -6
  122. package/dist/{researcher-jsW1X94L.d.ts.map → researcher-64T49THL.d.ts.map} +1 -1
  123. package/dist/{reward-hacking-ZXEi9VCq.d.ts → reward-hacking-uzO_ihep.d.ts} +2 -2
  124. package/dist/{reward-hacking-ZXEi9VCq.d.ts.map → reward-hacking-uzO_ihep.d.ts.map} +1 -1
  125. package/dist/rl.d.ts +53 -99
  126. package/dist/rl.d.ts.map +1 -1
  127. package/dist/rl.js +182 -169
  128. package/dist/rl.js.map +1 -1
  129. package/dist/rollout/index.d.ts +1 -1
  130. package/dist/rollout/index.js +2 -2
  131. package/dist/{rollout-DmoJVqrF.js → rollout-B-UF5R6w.js} +2 -2
  132. package/dist/{rollout-DmoJVqrF.js.map → rollout-B-UF5R6w.js.map} +1 -1
  133. package/dist/rubric-predictive-validity-Bmj2_cll.d.ts +79 -0
  134. package/dist/rubric-predictive-validity-Bmj2_cll.d.ts.map +1 -0
  135. package/dist/rubric-predictive-validity-CCK-1B7w.js +178 -0
  136. package/dist/rubric-predictive-validity-CCK-1B7w.js.map +1 -0
  137. package/dist/{run-record-DTv1MdjK.d.ts → run-record-BiTWauyO.d.ts} +2 -2
  138. package/dist/{run-record-DTv1MdjK.d.ts.map → run-record-BiTWauyO.d.ts.map} +1 -1
  139. package/dist/run-record-Br-Yzt_k.js +464 -0
  140. package/dist/run-record-Br-Yzt_k.js.map +1 -0
  141. package/dist/{run-record-DQpSf7t-.js → run-record-DualPTn2.js} +2 -2
  142. package/dist/{run-record-DQpSf7t-.js.map → run-record-DualPTn2.js.map} +1 -1
  143. package/dist/{semantic-concept-judge-Bi6_iGqg.js → semantic-concept-judge-Bm5JDEKO.js} +3 -3
  144. package/dist/{semantic-concept-judge-Bi6_iGqg.js.map → semantic-concept-judge-Bm5JDEKO.js.map} +1 -1
  145. package/dist/{sequential-B5gXgcyp.js → sequential-DAsyV2T9.js} +42 -25
  146. package/dist/sequential-DAsyV2T9.js.map +1 -0
  147. package/dist/{series-convergence-DeG33RpC.d.ts → series-convergence-BnMs_uAr.d.ts} +3 -3
  148. package/dist/{series-convergence-DeG33RpC.d.ts.map → series-convergence-BnMs_uAr.d.ts.map} +1 -1
  149. package/dist/{skillopt-optimization-method-C3oYul8v.js → skillopt-optimization-method-CL_0aArC.js} +5 -5
  150. package/dist/{skillopt-optimization-method-C3oYul8v.js.map → skillopt-optimization-method-CL_0aArC.js.map} +1 -1
  151. package/dist/{statistical-heldout-0La5ZTlv.d.ts → statistical-heldout-CpVd6FmY.d.ts} +207 -144
  152. package/dist/statistical-heldout-CpVd6FmY.d.ts.map +1 -0
  153. package/dist/{store-tool-spans-4J1EDElP.d.ts → store-tool-spans-Dt-YdAuE.d.ts} +6 -6
  154. package/dist/{store-tool-spans-4J1EDElP.d.ts.map → store-tool-spans-Dt-YdAuE.d.ts.map} +1 -1
  155. package/dist/{summary-report-gMrbYawB.d.ts → summary-report-D1h4dlrK.d.ts} +3 -3
  156. package/dist/{summary-report-gMrbYawB.d.ts.map → summary-report-D1h4dlrK.d.ts.map} +1 -1
  157. package/dist/{summary-report-B16xy9Kd.js → summary-report-e-MaOAHV.js} +2 -2
  158. package/dist/{summary-report-B16xy9Kd.js.map → summary-report-e-MaOAHV.js.map} +1 -1
  159. package/dist/{tool-groups-2QA0S7dK.d.ts → tool-groups-B2bSNaJB.d.ts} +3 -3
  160. package/dist/tool-groups-B2bSNaJB.d.ts.map +1 -0
  161. package/dist/{tool-waste-B9tdWV6g.js → tool-waste-C7MU9u1e.js} +2 -2
  162. package/dist/{tool-waste-B9tdWV6g.js.map → tool-waste-C7MU9u1e.js.map} +1 -1
  163. package/dist/trace-repair/index.d.ts +2 -2
  164. package/dist/traces.d.ts +6 -6
  165. package/dist/traces.js +1 -1
  166. package/dist/{types-BmlkCrg0.d.ts → types-BvZoPTGa.d.ts} +3 -3
  167. package/dist/{types-BmlkCrg0.d.ts.map → types-BvZoPTGa.d.ts.map} +1 -1
  168. package/dist/{types-gvRsyJLh.d.ts → types-CBbLtr2J.d.ts} +38 -3
  169. package/dist/{types-gvRsyJLh.d.ts.map → types-CBbLtr2J.d.ts.map} +1 -1
  170. package/dist/{types-C34V4Vto.d.ts → types-CS0qk_Yp.d.ts} +4 -4
  171. package/dist/{types-C34V4Vto.d.ts.map → types-CS0qk_Yp.d.ts.map} +1 -1
  172. package/dist/{types-DzuaM493.d.ts → types-D7gEdPoQ.d.ts} +3 -3
  173. package/dist/{types-DzuaM493.d.ts.map → types-D7gEdPoQ.d.ts.map} +1 -1
  174. package/dist/wire/index.d.ts +2 -2
  175. package/docs/adapters-observability.md +14 -0
  176. package/docs/campaign-proposers.md +86 -128
  177. package/docs/charter.md +108 -112
  178. package/docs/concepts.md +157 -69
  179. package/docs/design/mlbenchmarks-book-review.md +440 -0
  180. package/docs/design/mlbenchmarks-review/observations.json +713 -0
  181. package/docs/design/mlbenchmarks-review/probes.mts +476 -0
  182. package/docs/design/mlbenchmarks-review/sources.json +200 -0
  183. package/docs/design/self-improvement-evidence-audit.md +263 -0
  184. package/docs/design.md +2 -1
  185. package/docs/eval-surface-map.md +95 -42
  186. package/docs/evaluation-integrity.md +220 -0
  187. package/docs/experiment.md +111 -55
  188. package/docs/feature-guide.md +5 -6
  189. package/docs/hosted-ingest-spec.md +4 -11
  190. package/docs/insight-report.md +187 -455
  191. package/docs/outcome-validity.md +182 -0
  192. package/docs/product-eval-adoption.md +1 -2
  193. package/docs/research-report-methodology.md +7 -7
  194. package/docs/search-history-receipts.md +8 -0
  195. package/docs/statistical-evidence.md +129 -0
  196. package/docs/verdicts.md +76 -49
  197. package/package.json +1 -1
  198. package/dist/agent-profile-cell-0gSi5ffD.js.map +0 -1
  199. package/dist/agent-profile-cell-CTOZJUuE.d.ts.map +0 -1
  200. package/dist/campaign-evidence-D8DBLqLI.js.map +0 -1
  201. package/dist/client-BlLY6o2w.js.map +0 -1
  202. package/dist/define-agent-eval-Cx4Ls9ta.d.ts.map +0 -1
  203. package/dist/define-agent-eval-Dzidv34q.js.map +0 -1
  204. package/dist/engine-CX8ReXkn.d.ts.map +0 -1
  205. package/dist/index-BxWvILU8.d.ts.map +0 -1
  206. package/dist/judge-calibration-C5CbMYce.d.ts.map +0 -1
  207. package/dist/ledger-core-Cs9f7385.js.map +0 -1
  208. package/dist/llm-judge-v80Kmu9g.js.map +0 -1
  209. package/dist/outcome-store-BYHIuO0e.d.ts.map +0 -1
  210. package/dist/outcome-store-ChBKlTd_.js +0 -75
  211. package/dist/outcome-store-ChBKlTd_.js.map +0 -1
  212. package/dist/promotion-policy-DWOm70gx.js.map +0 -1
  213. package/dist/rubric-predictive-validity-2D5Gw9z9.js +0 -131
  214. package/dist/rubric-predictive-validity-2D5Gw9z9.js.map +0 -1
  215. package/dist/rubric-predictive-validity-Dl1dvKCv.d.ts +0 -75
  216. package/dist/rubric-predictive-validity-Dl1dvKCv.d.ts.map +0 -1
  217. package/dist/run-record-CR63CpHK.js +0 -216
  218. package/dist/run-record-CR63CpHK.js.map +0 -1
  219. package/dist/sequential-B5gXgcyp.js.map +0 -1
  220. package/dist/statistical-heldout-0La5ZTlv.d.ts.map +0 -1
  221. package/dist/tool-groups-2QA0S7dK.d.ts.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["packageVersion","fsConstants","fs","DEFAULT_FALLBACK_INSTRUCTION","clamp01","expectString","expectStringArray","clamp01","clamp01","isObject","packageVersion","packageVersion"],"sources":["../src/profile/baselines.ts","../src/profile/index.ts","../src/verification-strategy.ts","../src/budget-guard.ts","../src/feedback-trajectory.ts","../src/scorecard.ts","../src/trace-contracts.ts","../src/active-learning.ts","../src/deprecation.ts","../src/client.ts","../src/command-runner.ts","../src/detectors/index.ts","../src/control-runtime.ts","../src/discover-personas.ts","../src/propose-review.ts","../src/propose-review-control.ts","../src/analyst/steer-firewall.ts","../src/analyst/policy-edit.ts","../src/capability-headroom.ts","../src/cost-tracker.ts","../src/error-count-extractor.ts","../src/knowledge/readiness.ts","../src/leaderboard.ts","../src/partition-held-out.ts","../src/product-benchmark/export.ts","../src/product-benchmark/index.ts","../src/runtime-trajectory.ts","../src/action-policy.ts","../src/deploy-gate-layer.ts","../src/held-out-gate.ts","../src/hidden-criteria-grading.ts","../src/integrity/single-backend.ts","../src/intent-match-judge.ts","../src/judge-ensemble.ts","../src/judge-retry.ts","../src/judge-panel.ts","../src/keyword-coverage-judge.ts","../src/multi-layer-verifier.ts","../src/oracle.ts","../src/treatment-gate.ts","../src/anti-slop.ts","../src/eval-trace-store.ts","../src/integrity/preflight.ts","../src/model-seats.ts","../src/prompt-registry.ts","../src/steering-optimizer.ts"],"sourcesContent":["/**\n * Strong, generically-useful baseline ROLES — the top zone of an `AgentProfile`\n * before any domain layer. A product composes one of these with its own\n * environment description (its sandbox) and its domain guidance, which lives in\n * the product repo (not here): a profile is `<baseline role> + <environment> +\n * <domain sections>`. Domain strength is NOT generalized into the substrate —\n * it is lifted here only once ≥2 products genuinely reuse it.\n *\n * Three roles cover the common shapes:\n * - `engineerRole` — builds + verifies real artifacts in a sandbox. Distilled\n * from agent-runtime's `coderProfile` doctrine (minimal\n * correct change, run the checks, fix the root cause,\n * never weaken a test or hide an error).\n * - `researcherRole` — gathers from real sources and grounds every claim\n * (cite or mark inferred; never fabricate).\n * - `generalistRole` — a strong default: helpful, grounded, verify-before-assert.\n *\n * All three are verification-first and domain-agnostic. They describe HOW a\n * capable IC operates, not WHAT domain it works in.\n */\n\n/** Senior-IC engineer operating in a sandbox — produces real artifacts and\n * verifies them before declaring done. The shared operator foundation for any\n * file-producing, tool-using product agent. */\nexport const engineerRole: string = [\n 'You are a senior principal engineer — a 10x individual contributor — operating inside an isolated sandbox workspace with real tools (shell, filesystem, editors, test runners).',\n 'You do not behave like a chatbot that describes work. You DO the work: you produce the actual artifact in the workspace, then you verify it.',\n '',\n 'How you operate:',\n '- Deliver the smallest correct change that fully satisfies the goal. Bias to the real artifact (the file, the patch, the document), never a description of it.',\n '- Before declaring done, run the available checks (tests, typecheck, validators, a re-read of what you produced). If a check fails, fix the ROOT CAUSE — never weaken the check, never hide the error, never fake success.',\n '- External-boundary calls (shell, network, filesystem) can fail. Inspect the outcome before relying on it; surface failures loudly rather than proceeding on a bad value.',\n '- State outcomes faithfully: what you verified, what you skipped, what is still failing. \"Done\" means produced AND verified.',\n].join('\\n')\n\n/** Researcher who grounds every claim in real sources — gathers, cites, and\n * distinguishes verified fact from inference. */\nexport const researcherRole: string = [\n 'You are a principal research analyst operating inside a workspace with tools to read sources, search, and record findings.',\n 'Your output is only as good as its grounding. You gather from the real sources in front of you and you ground every material claim.',\n '',\n 'How you operate:',\n '- Read the actual sources before concluding. Do not answer from memory when a source is available to check.',\n '- Cite the source for every material claim; explicitly mark anything you infer rather than verify. Never fabricate a source, a quote, a number, or a citation.',\n '- Distinguish what the sources establish from what you are extrapolating, and say which is which.',\n '- When the sources are insufficient or contradictory, say so plainly rather than papering over the gap.',\n].join('\\n')\n\n/** Strong general-purpose default — helpful, grounded, verifies before asserting. */\nexport const generalistRole: string = [\n 'You are a capable, senior generalist assistant operating inside a workspace with real tools.',\n 'You are direct and grounded: you verify before you assert, and you produce real output rather than describing it.',\n '',\n 'How you operate:',\n '- Prefer doing over describing — when the workspace lets you produce the artifact, produce it.',\n '- Ground claims in what you can check; when you cannot check something, say so instead of guessing confidently.',\n '- Verify your output before declaring done, and report what you verified vs. what remains uncertain.',\n '- Ask the user only when a choice is genuinely theirs and you cannot resolve it from the task, the workspace, or sensible defaults.',\n].join('\\n')\n\n/** The named baseline roles, for selection by key (e.g. from a product config). */\nexport const BASELINE_ROLES = {\n engineer: engineerRole,\n researcher: researcherRole,\n generalist: generalistRole,\n} as const\n\nexport type BaselineRoleKey = keyof typeof BASELINE_ROLES\n","/**\n * Structured prompt profile — the system prompt as named, addressable sections\n * instead of one opaque blob. The self-improvement loop targets ONE evolvable\n * `domain` section at a time (via `applyDomainPatch`); the role, environment,\n * tool conventions, and skill roster stay fixed so a candidate diff is\n * attributable to a single section rather than a whole-prompt rewrite.\n *\n * `renderProfile` emits the prompt in a fixed five-zone order — role,\n * Environment, Tool conventions, Skills, Domain guidance — mirroring the layout\n * of Harvey LAB's `harness/system_prompt.md` (workspace root, read-only\n * documents, output dir, skills dir). `profileToSurface` is the bridge to the\n * loop's string `MutableSurface`: a profile renders to exactly the text a\n * candidate is scored on.\n *\n * Distinct from the canonical `AgentProfile` exported by\n * `@tangle-network/agent-interface`. This helper builds prompt content that can\n * be rendered into an agent-interface profile's `prompt.systemPrompt`.\n */\n\nimport { surfaceContentHash } from '../campaign/surface-identity'\nimport { BASELINE_ROLES, type BaselineRoleKey } from './baselines'\n\nexport {\n BASELINE_ROLES,\n type BaselineRoleKey,\n engineerRole,\n generalistRole,\n researcherRole,\n} from './baselines'\n\n/** A named, addressable region of the system prompt. `evolvable` marks whether\n * the self-improvement loop is allowed to patch its body; fixed scaffolding\n * (e.g. a compliance preamble) sets `evolvable: false`. */\nexport interface AgentProfileSection {\n id: string\n title: string\n body: string\n evolvable: boolean\n}\n\n/** A skill the agent can invoke. `triggers` are the phrases/conditions that\n * should activate it; `scriptsDir` points at its executable scripts when the\n * skill ships code (mirrors Harvey's `skills/<name>/scripts/`). */\nexport interface ProfileSkill {\n name: string\n description: string\n triggers: string[]\n scriptsDir?: string\n}\n\n/** The structured system prompt. The first four fields are fixed scaffolding;\n * `domain` is the evolvable surface the loop optimizes. */\nexport interface PromptProfile {\n role: string\n environment: string\n toolConventions: string\n skills: ProfileSkill[]\n domain: AgentProfileSection[]\n}\n\nfunction renderSkill(skill: ProfileSkill): string {\n const lines = [`### ${skill.name}`, skill.description]\n if (skill.triggers.length > 0) {\n lines.push(`Triggers: ${skill.triggers.join(', ')}`)\n }\n if (skill.scriptsDir !== undefined) {\n lines.push(`Scripts: ${skill.scriptsDir}`)\n }\n return lines.join('\\n')\n}\n\n/**\n * Emit the sectioned system prompt in fixed order: role text, then\n * `## Environment`, `## Tool conventions`, `## Skills` (each skill as\n * `### <name>` + description + triggers), `## Domain guidance` (each section as\n * `### <title>` + body). The order is load-bearing — the loop diffs rendered\n * text, and reordering would make every candidate look like a full rewrite.\n */\nexport function renderProfile(p: PromptProfile): string {\n const zones: string[] = [\n p.role.trim(),\n `## Environment\\n\\n${p.environment.trim()}`,\n `## Tool conventions\\n\\n${p.toolConventions.trim()}`,\n `## Skills\\n\\n${\n p.skills.length > 0 ? p.skills.map(renderSkill).join('\\n\\n') : '_No skills configured._'\n }`,\n `## Domain guidance\\n\\n${\n p.domain.length > 0\n ? p.domain.map((s) => `### ${s.title}\\n\\n${s.body.trim()}`).join('\\n\\n')\n : '_No domain guidance yet._'\n }`,\n ]\n return zones.join('\\n\\n')\n}\n\n/** The string `MutableSurface` the self-improvement loop scores — a profile\n * renders to exactly the text a candidate is graded on. */\nexport function profileToSurface(p: PromptProfile): string {\n return renderProfile(p)\n}\n\nconst STOCK_SKILLS: ProfileSkill[] = [\n {\n name: 'read-documents',\n description:\n 'Read every source document under the read-only documents directory before drafting.',\n triggers: [\n 'task references a source document',\n 'instructions cite an exhibit, filing, or input file',\n ],\n },\n {\n name: 'write-deliverable',\n description:\n 'Write deliverables to the output directory; use markdown for notes and the file-type skills for binary artifacts.',\n triggers: ['the task asks for a produced artifact', 'a deliverable is named in the brief'],\n },\n]\n\nconst ENVIRONMENT_PREAMBLE =\n 'You are an AI agent executing a task within a single workspace root.\\n\\n' +\n '- Workspace root: bash starts here. Use it for notes, scratch files, and intermediate work.\\n' +\n '- Documents directory: task source documents live here and are read-only — never write to them.\\n' +\n '- Output directory: write every deliverable here; relative write/edit paths route here automatically.\\n' +\n '- Skills directory: skill scripts live at <workspace>/skills/<name>/scripts/.'\n\nconst TOOL_CONVENTIONS_PREAMBLE =\n 'Use read to consume input files. Use write only for plain markdown (typically a response summary). ' +\n 'Use edit for incremental refinement of a file you already created. ' +\n 'External-boundary calls return typed outcomes — inspect success before using a value.'\n\n/**\n * The fixed-scaffolding baseline: a `role`/`environment`/`toolConventions`\n * profile with the stock skill roster and NO domain guidance. The\n * production profile is this plus shipped domain sections.\n */\nexport function baselineProfile(args: {\n role: string\n environment?: string\n toolConventions?: string\n skills?: ProfileSkill[]\n}): PromptProfile {\n return {\n role: args.role,\n environment: args.environment ?? ENVIRONMENT_PREAMBLE,\n toolConventions: args.toolConventions ?? TOOL_CONVENTIONS_PREAMBLE,\n skills: args.skills ?? STOCK_SKILLS,\n domain: [],\n }\n}\n\n/**\n * Baseline from one of the strong generic roles (`'engineer' | 'researcher' |\n * 'generalist'`) — the common case: pick a role foundation, optionally override\n * the environment to describe THIS product's sandbox, then layer domain via\n * `prodProfile`. Domain guidance stays in the product repo; this only supplies\n * the generically-useful role + stock scaffolding.\n */\nexport function baselineProfileFromRole(\n role: BaselineRoleKey,\n args: { environment?: string; toolConventions?: string; skills?: ProfileSkill[] } = {},\n): PromptProfile {\n return baselineProfile({ role: BASELINE_ROLES[role], ...args })\n}\n\n/** The production profile: the baseline scaffolding plus the domain sections\n * shipped after self-improvement. Differs from the baseline ONLY in `domain`\n * (and any skills the caller layered into the baseline) — the role,\n * environment, and tool conventions are carried through unchanged. */\nexport function prodProfile(\n baseline: PromptProfile,\n shipped: AgentProfileSection[],\n): PromptProfile {\n return { ...baseline, domain: [...baseline.domain, ...shipped] }\n}\n\n/**\n * Section-scoped edit — replace the body of ONE domain section by id, leaving\n * every other section byte-identical. This is how the loop targets a single\n * evolvable surface. Throws on an unknown section id (a patch that hits no\n * section is a silent no-op otherwise — fail loud). Throws when the targeted\n * section is `evolvable: false`.\n */\nexport function applyDomainPatch(\n p: PromptProfile,\n sectionId: string,\n newBody: string,\n): PromptProfile {\n const idx = p.domain.findIndex((s) => s.id === sectionId)\n if (idx === -1) {\n throw new Error(\n `applyDomainPatch: no domain section \"${sectionId}\" (have: ${\n p.domain.map((s) => s.id).join(', ') || '<none>'\n })`,\n )\n }\n const target = p.domain[idx]\n if (target === undefined) {\n throw new Error(`applyDomainPatch: domain section \"${sectionId}\" resolved to undefined`)\n }\n if (!target.evolvable) {\n throw new Error(`applyDomainPatch: domain section \"${sectionId}\" is not evolvable`)\n }\n const next = [...p.domain]\n next[idx] = { ...target, body: newBody }\n return { ...p, domain: next }\n}\n\n/**\n * Content hash of a single section — its loop identity. Delegates to the\n * campaign provenance `surfaceContentHash` (the same helper the loop's\n * provenance record uses for full surfaces), so a section hash is byte-for-byte\n * comparable with the `sha256:`-prefixed content hashes that record carries.\n * Two sections that render identically (same title + body) share a hash; the\n * `id` and `evolvable` flag are excluded — they are routing metadata, not\n * content.\n */\nexport function sectionHash(section: AgentProfileSection): string {\n return surfaceContentHash(JSON.stringify({ title: section.title, body: section.body }))\n}\n","/**\n * Verification-strategy family — the shared vocabulary for \"what certified\n * this result\", covering tasks with an answer key and tasks without one.\n *\n * Charter Wave 5 (docs/charter.md): an unsolved problem has no held-out\n * suite by definition, so the held-out suite must be ONE member of a\n * strategy family, not the family itself. This module carries the taxonomy,\n * the port shape, and the one protocol built directly on that port: the\n * blind two-arm statement-equivalence check. A checker is an injected\n * executable boundary that returns a typed outcome, so a consumer binds its\n * own kernel (a Lean toolchain, a metamorphic harness, a replication\n * runner) and this package never chooses one. Instruments, never methods.\n *\n * Full family doc, per-member failure modes in prose, and the BCWW pilot\n * worked example: docs/verification-strategies.md. How every executed\n * verdict lands in `DefaultVerdict` with a certification: docs/verdicts.md.\n *\n * Leaf module: no imports from this package. `src/verdict.ts` and\n * `src/rl/verifiable-reward.ts` both build on these types.\n */\n\n/**\n * One member of the verification-strategy family.\n *\n * Every member has a documented failure mode — the specific way it can\n * certify a wrong result. A consumer that reads a certification must weigh\n * the member's failure mode, not treat \"certified\" as one bit.\n *\n * - `'compile'` — typecheck / build / lint passed. Deterministic.\n * Failure mode: code that compiles is not code that is correct; the\n * weakest deterministic member.\n * - `'test'` — unit / integration / held-out suite pass-rate. Deterministic.\n * Failure mode: assumes an answer key exists; certifies nothing outside\n * the suite's coverage, and a stubbed integration reports green.\n * - `'schema'` — structured output validates. Deterministic.\n * Failure mode: shape is not meaning; a well-formed wrong answer passes.\n * - `'sandbox'` — sandbox execution exit code. Deterministic.\n * Failure mode: an exit code compresses the whole run to one bit; a\n * faked success exits 0.\n * - `'judge'` — LLM judge score. Probabilistic.\n * Failure mode: drifts across model versions and is Goodhart-gameable by\n * the graded policy.\n * - `'composite'` — weighted blend across members. Determinism inherited\n * from its members.\n * Failure mode: scalar collapse — the blend hides which member carried\n * the score and which failed.\n * - `'proof-kernel'` — a proof assistant's kernel accepted a formal proof.\n * Deterministic.\n * Failure mode: the formalization gap. The kernel certifies the formal\n * statement, never that the formal statement matches the informal claim;\n * a proved theorem about the wrong statement is a wrong result with a\n * valid certificate. Discharge it with the blind statement-equivalence\n * protocol (`runEquivalenceCheck` in this module).\n * - `'invariant'` — invariant / metamorphic properties held on the result.\n * Deterministic.\n * Failure mode: weak invariants pass everything. An invariant set earns\n * weight only through seeded-bug calibration — a mutation the set\n * provably rejects; an uncalibrated set is a rubber stamp.\n * - `'replication'` — an independent re-execution reproduced the result\n * from pinned inputs. Deterministic given the pins.\n * Failure mode: replication re-runs the method, so it catches\n * nondeterminism and environment drift, never a methodological error the\n * method itself carries.\n * - `'agreement'` — independently-derived results agree. Probabilistic.\n * Failure mode: the shared blind spot. Derivers that share training\n * corpora, priors, or the same misread of the source agree for the same\n * wrong reason; the blindness provenance of each arm is what the\n * certificate rests on.\n */\nexport type VerificationStrategySource =\n | 'compile'\n | 'test'\n | 'schema'\n | 'sandbox'\n | 'judge'\n | 'composite'\n | 'proof-kernel'\n | 'invariant'\n | 'replication'\n | 'agreement'\n\n/**\n * What a strategy member can honestly claim about its outcomes.\n *\n * `determinism: 'inherited'` exists only for `'composite'`: a blend takes\n * the class of its members. The reward axis stays binary\n * (`VerifiableReward.determinism`); this registry describes the family,\n * it never scores a run.\n */\nexport interface VerificationStrategyProfile {\n /** Determinism class a well-formed checker of this member can claim. */\n determinism: 'deterministic' | 'probabilistic' | 'inherited'\n /** The documented way this member certifies a wrong result. */\n failureMode: string\n}\n\n/**\n * The family registry. `Record` over the union keeps it exhaustive: adding\n * a member to `VerificationStrategySource` without a profile here fails to\n * compile. The failure mode travels with the taxonomy so a reader of a\n * certification can surface it without this package's docs at hand.\n */\nexport const VERIFICATION_STRATEGIES: Record<\n VerificationStrategySource,\n VerificationStrategyProfile\n> = {\n compile: {\n determinism: 'deterministic',\n failureMode: 'code that compiles is not code that is correct',\n },\n test: {\n determinism: 'deterministic',\n failureMode:\n 'assumes an answer key; certifies nothing outside suite coverage, and a stubbed integration reports green',\n },\n schema: {\n determinism: 'deterministic',\n failureMode: 'shape is not meaning; a well-formed wrong answer passes',\n },\n sandbox: {\n determinism: 'deterministic',\n failureMode: 'an exit code compresses the run to one bit; a faked success exits 0',\n },\n judge: {\n determinism: 'probabilistic',\n failureMode: 'drifts across model versions and is Goodhart-gameable by the graded policy',\n },\n composite: {\n determinism: 'inherited',\n failureMode: 'scalar collapse: the blend hides which member carried the score',\n },\n 'proof-kernel': {\n determinism: 'deterministic',\n failureMode:\n 'the formalization gap: the kernel certifies the formal statement, never that it matches the informal claim',\n },\n invariant: {\n determinism: 'deterministic',\n failureMode:\n 'weak invariants pass everything; a set uncalibrated by seeded bugs is a rubber stamp',\n },\n replication: {\n determinism: 'deterministic',\n failureMode:\n 're-runs the method, so it catches drift and nondeterminism, never an error the method itself carries',\n },\n agreement: {\n determinism: 'probabilistic',\n failureMode:\n 'the shared blind spot: derivers with common corpora or priors agree for the same wrong reason',\n },\n}\n\n/** Every family member, derived from the registry so it cannot drift. */\nexport const VERIFICATION_STRATEGY_SOURCES = Object.keys(\n VERIFICATION_STRATEGIES,\n) as readonly VerificationStrategySource[]\n\n/**\n * Exact identity of the thing that checked. \"lean4 4.33.0 with Mathlib\n * db584cd6d46c\" and \"lean4, some version\" are different certificates: the\n * first is re-runnable, the second is a story.\n */\nexport interface CheckerIdentity {\n /** Toolchain or model name, e.g. `'lean4'` or a judge model id. */\n name: string\n /** Exact version or snapshot, e.g. `'4.33.0'` or a model snapshot id. */\n version: string\n /**\n * Content pins the version alone does not capture, e.g.\n * `{ mathlib: 'db584cd6d46c' }`. Keyed by dependency name.\n */\n pins?: Record<string, string>\n}\n\n/**\n * Typed outcome of an external checker call. Callers MUST inspect\n * `succeeded` before touching `value`; a failed check keeps its full error\n * text instead of collapsing to null.\n */\nexport type CheckerOutcome<Result> =\n | { succeeded: true; value: Result }\n | { succeeded: false; error: string }\n\n/**\n * The port shape every strategy binds through: an injected executable\n * boundary. This package defines the port and refuses to ship any\n * implementation behind it — the consumer binds its own kernel, invariant\n * harness, replication runner, or judge, and the binding carries its own\n * identity and determinism claim.\n *\n * A checker that ran but could not decide returns\n * `{ succeeded: false, error }` with the reason; `succeeded: true` is\n * reserved for a discharged check.\n */\nexport interface StrategyChecker<Input, Result> {\n /** Which family member this checker discharges obligations for. */\n strategy: VerificationStrategySource\n identity: CheckerIdentity\n /** Determinism class this checker claims for its outcomes. */\n determinism: 'deterministic' | 'probabilistic'\n check(input: Input): Promise<CheckerOutcome<Result>>\n}\n\n// ── Blind statement-equivalence protocol ─────────────────────────────\n\n/**\n * Statement-equivalence protocol — the blind two-arm design as a typed\n * primitive.\n *\n * The problem it closes is the proof-kernel failure mode (the\n * formalization gap): a kernel certifies a formal statement, never that\n * the formal statement matches the informal claim. The protocol makes the\n * gap measurable: two arms derive the formal statement independently and\n * blind to each other, then a checker discharges the obligation that the\n * two statements are equivalent. A statement mismatch is a successful\n * outcome — it is the formalization gap made visible with a separating\n * witness in hand.\n *\n * The protocol is pure contract + record types + the asymmetry refusals.\n * Execution binds through the same `StrategyChecker` port as every other\n * strategy: the consumer injects its own kernel. The pilot record this\n * shape reproduces was assembled by hand for the BCWW (4.6) inequality;\n * docs/verification-strategies.md carries the worked example with artifact\n * paths. `equivalenceVerdict` (src/verdict.ts) lands a finished record in\n * the shared verdict spine.\n *\n * The refusals are the design. An arm that saw the other arm's statement,\n * or the outcome it feeds, did not independently derive anything — the\n * check is invalid, and this module throws rather than record it.\n */\n\n/**\n * The two-arm blind design. `arms: 2` and `blind: true` are literal types\n * on purpose: a wider design is a different protocol, not a parameter.\n */\nexport interface EquivalenceCheckSpec {\n /**\n * The strategy member whose obligation the check discharges — the pilot\n * used `'proof-kernel'`: the Lean kernel proved the two statements\n * equivalent. The bound checker must declare the same member.\n */\n source: VerificationStrategySource\n /**\n * Stable identity of the claim under verification: a path, digest, or\n * citation. Pilot: arXiv:1507.05650 inequality (4.6) plus the\n * five-atom counterexample record.\n */\n artifact: string\n /** Exactly two independent arms. An N-arm design is not this protocol. */\n arms: 2\n /**\n * Blind derivation is the point: a non-blind run is not a weaker check,\n * it is no check. `false` is unrepresentable here and refused at runtime\n * for untyped callers.\n */\n blind: true\n}\n\n/** A validated, frozen spec. Produced only by `defineEquivalenceCheck`. */\nexport interface EquivalenceCheckDefinition {\n readonly spec: Readonly<EquivalenceCheckSpec>\n}\n\n/** One arm's committed statement plus the provenance the record rests on. */\nexport interface EquivalenceArm {\n armId: string\n /** The committed formal statement text (pilot: the arm's `Statement.lean` source). */\n statement: string\n /**\n * What this arm derived the statement from. Pilot arm A: the paper's\n * LaTeX source; pilot arm B: the campaign's artifacts. The two arms\n * SHOULD derive from different renderings of the claim — that is what\n * makes agreement informative.\n */\n derivedFrom: string\n /**\n * The blindness declaration. Both flags must be `true`; a `false` value\n * is refused loudly, because recording a non-blind arm would launder an\n * invalid check into a valid-looking record.\n */\n blindness: {\n /** This arm never saw any other arm's statement before committing its own. */\n toOtherArms: boolean\n /** This arm never saw the verification outcome before committing. */\n toOutcome: boolean\n }\n}\n\nexport type EquivalenceObligationStatus =\n | 'proved'\n | 'refuted-with-separating-witness'\n | 'unresolved'\n\n/**\n * The discharged (or undischarged) equivalence obligation.\n *\n * Field presence is status-dependent and enforced by\n * `buildEquivalenceRecord`:\n * - `'proved'` requires `evidenceDigest` and forbids `separatingWitness`.\n * - `'refuted-with-separating-witness'` requires both the witness and\n * `evidenceDigest`.\n * - `'unresolved'` requires `unresolvedReason` and forbids the witness —\n * an undischarged obligation keeps its diagnostic instead of faking\n * either verdict.\n */\nexport interface EquivalenceObligation {\n status: EquivalenceObligationStatus\n /** The input on which the two statements provably disagree. */\n separatingWitness?: string\n /** Why the obligation could not be discharged (checker error text, coverage limit). */\n unresolvedReason?: string\n /** The checker that ran (or failed to run) the obligation. */\n checker: CheckerIdentity\n /** Digest of the checker's evidence artifact (pilot: the kernel-checked `Check.lean` run). */\n evidenceDigest?: string\n}\n\n/** The record the protocol produces — the by-hand pilot record, typed. */\nexport interface EquivalenceRecord {\n spec: Readonly<EquivalenceCheckSpec>\n arms: readonly [EquivalenceArm, EquivalenceArm]\n obligation: EquivalenceObligation\n}\n\n/** Input the bound checker receives: the artifact identity and both committed statements. */\nexport interface EquivalenceCheckerInput {\n artifact: string\n statements: readonly [string, string]\n}\n\n/**\n * What a checker that RAN must return. `'unresolved'` is deliberately not\n * a checker result: a checker that could not decide returns\n * `{ succeeded: false, error }` through the port, and the protocol records\n * the unresolved obligation with that reason.\n */\nexport interface EquivalenceCheckerResult {\n status: 'proved' | 'refuted-with-separating-witness'\n /** Required when `status` is refuted. */\n separatingWitness?: string\n evidenceDigest: string\n}\n\n/** An equivalence checker is a `StrategyChecker` — same port as every strategy. */\nexport type EquivalenceChecker = StrategyChecker<EquivalenceCheckerInput, EquivalenceCheckerResult>\n\n/** A refused equivalence check. `code` names the exact refusal for programmatic handling. */\nexport class EquivalenceProtocolError extends Error {\n readonly code:\n | 'arm-count'\n | 'not-blind'\n | 'arm-saw-other'\n | 'arm-saw-outcome'\n | 'duplicate-arm-id'\n | 'empty-field'\n | 'unknown-source'\n | 'witness-missing'\n | 'witness-on-proved'\n | 'witness-on-unresolved'\n | 'reason-missing'\n | 'evidence-missing'\n | 'checker-strategy-mismatch'\n\n constructor(code: EquivalenceProtocolError['code'], message: string) {\n super(message)\n this.name = 'EquivalenceProtocolError'\n this.code = code\n }\n}\n\n/**\n * Validate and freeze a two-arm blind equivalence check spec.\n *\n * The literal types already refuse a wide design at compile time; the\n * runtime checks hold the same line for untyped callers. There is no\n * escape hatch: `arms: 3` or `blind: false` throws, never downgrades.\n */\nexport function defineEquivalenceCheck(spec: EquivalenceCheckSpec): EquivalenceCheckDefinition {\n if (spec.arms !== 2) {\n throw new EquivalenceProtocolError(\n 'arm-count',\n `equivalence check requires exactly 2 arms, received ${String(spec.arms)}`,\n )\n }\n if (spec.blind !== true) {\n throw new EquivalenceProtocolError(\n 'not-blind',\n 'equivalence check requires blind: true — a non-blind run is not a weaker check, it is no check',\n )\n }\n if (typeof spec.artifact !== 'string' || spec.artifact.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n 'spec.artifact must identify the claim under verification',\n )\n }\n if (!VERIFICATION_STRATEGY_SOURCES.includes(spec.source)) {\n throw new EquivalenceProtocolError(\n 'unknown-source',\n `spec.source '${String(spec.source)}' is not a verification-strategy member`,\n )\n }\n return Object.freeze({ spec: Object.freeze({ ...spec }) })\n}\n\n/**\n * Assemble the equivalence record, refusing every asymmetry.\n *\n * Refusals (each throws `EquivalenceProtocolError`):\n * - an arm whose `blindness.toOtherArms` is false — it saw the other\n * statement, so nothing was independently derived;\n * - an arm whose `blindness.toOutcome` is false — it could steer its\n * statement toward (or away from) the known result;\n * - duplicate arm ids, empty statements, empty derivations;\n * - an obligation whose fields contradict its status (see\n * `EquivalenceObligation`).\n */\nexport function buildEquivalenceRecord(\n definition: EquivalenceCheckDefinition,\n arms: readonly [EquivalenceArm, EquivalenceArm],\n obligation: EquivalenceObligation,\n): EquivalenceRecord {\n assertArms(arms)\n assertObligation(obligation)\n return Object.freeze({\n spec: definition.spec,\n arms: Object.freeze([Object.freeze({ ...arms[0] }), Object.freeze({ ...arms[1] })] as const),\n obligation: Object.freeze({ ...obligation }),\n })\n}\n\n/**\n * Discharge the obligation through an injected checker and return the\n * record.\n *\n * Order matters: every arm refusal fires BEFORE the checker runs — an\n * invalid check must not spend. A checker whose `strategy` differs from\n * `spec.source` is refused for the same reason: a judge cannot silently\n * discharge a proof-kernel obligation.\n *\n * A checker failure (`succeeded: false`) is not thrown: it becomes an\n * `'unresolved'` obligation carrying the full error text, which is the\n * honest record of an undischarged check.\n */\nexport async function runEquivalenceCheck(\n definition: EquivalenceCheckDefinition,\n arms: readonly [EquivalenceArm, EquivalenceArm],\n checker: EquivalenceChecker,\n): Promise<EquivalenceRecord> {\n assertArms(arms)\n if (checker.strategy !== definition.spec.source) {\n throw new EquivalenceProtocolError(\n 'checker-strategy-mismatch',\n `spec.source is '${definition.spec.source}' but the bound checker declares '${checker.strategy}'`,\n )\n }\n const outcome = await checker.check({\n artifact: definition.spec.artifact,\n statements: [arms[0].statement, arms[1].statement],\n })\n if (!outcome.succeeded) {\n return buildEquivalenceRecord(definition, arms, {\n status: 'unresolved',\n unresolvedReason: outcome.error,\n checker: checker.identity,\n })\n }\n const { status, separatingWitness, evidenceDigest } = outcome.value\n return buildEquivalenceRecord(definition, arms, {\n status,\n ...(separatingWitness === undefined ? {} : { separatingWitness }),\n checker: checker.identity,\n evidenceDigest,\n })\n}\n\nfunction assertArms(arms: readonly [EquivalenceArm, EquivalenceArm]): void {\n if (arms.length !== 2) {\n throw new EquivalenceProtocolError(\n 'arm-count',\n `equivalence record requires exactly 2 arms, received ${arms.length}`,\n )\n }\n if (arms[0].armId === arms[1].armId) {\n throw new EquivalenceProtocolError(\n 'duplicate-arm-id',\n `both arms declare armId '${arms[0].armId}' — two labels for one derivation is one arm`,\n )\n }\n for (const arm of arms) {\n if (arm.statement.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n `arm '${arm.armId}' committed an empty statement`,\n )\n }\n if (arm.derivedFrom.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n `arm '${arm.armId}' declares no derivation provenance`,\n )\n }\n if (arm.blindness.toOtherArms !== true) {\n throw new EquivalenceProtocolError(\n 'arm-saw-other',\n `arm '${arm.armId}' saw another arm's statement — the derivation is not independent and the check is invalid`,\n )\n }\n if (arm.blindness.toOutcome !== true) {\n throw new EquivalenceProtocolError(\n 'arm-saw-outcome',\n `arm '${arm.armId}' saw the outcome before committing — the check is invalid`,\n )\n }\n }\n}\n\nfunction assertObligation(obligation: EquivalenceObligation): void {\n const { status, separatingWitness, unresolvedReason, evidenceDigest } = obligation\n if (status === 'refuted-with-separating-witness') {\n if (typeof separatingWitness !== 'string' || separatingWitness.trim() === '') {\n throw new EquivalenceProtocolError(\n 'witness-missing',\n 'a refuted equivalence must carry the separating witness — a refutation without one is an assertion',\n )\n }\n if (typeof evidenceDigest !== 'string' || evidenceDigest.trim() === '') {\n throw new EquivalenceProtocolError(\n 'evidence-missing',\n 'a refuted equivalence must carry its evidence digest',\n )\n }\n return\n }\n if (status === 'proved') {\n if (separatingWitness !== undefined) {\n throw new EquivalenceProtocolError(\n 'witness-on-proved',\n 'a proved equivalence cannot carry a separating witness — the two claims contradict',\n )\n }\n if (typeof evidenceDigest !== 'string' || evidenceDigest.trim() === '') {\n throw new EquivalenceProtocolError(\n 'evidence-missing',\n 'a proved equivalence must carry its evidence digest',\n )\n }\n return\n }\n // status === 'unresolved'\n if (separatingWitness !== undefined) {\n throw new EquivalenceProtocolError(\n 'witness-on-unresolved',\n 'an unresolved obligation cannot carry a separating witness — a witness in hand is a refutation',\n )\n }\n if (typeof unresolvedReason !== 'string' || unresolvedReason.trim() === '') {\n throw new EquivalenceProtocolError(\n 'reason-missing',\n \"an unresolved obligation must say why — 'unresolved' with no reason erases the diagnostic\",\n )\n }\n}\n","/**\n * BudgetGuard — enforces token / wall-clock / call / $ caps, records\n * a ledger entry on every decrement, emits `budget_breach` + throws\n * `BudgetBreachError` when a cap is hit.\n *\n * Wraps a TraceEmitter. The emitter persists ledger entries + breach\n * events so the classifier, pipelines, and reports can all read\n * budget state from the trace corpus — no separate accounting.\n */\n\nimport { AgentEvalError } from './errors'\nimport type { TraceEmitter } from './trace/emitter'\nimport type { BudgetSpec } from './trace/schema'\n\nexport class BudgetBreachError extends AgentEvalError {\n constructor(\n public dimension: keyof BudgetSpec,\n public limit: number,\n public attempted: number,\n ) {\n super('verification', `budget breach on ${dimension}: attempted ${attempted} vs limit ${limit}`)\n }\n}\n\nexport class BudgetGuard {\n private consumed: Record<keyof BudgetSpec, number> = { tokens: 0, wallMs: 0, calls: 0, usd: 0 }\n private emitter: TraceEmitter\n private budget: BudgetSpec\n private startedAt: number\n\n constructor(emitter: TraceEmitter, budget: BudgetSpec, now: () => number = () => Date.now()) {\n this.emitter = emitter\n this.budget = budget\n this.startedAt = now()\n }\n\n /** Record consumption. Throws `BudgetBreachError` if any dimension exceeds its cap. */\n async charge(delta: Partial<Record<keyof BudgetSpec, number>>, spanId?: string): Promise<void> {\n for (const [dim, value] of Object.entries(delta) as Array<[keyof BudgetSpec, number]>) {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`BudgetGuard.charge: non-finite or negative ${dim}=${value}`)\n }\n this.consumed[dim] += value\n const limit = this.budget[dim]\n const consumed = this.consumed[dim]\n const remaining = limit === undefined ? Infinity : limit - consumed\n const breached = limit !== undefined && consumed > limit\n if (limit !== undefined) {\n await this.emitter.recordBudget({\n dimension: dim,\n limit,\n consumed,\n remaining,\n breached,\n spanId,\n })\n }\n if (breached) {\n throw new BudgetBreachError(dim, limit!, consumed)\n }\n }\n }\n\n /** Convenience: advance wall-clock budget based on elapsed wall time. */\n async tickWall(nowMs: number, spanId?: string): Promise<void> {\n const elapsed = nowMs - this.startedAt\n const already = this.consumed.wallMs\n const delta = Math.max(0, elapsed - already)\n if (delta > 0) await this.charge({ wallMs: delta }, spanId)\n }\n\n get state(): Record<keyof BudgetSpec, number> {\n return { ...this.consumed }\n }\n}\n","import type { AnalystFinding, AnalystRunResult } from './analyst/types'\nimport type { ControlEvalResult, ControlRunResult, ControlStep } from './control-runtime'\nimport type { DatasetScenario, DatasetSplit } from './dataset'\nimport {\n type AnalystReviewDecision,\n analystFindingDigest,\n analystRunDigest,\n assertUniqueFindingIds,\n completedAnalystReviewQuality,\n readAnalystReview,\n snapshotAnalystRun,\n validateAnalystReviewDecisions,\n} from './feedback-trajectory-review'\nimport { canonicalString, compareCodeUnits } from './ledger-core/canonical'\n\nexport type {\n AnalystFindingDigest,\n AnalystMissedIssue,\n AnalystReviewCounts,\n AnalystReviewDecision,\n AnalystReviewQuality,\n AnalystReviewSource,\n AnalystRunDigest,\n} from './feedback-trajectory-review'\nexport { analystFindingDigest, analystRunDigest } from './feedback-trajectory-review'\n\nexport type FeedbackArtifactType =\n | 'text'\n | 'code'\n | 'plan'\n | 'research'\n | 'action'\n | 'ui'\n | 'decision'\n | 'data'\n | 'other'\n\nexport type FeedbackLabelSource = 'user' | 'judge' | 'environment' | 'metric' | 'policy' | 'system'\n\nexport type FeedbackLabelKind =\n | 'approve'\n | 'reject'\n | 'select'\n | 'edit'\n | 'rank'\n | 'rate'\n | 'comment'\n | 'metric_outcome'\n | 'policy_block'\n | 'revision_request'\n\nexport type FeedbackSeverity = 'info' | 'warning' | 'error' | 'critical'\n\nexport interface FeedbackTask {\n intent: string\n context?: unknown\n}\n\nexport interface ProposedSideEffect {\n type: string\n risk?: 'low' | 'medium' | 'high'\n costUsd?: number\n externalSideEffect?: boolean\n requiresApproval?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackLabel {\n id?: string\n source: FeedbackLabelSource\n kind: FeedbackLabelKind\n value: unknown\n reason?: string\n severity?: FeedbackSeverity\n createdAt: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackAttempt {\n id: string\n stepIndex: number\n artifactType: FeedbackArtifactType\n artifact: unknown\n options?: unknown[]\n proposedAction?: ProposedSideEffect\n evals?: ControlEvalResult[]\n feedback?: FeedbackLabel[]\n createdAt: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackOutcome {\n success?: boolean\n score?: number\n metrics?: Record<string, number>\n costUsd?: number\n detail?: string\n observedAt?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTrajectory {\n id: string\n projectId?: string\n scenarioId?: string\n task: FeedbackTask\n attempts: FeedbackAttempt[]\n labels: FeedbackLabel[]\n outcome?: FeedbackOutcome\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt: string\n updatedAt?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTrajectoryStore {\n save(trajectory: FeedbackTrajectory): Promise<void>\n get(id: string): Promise<FeedbackTrajectory | null>\n list(filter?: FeedbackTrajectoryFilter): Promise<FeedbackTrajectory[]>\n appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory>\n appendLabel(id: string, label: FeedbackLabel, attemptId?: string): Promise<FeedbackTrajectory>\n}\n\nexport interface FeedbackTrajectoryFilter {\n projectId?: string\n scenarioId?: string\n split?: DatasetSplit\n tag?: [string, string]\n}\n\nexport interface FeedbackSplitPolicy {\n trainPct?: number\n devPct?: number\n testPct?: number\n holdoutPct?: number\n}\n\nexport interface PreferenceMemoryEntry {\n instruction: string\n rationale: string\n weight: number\n sourceTrajectoryId: string\n sourceLabelId?: string\n category?: string\n}\n\nexport interface FeedbackOptimizerRow {\n scenarioId: string\n trajectoryId: string\n labelKinds: FeedbackLabelKind[]\n score?: number\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackReplayResult {\n trajectoryId: string\n pass: boolean\n score?: number\n labels: FeedbackLabel[]\n outcome?: FeedbackOutcome\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackReplayAdapter {\n replay(\n trajectory: FeedbackTrajectory,\n ):\n | Promise<Omit<FeedbackReplayResult, 'trajectoryId'>>\n | Omit<FeedbackReplayResult, 'trajectoryId'>\n}\n\nexport interface AnalystFeedbackTrajectoryOptions {\n task: FeedbackTask\n labels?: readonly FeedbackLabel[]\n reviewRequests?: readonly AnalystReviewRequest[]\n reviewDecisions?: readonly AnalystReviewDecision[]\n outcome?: FeedbackOutcome\n id?: string\n projectId?: string\n scenarioId?: string\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt?: string\n trace?: {\n source?: string\n traceIds?: readonly string[]\n artifactUri?: string\n }\n metadata?: Record<string, unknown>\n}\n\nexport interface AnalystReviewRequest {\n id: string\n runId: string\n runDigest: `sha256:${string}`\n findingId: string\n findingDigest: `sha256:${string}`\n analystId: string\n area: string\n claim: string\n evidence: AnalystFinding['evidence_refs']\n recommendedAction?: string\n validationPlan?: string\n severity: FeedbackSeverity\n confidence: number\n createdAt: string\n}\n\nconst DEFAULT_SPLIT_POLICY: Required<FeedbackSplitPolicy> = {\n trainPct: 70,\n devPct: 15,\n testPct: 10,\n holdoutPct: 5,\n}\n\nexport class InMemoryFeedbackTrajectoryStore implements FeedbackTrajectoryStore {\n private readonly trajectories = new Map<string, FeedbackTrajectory>()\n\n async save(trajectory: FeedbackTrajectory): Promise<void> {\n this.trajectories.set(trajectory.id, cloneTrajectory(trajectory))\n }\n\n async get(id: string): Promise<FeedbackTrajectory | null> {\n const trajectory = this.trajectories.get(id)\n return trajectory ? cloneTrajectory(trajectory) : null\n }\n\n async list(filter: FeedbackTrajectoryFilter = {}): Promise<FeedbackTrajectory[]> {\n return [...this.trajectories.values()]\n .filter((trajectory) => matchesFilter(trajectory, filter))\n .map(cloneTrajectory)\n }\n\n async appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory> {\n const trajectory = this.trajectories.get(id)\n if (!trajectory)\n throw new Error(`FeedbackTrajectoryStore.appendAttempt: unknown trajectory \"${id}\"`)\n const next = cloneTrajectory({\n ...trajectory,\n attempts: [...trajectory.attempts, attempt],\n updatedAt: attempt.createdAt,\n })\n this.trajectories.set(id, next)\n return cloneTrajectory(next)\n }\n\n async appendLabel(\n id: string,\n label: FeedbackLabel,\n attemptId?: string,\n ): Promise<FeedbackTrajectory> {\n const trajectory = this.trajectories.get(id)\n if (!trajectory)\n throw new Error(`FeedbackTrajectoryStore.appendLabel: unknown trajectory \"${id}\"`)\n const attempts = attemptId\n ? trajectory.attempts.map((attempt) =>\n attempt.id === attemptId\n ? { ...attempt, feedback: [...(attempt.feedback ?? []), label] }\n : attempt,\n )\n : trajectory.attempts\n const next = cloneTrajectory({\n ...trajectory,\n attempts,\n labels: attemptId ? trajectory.labels : [...trajectory.labels, label],\n updatedAt: label.createdAt,\n })\n this.trajectories.set(id, next)\n return cloneTrajectory(next)\n }\n}\n\nexport class FileSystemFeedbackTrajectoryStore implements FeedbackTrajectoryStore {\n private readonly dir: string\n private readonly memory = new InMemoryFeedbackTrajectoryStore()\n private loaded = false\n\n constructor(options: { dir: string }) {\n this.dir = options.dir\n }\n\n async save(trajectory: FeedbackTrajectory): Promise<void> {\n await this.load()\n await this.memory.save(trajectory)\n await this.append({ op: 'save', trajectory })\n }\n\n async get(id: string): Promise<FeedbackTrajectory | null> {\n await this.load()\n return this.memory.get(id)\n }\n\n async list(filter: FeedbackTrajectoryFilter = {}): Promise<FeedbackTrajectory[]> {\n await this.load()\n return this.memory.list(filter)\n }\n\n async appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory> {\n await this.load()\n const next = await this.memory.appendAttempt(id, attempt)\n await this.append({ op: 'appendAttempt', id, attempt })\n return next\n }\n\n async appendLabel(\n id: string,\n label: FeedbackLabel,\n attemptId?: string,\n ): Promise<FeedbackTrajectory> {\n await this.load()\n const next = await this.memory.appendLabel(id, label, attemptId)\n await this.append({ op: 'appendLabel', id, label, attemptId })\n return next\n }\n\n private async append(record: unknown): Promise<void> {\n const { appendFile, mkdir } = await import('node:fs/promises')\n const { join } = await import('node:path')\n await mkdir(this.dir, { recursive: true })\n await appendFile(\n join(this.dir, 'feedback-trajectories.ndjson'),\n `${JSON.stringify(record)}\\n`,\n 'utf8',\n )\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return\n const { readFile } = await import('node:fs/promises')\n const { join } = await import('node:path')\n const file = join(this.dir, 'feedback-trajectories.ndjson')\n try {\n const raw = await readFile(file, 'utf8')\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n try {\n const record = JSON.parse(line) as\n | { op: 'save'; trajectory: FeedbackTrajectory }\n | { op: 'appendAttempt'; id: string; attempt: FeedbackAttempt }\n | { op: 'appendLabel'; id: string; label: FeedbackLabel; attemptId?: string }\n if (record.op === 'save') await this.memory.save(record.trajectory)\n if (record.op === 'appendAttempt')\n await this.memory.appendAttempt(record.id, record.attempt)\n if (record.op === 'appendLabel')\n await this.memory.appendLabel(record.id, record.label, record.attemptId)\n } catch {\n /* corrupt records are skipped so one bad line does not discard the corpus */\n }\n }\n } catch {\n /* first run */\n }\n this.loaded = true\n }\n}\n\nexport function createFeedbackTrajectory(input: {\n id?: string\n projectId?: string\n scenarioId?: string\n task: FeedbackTask\n attempts?: FeedbackAttempt[]\n labels?: FeedbackLabel[]\n outcome?: FeedbackOutcome\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt?: string\n metadata?: Record<string, unknown>\n}): FeedbackTrajectory {\n const createdAt = input.createdAt ?? new Date().toISOString()\n const id =\n input.id ??\n `ft_${stableHash(`${input.projectId ?? ''}|${input.scenarioId ?? ''}|${input.task.intent}|${createdAt}`).toString(16)}`\n return {\n id,\n projectId: input.projectId,\n scenarioId: input.scenarioId,\n task: input.task,\n attempts: input.attempts ?? [],\n labels: input.labels ?? [],\n outcome: input.outcome,\n split: input.split,\n tags: input.tags,\n createdAt,\n metadata: input.metadata,\n }\n}\n\n/** Preserve a trace-analysis run for review, whether or not review is complete. */\nexport function analystRunToFeedbackTrajectory(\n run: AnalystRunResult,\n options: AnalystFeedbackTrajectoryOptions,\n): FeedbackTrajectory {\n const archivedRun = snapshotAnalystRun(run, `analyst run \"${run.run_id}\"`)\n const runDigest = analystRunDigest(archivedRun)\n const findings = archivedRun.findings\n const findingIds = findings.map((finding) => finding.finding_id)\n assertUniqueFindingIds(findingIds)\n const analystIds = [\n ...new Set([\n ...findings.map((finding) => finding.analyst_id),\n ...archivedRun.per_analyst.map((summary) => summary.analyst_id),\n ]),\n ]\n const reviewDecisions = validateAnalystReviewDecisions({\n runId: archivedRun.run_id,\n runDigest,\n findings,\n analystIds,\n decisions: options.reviewDecisions ?? [],\n })\n const reviewRequests =\n options.reviewRequests === undefined\n ? undefined\n : validateAnalystReviewRequests(archivedRun, options.reviewRequests)\n const createdAt = options.createdAt ?? archivedRun.started_at\n const knownCostUsd = archivedRun.total_cost_usd\n const capturedCost =\n archivedRun.total_cost_provenance?.kind === 'uncaptured'\n ? undefined\n : archivedRun.total_cost_usd\n return createFeedbackTrajectory({\n id: options.id,\n projectId: options.projectId,\n scenarioId: options.scenarioId,\n task: options.task,\n attempts: [\n {\n id: `analysis:${archivedRun.run_id}`,\n stepIndex: 0,\n artifactType: 'research',\n artifact: {\n type: 'analyst-run',\n analystRunId: archivedRun.run_id,\n runDigest,\n correlationId: archivedRun.correlation_id,\n analystIds,\n findings,\n ...('execution_plan' in archivedRun ? { executionPlan: archivedRun.execution_plan } : {}),\n ...('completion' in archivedRun ? { completion: archivedRun.completion } : {}),\n },\n createdAt,\n metadata: {\n perAnalyst: archivedRun.per_analyst,\n trace: options.trace,\n reviewRequests,\n },\n },\n ],\n labels: [...(options.labels ?? [])],\n outcome: options.outcome\n ? {\n ...options.outcome,\n costUsd: options.outcome.costUsd ?? capturedCost,\n }\n : capturedCost === undefined\n ? undefined\n : { costUsd: capturedCost, observedAt: archivedRun.ended_at },\n split: options.split,\n tags: options.tags,\n createdAt,\n metadata: {\n ...options.metadata,\n analysis: {\n kind: 'analyst-run',\n runId: archivedRun.run_id,\n runDigest,\n startedAt: archivedRun.started_at,\n endedAt: archivedRun.ended_at,\n reviewDecisions,\n costProvenance: archivedRun.total_cost_provenance,\n knownCostUsd,\n },\n },\n })\n}\n\n/** Convert one immutable analyst run into revision requests for an independent reviewer. */\nexport function analystRunToReviewRequests(\n run: AnalystRunResult,\n options: { createdAt?: string } = {},\n): AnalystReviewRequest[] {\n const archivedRun = snapshotAnalystRun(run, `analyst run \"${run.run_id}\"`)\n const runDigest = analystRunDigest(archivedRun)\n const createdAt = options.createdAt ?? new Date().toISOString()\n return archivedRun.findings.map((finding) => ({\n id: analystReviewRequestId(runDigest, finding.finding_id),\n runId: archivedRun.run_id,\n runDigest,\n findingId: finding.finding_id,\n findingDigest: analystFindingDigest(finding),\n analystId: finding.analyst_id,\n area: finding.area,\n claim: finding.claim,\n evidence: finding.evidence_refs,\n recommendedAction: finding.recommended_action,\n validationPlan: finding.validation_plan,\n severity: feedbackSeverityFromFinding(finding),\n confidence: finding.confidence,\n createdAt,\n }))\n}\n\nfunction validateAnalystReviewRequests(\n run: AnalystRunResult,\n requests: readonly AnalystReviewRequest[],\n): AnalystReviewRequest[] {\n const runDigest = analystRunDigest(run)\n const findingsById = new Map(run.findings.map((finding) => [finding.finding_id, finding]))\n const seenFindingIds = new Set<string>()\n return requests.map((request, index) => {\n if (request.runId !== run.run_id) {\n throw new TypeError(`analyst review request ${index} run id mismatch`)\n }\n if (request.runDigest !== runDigest) {\n throw new TypeError(`analyst review request ${index} run digest mismatch`)\n }\n const finding = findingsById.get(request.findingId)\n if (!finding) {\n throw new TypeError(\n `analyst review request ${index} references unknown finding id \"${request.findingId}\"`,\n )\n }\n if (seenFindingIds.has(request.findingId)) {\n throw new TypeError(`duplicate analyst review request for finding id \"${request.findingId}\"`)\n }\n seenFindingIds.add(request.findingId)\n if (request.findingDigest !== analystFindingDigest(finding)) {\n throw new TypeError(`analyst review request ${index} finding digest mismatch`)\n }\n if (request.id !== analystReviewRequestId(runDigest, request.findingId)) {\n throw new TypeError(`analyst review request ${index} id mismatch`)\n }\n return request\n })\n}\n\nfunction analystReviewRequestId(runDigest: `sha256:${string}`, findingId: string): string {\n return `analyst:${runDigest}:${findingId}`\n}\n\nexport function assignFeedbackSplit(\n trajectory: Pick<FeedbackTrajectory, 'id' | 'projectId' | 'scenarioId' | 'task'>,\n policy: FeedbackSplitPolicy = {},\n): DatasetSplit {\n const split = { ...DEFAULT_SPLIT_POLICY, ...policy }\n const total = split.trainPct + split.devPct + split.testPct + split.holdoutPct\n if (total <= 0) throw new Error('assignFeedbackSplit: split percentages must sum above zero')\n const bucket =\n stableHash(\n `${trajectory.projectId ?? ''}|${trajectory.scenarioId ?? ''}|${trajectory.id}|${trajectory.task.intent}`,\n ) % total\n if (bucket < split.trainPct) return 'train'\n if (bucket < split.trainPct + split.devPct) return 'dev'\n if (bucket < split.trainPct + split.devPct + split.testPct) return 'test'\n return 'holdout'\n}\n\nexport function withAssignedFeedbackSplit(\n trajectory: FeedbackTrajectory,\n policy?: FeedbackSplitPolicy,\n): FeedbackTrajectory {\n return {\n ...trajectory,\n split: trajectory.split ?? assignFeedbackSplit(trajectory, policy),\n }\n}\n\nexport function feedbackTrajectoryToDatasetScenario(\n trajectory: FeedbackTrajectory,\n): DatasetScenario {\n const withSplit = withAssignedFeedbackSplit(trajectory)\n return {\n id: withSplit.scenarioId ?? withSplit.id,\n split: withSplit.split,\n payload: withSplit,\n tags: {\n ...(withSplit.projectId ? { projectId: withSplit.projectId } : {}),\n ...(withSplit.tags ?? {}),\n source: 'feedback-trajectory',\n },\n }\n}\n\nexport function feedbackTrajectoriesToDatasetScenarios(\n trajectories: FeedbackTrajectory[],\n): DatasetScenario[] {\n return trajectories.map(feedbackTrajectoryToDatasetScenario)\n}\n\nexport function feedbackTrajectoryToOptimizerRow(\n trajectory: FeedbackTrajectory,\n): FeedbackOptimizerRow {\n const labels = allLabels(trajectory)\n const analystReview = readAnalystReview(trajectory)\n const analystQuality = analystReview ? completedAnalystReviewQuality(analystReview) : undefined\n const reviewLabelKinds = analystReview\n ? analystReview.reviewDecisions.map((decision): FeedbackLabelKind => {\n if (decision.verdict === 'rejected') return 'reject'\n if (decision.verdict === 'completeness_assessed' && decision.missedIssues.length > 0) {\n return 'revision_request'\n }\n return 'approve'\n })\n : []\n return {\n scenarioId: trajectory.scenarioId ?? trajectory.id,\n trajectoryId: trajectory.id,\n labelKinds: [...new Set([...labels.map((label) => label.kind), ...reviewLabelKinds])],\n score: analystQuality?.f1 ?? trajectory.outcome?.score ?? scoreFromLabels(labels),\n metadata: {\n projectId: trajectory.projectId,\n split: trajectory.split,\n intent: trajectory.task.intent,\n attempts: trajectory.attempts.length,\n outcome: trajectory.outcome,\n labels,\n ...(analystReview\n ? {\n analystReview: {\n findingIds: analystReview.findingIds,\n findingDigests: analystReview.findings.map((finding) => ({\n findingId: finding.finding_id,\n findingDigest: analystFindingDigest(finding),\n })),\n decisions: analystReview.reviewDecisions,\n precision: analystQuality?.precision,\n recall: analystQuality?.recall,\n f1: analystQuality?.f1,\n counts: analystQuality?.counts,\n },\n }\n : {}),\n },\n }\n}\n\nexport function feedbackTrajectoriesToOptimizerRows(\n trajectories: FeedbackTrajectory[],\n): FeedbackOptimizerRow[] {\n return trajectories.map(feedbackTrajectoryToOptimizerRow)\n}\n\nexport async function replayFeedbackTrajectory(\n trajectory: FeedbackTrajectory,\n adapter: FeedbackReplayAdapter,\n): Promise<FeedbackReplayResult> {\n try {\n const result = await adapter.replay(trajectory)\n return {\n trajectoryId: trajectory.id,\n ...result,\n }\n } catch (err) {\n const createdAt = new Date().toISOString()\n const message = err instanceof Error ? err.message : String(err)\n return {\n trajectoryId: trajectory.id,\n pass: false,\n labels: [\n {\n source: 'system',\n kind: 'reject',\n value: false,\n reason: message,\n severity: 'error',\n createdAt,\n },\n ],\n outcome: {\n success: false,\n score: 0,\n detail: message,\n observedAt: createdAt,\n },\n metadata: { replayError: true },\n }\n }\n}\n\nexport async function replayFeedbackTrajectories(\n trajectories: FeedbackTrajectory[],\n adapter: FeedbackReplayAdapter,\n): Promise<FeedbackReplayResult[]> {\n const results: FeedbackReplayResult[] = []\n for (const trajectory of trajectories) {\n results.push(await replayFeedbackTrajectory(trajectory, adapter))\n }\n return results\n}\n\nexport function summarizePreferenceMemory(\n trajectories: FeedbackTrajectory[],\n options: { maxEntries?: number } = {},\n): PreferenceMemoryEntry[] {\n const maxEntries = options.maxEntries ?? 20\n const entries: PreferenceMemoryEntry[] = []\n for (const trajectory of trajectories) {\n for (const label of allLabels(trajectory)) {\n const instruction = instructionFromLabel(trajectory, label)\n if (!instruction) continue\n entries.push({\n instruction,\n rationale: label.reason ?? `${label.kind} label from ${label.source}`,\n weight: weightForLabel(label),\n sourceTrajectoryId: trajectory.id,\n sourceLabelId: label.id,\n category: label.kind,\n })\n }\n }\n\n const byInstruction = new Map<string, PreferenceMemoryEntry>()\n for (const entry of entries) {\n const key = entry.instruction.toLowerCase().replace(/\\s+/g, ' ').trim()\n const existing = byInstruction.get(key)\n if (!existing || entry.weight > existing.weight) byInstruction.set(key, entry)\n }\n return [...byInstruction.values()].sort((a, b) => b.weight - a.weight).slice(0, maxEntries)\n}\n\nexport function renderPreferenceMemoryMarkdown(entries: PreferenceMemoryEntry[]): string {\n const lines = ['# Preference Memory', '']\n for (const entry of entries) {\n lines.push(`- ${entry.instruction}`)\n lines.push(` Rationale: ${entry.rationale}`)\n lines.push(` Source: ${entry.sourceTrajectoryId}`)\n lines.push('')\n }\n return `${lines.join('\\n').trim()}\\n`\n}\n\n/** One RFC 8785 canonical JSON row per trajectory, sorted by id, so two exports\n * of equal stores are byte-equal. Each row is the trajectory's JSON document\n * form — the same form every store persists. */\nexport function serializeFeedbackTrajectoriesJsonl(trajectories: FeedbackTrajectory[]): string {\n return `${trajectories\n .slice()\n .sort((a, b) => compareCodeUnits(a.id, b.id))\n .map((trajectory) => canonicalString(cloneTrajectory(trajectory)))\n .join('\\n')}\\n`\n}\n\nexport function parseFeedbackTrajectoriesJsonl(jsonl: string): FeedbackTrajectory[] {\n const trajectories: FeedbackTrajectory[] = []\n for (const line of jsonl.split('\\n')) {\n if (!line.trim()) continue\n trajectories.push(JSON.parse(line) as FeedbackTrajectory)\n }\n return trajectories\n}\n\nexport function controlRunToFeedbackTrajectory<TState, TAction, TActionResult>(\n run: ControlRunResult<TState, TAction, TActionResult>,\n options: {\n projectId?: string\n scenarioId?: string\n artifactType?: FeedbackArtifactType\n artifactFromStep?: (step: ControlStep<TState, TAction, TActionResult>) => unknown\n proposedActionFromStep?: (\n step: ControlStep<TState, TAction, TActionResult>,\n ) => ProposedSideEffect | undefined\n createdAt?: string\n } = {},\n): FeedbackTrajectory {\n const createdAt = options.createdAt ?? new Date().toISOString()\n const trajectoryId =\n run.runId ?? `ft_control_${stableHash(`${run.intent}|${createdAt}`).toString(16)}`\n return createFeedbackTrajectory({\n id: trajectoryId,\n projectId: options.projectId,\n scenarioId: options.scenarioId,\n task: { intent: run.intent },\n createdAt,\n attempts: run.steps.map((step) => ({\n id: `${trajectoryId}_step_${step.index}`,\n stepIndex: step.index,\n artifactType: options.artifactType ?? 'action',\n artifact: options.artifactFromStep?.(step) ?? step.actionOutcome?.result ?? step.decision,\n proposedAction: options.proposedActionFromStep?.(step),\n evals: step.evalsAfter,\n createdAt: step.startedAt,\n metadata: {\n decision: step.decision,\n actionOutcome: step.actionOutcome,\n },\n })),\n labels: [\n {\n source: 'system',\n kind: run.pass ? 'approve' : 'reject',\n value: run.pass,\n reason: run.reason,\n severity: run.pass ? 'info' : 'error',\n createdAt,\n },\n ],\n outcome: {\n success: run.pass,\n score: run.score,\n costUsd: run.spentCostUsd,\n detail: run.reason,\n observedAt: createdAt,\n metadata: {\n stoppedBy: run.stoppedBy,\n failureClass: run.failureClass,\n },\n },\n })\n}\n\nfunction allLabels(trajectory: FeedbackTrajectory): FeedbackLabel[] {\n const labels = [\n ...trajectory.labels,\n ...trajectory.attempts.flatMap((attempt) => attempt.feedback ?? []),\n ]\n const seen = new Set<string>()\n return labels.filter((label) => {\n const key =\n label.id ?? `${label.source}|${label.kind}|${label.createdAt}|${JSON.stringify(label.value)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction feedbackSeverityFromFinding(finding: AnalystFinding): FeedbackSeverity {\n switch (finding.severity) {\n case 'critical':\n return 'critical'\n case 'high':\n return 'error'\n case 'medium':\n return 'warning'\n default:\n return 'info'\n }\n}\n\nfunction scoreFromLabels(labels: FeedbackLabel[]): number | undefined {\n if (!labels.length) return undefined\n const scored = labels\n .map((label) => {\n if (label.kind === 'approve' || label.kind === 'select') return 1\n if (label.kind === 'reject' || label.kind === 'policy_block') return 0\n if (label.kind === 'rate' && typeof label.value === 'number')\n return Math.max(0, Math.min(1, label.value))\n return undefined\n })\n .filter((value): value is number => typeof value === 'number')\n if (!scored.length) return undefined\n return Math.round((scored.reduce((sum, value) => sum + value, 0) / scored.length) * 1000) / 1000\n}\n\nfunction instructionFromLabel(\n trajectory: FeedbackTrajectory,\n label: FeedbackLabel,\n): string | undefined {\n if (label.kind === 'reject' && label.reason)\n return `Avoid outputs like \"${compact(trajectory.task.intent, 80)}\" when: ${label.reason}`\n if (label.kind === 'revision_request' && label.reason)\n return `Revise similar work by applying: ${label.reason}`\n if (label.kind === 'select' && label.reason)\n return `Prefer selected options for \"${compact(trajectory.task.intent, 80)}\" because: ${label.reason}`\n if (label.kind === 'approve' && label.reason)\n return `Repeat the pattern approved for \"${compact(trajectory.task.intent, 80)}\": ${label.reason}`\n if (label.kind === 'comment' && label.reason) return label.reason\n return undefined\n}\n\nfunction weightForLabel(label: FeedbackLabel): number {\n const severity =\n label.severity === 'critical'\n ? 4\n : label.severity === 'error'\n ? 3\n : label.severity === 'warning'\n ? 2\n : 1\n const source =\n label.source === 'user'\n ? 3\n : label.source === 'metric' || label.source === 'environment'\n ? 2\n : 1\n return severity * source\n}\n\nfunction matchesFilter(trajectory: FeedbackTrajectory, filter: FeedbackTrajectoryFilter): boolean {\n if (filter.projectId && trajectory.projectId !== filter.projectId) return false\n if (filter.scenarioId && trajectory.scenarioId !== filter.scenarioId) return false\n if (filter.split && trajectory.split !== filter.split) return false\n if (filter.tag) {\n const [key, value] = filter.tag\n if (trajectory.tags?.[key] !== value) return false\n }\n return true\n}\n\nfunction cloneTrajectory(trajectory: FeedbackTrajectory): FeedbackTrajectory {\n return JSON.parse(JSON.stringify(trajectory)) as FeedbackTrajectory\n}\n\nfunction compact(value: string, max: number): string {\n const normalized = value.replace(/\\s+/g, ' ').trim()\n return normalized.length > max ? `${normalized.slice(0, max).trim()}...` : normalized\n}\n\nfunction stableHash(input: string): number {\n let hash = 2166136261\n for (let i = 0; i < input.length; i += 1) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 16777619)\n }\n return hash >>> 0\n}\n","/**\n * @stable\n *\n * Eval scorecard — the persistent (persona × profile) score timeline.\n *\n * Every benchmark run folds into per-cell entries; a cell is\n * `(scenarioId, profileHash)` and its timeline carries one entry per commit.\n * The scorecard answers the question a single run cannot: did THIS change\n * regress persona P on profile F, even while the aggregate improved?\n *\n * Storage is an append-only JSONL log — one line per (cell, commit). Appends\n * never read-modify-write, so concurrent campaign runs cannot clobber each\n * other; `loadScorecard` folds the log into the queryable `Scorecard`, and a\n * malformed line never breaks the read. `diffScorecard` compares the latest\n * entry of each cell against its predecessor with Cohen's d + Welch's t-test.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport type { AgentProfile } from './agent-profile'\nimport { agentProfileHash, agentProfileModelId } from './agent-profile'\nimport { welchsTTest } from './baseline'\nimport { type RunRecord, runTaskScore } from './run-record'\nimport { cohensD } from './statistics'\n\n// ── Types ────────────────────────────────────────────────────────────\n\n/** One commit's measurement of one (scenario, profile) cell. */\nexport interface ScorecardEntry {\n commitSha: string\n /** ISO timestamp the entry was recorded. */\n timestamp: string\n /** Per-seed (or per-rep) scores for this cell at this commit. */\n scores: number[]\n /** Median of `scores` — the cell's headline score for the commit. */\n composite: number\n /** Per-dimension means, when the runs carried a judge breakdown. */\n perDimension?: Record<string, number>\n /** RunRecord ids folded into this entry — provenance. */\n runIds: string[]\n}\n\n/** A (scenario, profile) cell and its commit-ordered score timeline. */\nexport interface ScorecardCell {\n scenarioId: string\n profileHash: string\n /** Model id — denormalised from the profile for readable filtering. */\n model: string\n timeline: ScorecardEntry[]\n}\n\n/** The folded scorecard: every cell, plus the profile definitions by hash. */\nexport interface Scorecard {\n cells: ScorecardCell[]\n /** Profile definitions seen — keeps the scorecard self-describing. */\n profiles: Record<string, AgentProfile>\n}\n\n/** One append-only log line — a single cell's entry for a single commit. */\nexport interface ScorecardLogLine {\n scenarioId: string\n profileHash: string\n model: string\n profile: AgentProfile\n entry: ScorecardEntry\n}\n\n// ── Recording ────────────────────────────────────────────────────────\n\nexport interface RecordRunsOptions {\n /** The profile that produced these runs — keys the cell. */\n profile: AgentProfile\n commitSha: string\n /** Defaults to `new Date().toISOString()`. */\n timestamp?: string\n}\n\nfunction median(xs: number[]): number {\n if (xs.length === 0) return 0\n const sorted = [...xs].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!\n}\n\n// Cells rank on `runTaskScore` — RAW on purpose: a scorecard reports the\n// measurement, and hiding a gamed run's score behind a 0 would make the gaming\n// invisible in the report.\n\n/** Mean of each judge dimension across the runs that reported one. */\nfunction aggregatePerDimension(runs: RunRecord[]): Record<string, number> | undefined {\n const sums = new Map<string, { total: number; count: number }>()\n for (const run of runs) {\n const dims = run.outcome.judgeScores?.perDimMean\n if (!dims) continue\n for (const [dim, value] of Object.entries(dims)) {\n if (!Number.isFinite(value)) continue\n const acc = sums.get(dim) ?? { total: 0, count: 0 }\n acc.total += value\n acc.count += 1\n sums.set(dim, acc)\n }\n }\n if (sums.size === 0) return undefined\n const out: Record<string, number> = {}\n for (const [dim, acc] of sums) out[dim] = acc.total / acc.count\n return out\n}\n\n/**\n * Fold a benchmark's `RunRecord[]` into per-cell scorecard log lines — one\n * line per scenario the runs cover. All runs are attributed to the single\n * `profile` in `opts` (the harness ran them under it); the cell key is\n * `(scenarioId, agentProfileHash(profile))`.\n */\nexport function recordRuns(runs: RunRecord[], opts: RecordRunsOptions): ScorecardLogLine[] {\n const profileHash = agentProfileHash(opts.profile)\n const model = agentProfileModelId(opts.profile)\n const timestamp = opts.timestamp ?? new Date().toISOString()\n\n const byScenario = new Map<string, RunRecord[]>()\n for (const run of runs) {\n const scenarioId = run.scenarioId\n if (!scenarioId) continue // un-keyed run — cannot place it in a cell\n const bucket = byScenario.get(scenarioId)\n if (bucket) bucket.push(run)\n else byScenario.set(scenarioId, [run])\n }\n\n const lines: ScorecardLogLine[] = []\n for (const [scenarioId, scenarioRuns] of byScenario) {\n const scored = scenarioRuns\n .map((run) => ({ run, score: runTaskScore(run) }))\n .filter((s): s is { run: RunRecord; score: number } => s.score !== undefined)\n if (scored.length === 0) continue\n const scores = scored.map((s) => s.score)\n const entry: ScorecardEntry = {\n commitSha: opts.commitSha,\n timestamp,\n scores,\n composite: median(scores),\n runIds: scored.map((s) => s.run.runId),\n }\n const perDimension = aggregatePerDimension(scenarioRuns)\n if (perDimension) entry.perDimension = perDimension\n lines.push({\n scenarioId,\n profileHash,\n model,\n profile: opts.profile,\n entry,\n })\n }\n return lines\n}\n\n// ── Storage ──────────────────────────────────────────────────────────\n\n/** Append cell entries to the JSONL scorecard log. Creates the file/dir. */\nexport function appendScorecard(logPath: string, lines: ScorecardLogLine[]): void {\n if (lines.length === 0) return\n mkdirSync(dirname(logPath), { recursive: true })\n appendFileSync(logPath, `${lines.map((line) => JSON.stringify(line)).join('\\n')}\\n`)\n}\n\n/** Record runs and append them to the log in one call. Returns the lines. */\nexport function recordRunsToScorecard(\n logPath: string,\n runs: RunRecord[],\n opts: RecordRunsOptions,\n): ScorecardLogLine[] {\n const lines = recordRuns(runs, opts)\n appendScorecard(logPath, lines)\n return lines\n}\n\n/**\n * Fold the JSONL log into a queryable `Scorecard`. A missing file yields an\n * empty scorecard; a malformed line is skipped — a corrupt append never\n * breaks the read. Each cell's timeline is sorted chronologically.\n */\nexport function loadScorecard(logPath: string): Scorecard {\n if (!existsSync(logPath)) return { cells: [], profiles: {} }\n const cells = new Map<string, ScorecardCell>()\n const profiles: Record<string, AgentProfile> = {}\n\n for (const raw of readFileSync(logPath, 'utf8').split('\\n')) {\n const line = raw.trim()\n if (!line) continue\n let parsed: ScorecardLogLine\n try {\n parsed = JSON.parse(line) as ScorecardLogLine\n } catch {\n continue // skip a malformed line rather than failing the whole read\n }\n if (!parsed?.scenarioId || !parsed.profileHash || !parsed.entry) continue\n const key = `${parsed.scenarioId}::${parsed.profileHash}`\n let cell = cells.get(key)\n if (!cell) {\n cell = {\n scenarioId: parsed.scenarioId,\n profileHash: parsed.profileHash,\n model: parsed.model,\n timeline: [],\n }\n cells.set(key, cell)\n }\n cell.timeline.push(parsed.entry)\n if (parsed.profile) profiles[parsed.profileHash] = parsed.profile\n }\n\n for (const cell of cells.values()) {\n cell.timeline.sort((a, b) => a.timestamp.localeCompare(b.timestamp))\n }\n return { cells: [...cells.values()], profiles }\n}\n\n// ── Diff ─────────────────────────────────────────────────────────────\n\nexport type CellVerdict = 'improved' | 'regressed' | 'flat' | 'new'\n\nexport interface ScorecardCellDiff {\n scenarioId: string\n profileHash: string\n model: string\n verdict: CellVerdict\n /** Composite of the latest entry. */\n current: number\n /** Composite of the comparison entry — `null` when `verdict === 'new'`. */\n baseline: number | null\n /** `current − baseline` — `null` when new. */\n delta: number | null\n /** Cohen's d of current vs baseline samples — `null` when new or n < 2. */\n cohensD: number | null\n /** Welch's t-test p-value — `null` when new or n < 2. */\n pValue: number | null\n currentCommit: string\n baselineCommit: string | null\n}\n\nexport interface ScorecardDiff {\n cells: ScorecardCellDiff[]\n summary: { improved: number; regressed: number; flat: number; new: number }\n}\n\nexport interface DiffScorecardOptions {\n /** Compare each cell against this commit instead of its immediate predecessor. */\n baselineCommit?: string\n /** |Cohen's d| at/above which a move counts as real. Default 0.5. */\n minEffect?: number\n /** p-value at/below which a move is significant. Default 0.05. */\n maxP?: number\n /**\n * |delta| at/above which a move counts when statistics are unavailable\n * (a cell with fewer than 2 samples on either side). Default 0.05.\n */\n minDelta?: number\n}\n\n/**\n * Compare the latest entry of every cell against its predecessor (or against\n * `baselineCommit`) and classify the move. A move is `improved`/`regressed`\n * only when it clears both the effect-size and significance gates; otherwise\n * `flat`. Cells with no prior entry are `new`.\n */\nexport function diffScorecard(\n scorecard: Scorecard,\n opts: DiffScorecardOptions = {},\n): ScorecardDiff {\n const minEffect = opts.minEffect ?? 0.5\n const maxP = opts.maxP ?? 0.05\n const minDelta = opts.minDelta ?? 0.05\n\n const cells: ScorecardCellDiff[] = []\n for (const cell of scorecard.cells) {\n const timeline = cell.timeline\n if (timeline.length === 0) continue\n const current = timeline[timeline.length - 1]!\n\n const baseline = opts.baselineCommit\n ? [...timeline].reverse().find((e) => e.commitSha === opts.baselineCommit && e !== current)\n : timeline[timeline.length - 2]\n\n const base: Omit<\n ScorecardCellDiff,\n 'verdict' | 'baseline' | 'delta' | 'cohensD' | 'pValue' | 'baselineCommit'\n > = {\n scenarioId: cell.scenarioId,\n profileHash: cell.profileHash,\n model: cell.model,\n current: current.composite,\n currentCommit: current.commitSha,\n }\n\n if (!baseline) {\n cells.push({\n ...base,\n verdict: 'new',\n baseline: null,\n delta: null,\n cohensD: null,\n pValue: null,\n baselineCommit: null,\n })\n continue\n }\n\n const delta = current.composite - baseline.composite\n const canStat = baseline.scores.length >= 2 && current.scores.length >= 2\n let d: number | null = null\n let p: number | null = null\n let verdict: CellVerdict\n\n if (canStat) {\n d = cohensD(baseline.scores, current.scores)\n const t = welchsTTest(baseline.scores, current.scores)\n p = Number.isFinite(t.p) ? t.p : null\n // `canStat` guarantees ≥ 2 samples per side, so a null d means zero\n // pooled spread across a real mean gap — an unbounded standardized\n // effect, which clears any finite threshold.\n const effectClears = d === null || Math.abs(d) >= minEffect\n const significant = effectClears && p !== null && p <= maxP\n verdict = significant ? (delta > 0 ? 'improved' : 'regressed') : 'flat'\n } else {\n // Too few samples for a real test — fall back to a raw-delta threshold.\n verdict = Math.abs(delta) >= minDelta ? (delta > 0 ? 'improved' : 'regressed') : 'flat'\n }\n\n cells.push({\n ...base,\n verdict,\n baseline: baseline.composite,\n delta,\n cohensD: d,\n pValue: p,\n baselineCommit: baseline.commitSha,\n })\n }\n\n const summary = { improved: 0, regressed: 0, flat: 0, new: 0 }\n for (const cell of cells) summary[cell.verdict] += 1\n return { cells, summary }\n}\n\n/**\n * Render a scorecard diff as a human-readable report — the block a feature\n * PR prints. Regressions are listed first; flat cells are summarised, not\n * enumerated.\n */\nexport function formatScorecardDiff(diff: ScorecardDiff): string {\n const lines: string[] = []\n const { summary } = diff\n lines.push(\n `Scorecard: ${summary.regressed} regressed · ${summary.improved} improved · ` +\n `${summary.flat} flat · ${summary.new} new`,\n )\n\n const fmt = (n: number) => n.toFixed(3)\n const noteworthy = diff.cells\n .filter((c) => c.verdict === 'regressed' || c.verdict === 'improved')\n .sort((a, b) => {\n // Regressions first, then by magnitude of delta.\n if (a.verdict !== b.verdict) return a.verdict === 'regressed' ? -1 : 1\n return Math.abs(b.delta ?? 0) - Math.abs(a.delta ?? 0)\n })\n\n for (const cell of noteworthy) {\n const mark = cell.verdict === 'regressed' ? 'REGRESSED' : 'improved'\n const deltaStr =\n cell.delta !== null ? (cell.delta >= 0 ? `+${fmt(cell.delta)}` : fmt(cell.delta)) : '—'\n const stat =\n cell.cohensD !== null\n ? ` (d=${cell.cohensD.toFixed(2)}${cell.pValue !== null ? `, p=${cell.pValue.toFixed(3)}` : ''})`\n : ''\n lines.push(\n ` ${mark} ${cell.scenarioId} · ${cell.model} · ${cell.profileHash.slice(0, 8)} ` +\n `${fmt(cell.baseline ?? 0)} → ${fmt(cell.current)} ${deltaStr}${stat}`,\n )\n }\n\n return lines.join('\\n')\n}\n","/**\n * Trace contracts — finite-trace temporal assertions over span sequences.\n *\n * Five LTLf operators over one ordered span sequence — `always(p)`,\n * `never(p)`, `eventually(p)`, `precedes(a, b)`, `neverUnless(p, prior)` —\n * deterministic and judge-free. No nesting: each rule is one operator over\n * flat `SpanPredicate`s; compose richer checks with multiple rules.\n *\n * A built `TraceContract` is a serializable plain object (RegExp matchers\n * are normalized to `SerializedRegex`), so ONE contract definition is\n * dual-use:\n *\n * - recorded eval traces — `evaluateTraceContract(contract, await\n * store.spans({ runId }))`.\n * - the production OTLP stream — `ExportableSpan`s flattened by\n * `trace/otel-bridge` satisfy `ContractSpan` structurally. A production\n * monitor implements `OtelExporter`, buffers `exportSpan` payloads per\n * trace, and runs `checkTraceContracts(buffer, contracts)` on flush:\n *\n * const buffer: ContractSpan[] = []\n * const monitor: OtelExporter = {\n * exportSpan: (s) => { buffer.push(s) },\n * flush: async () => {\n * const { allValid, verdicts } = checkTraceContracts(buffer, contracts)\n * if (!allValid) alert(verdicts)\n * },\n * shutdown: async () => {},\n * }\n * const store = createOtelTracingStore(inner, monitor, runId)\n *\n * `custom` predicate functions are the one non-serializable escape hatch:\n * the builder stamps `requiresCustom: true` (which DOES survive JSON) so a\n * deserialized contract that lost its function fails loud at evaluation\n * instead of silently weakening.\n *\n * Naming: the root barrel exports ci-gate's threshold-contract\n * `evaluateContract`, so the evaluators here are `evaluateTraceContract` /\n * `checkTraceContracts`.\n */\n\nimport type { JudgeConfig, JudgeDimension, Scenario } from './campaign/types'\nimport { ValidationError } from './errors'\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\n// ── Span surface ──────────────────────────────────────────────────────\n\n/**\n * Minimal structural span the checker reads. Both the eval-side `Span`\n * (trace/schema) and the OTLP-flattened `ExportableSpan` (trace/otel-export)\n * satisfy it; any other producer only needs these fields.\n */\nexport interface ContractSpan {\n spanId?: string\n name?: string\n kind?: string\n startedAt?: number\n status?: string\n error?: string\n /** Typed field on eval-side ToolSpans; OTLP flattenings drop it (see\n * `tool` matching order in {@link matchSpan}). */\n toolName?: string\n attributes?: Record<string, unknown>\n}\n\n/** JSON-safe RegExp form — what the builder normalizes RegExp matchers to. */\nexport interface SerializedRegex {\n $regex: string\n flags: string\n}\n\nexport type TextMatcher = string | RegExp | SerializedRegex\n\n/**\n * Proposition over one span. All specified fields must match (AND).\n * At least one field is required — an empty predicate would match every\n * span and is rejected.\n *\n * `tool` resolution order covers both span shapes: `span.toolName` (typed\n * ToolSpan) → `attributes['tool.name']` / `attributes['toolName']`\n * (OTLP-flat attribute conventions) → `span.name` when `kind === 'tool'`\n * (otel-bridge's `ExportableSpan`, which drops `toolName`).\n *\n * `attr` values match by strict equality, or regex-test when the value is a\n * RegExp/SerializedRegex and the attribute is a string. Structured attribute\n * values need `custom`.\n */\nexport interface SpanPredicate {\n name?: TextMatcher\n tool?: TextMatcher\n attr?: Record<string, unknown>\n custom?: (span: ContractSpan) => boolean\n /** Stamped by the builder when `custom` is present. Survives JSON while\n * the function does not, so evaluation of a deserialized contract throws\n * instead of silently dropping the check. */\n requiresCustom?: true\n}\n\n// ── Contract shape ────────────────────────────────────────────────────\n\nexport type ContractRuleKind = 'always' | 'never' | 'eventually' | 'precedes' | 'neverUnless'\n\nexport interface ContractRule {\n kind: ContractRuleKind\n /** Unique within the contract — keys the per-rule score. */\n label: string\n /** Subject predicate for always / never / eventually / neverUnless. */\n p?: SpanPredicate\n /** precedes: the required precondition. */\n a?: SpanPredicate\n /** precedes: the guarded match — every b-match needs an earlier a-match. */\n b?: SpanPredicate\n /** neverUnless: the authorizing earlier match. */\n prior?: SpanPredicate\n}\n\n/** Serializable plain object — `traceContract(name)....build()` output. */\nexport interface TraceContract {\n name: string\n rules: ContractRule[]\n}\n\nexport interface ContractViolation {\n rule: string\n spanId?: string\n detail: string\n}\n\nexport interface ContractVerdict extends DefaultVerdict {\n /** Contract name — keys this verdict in multi-contract reports. */\n contract: string\n valid: boolean\n /** Fraction of rules passing, in [0, 1]. */\n score: number\n /** Per-rule 0|1 keyed by rule label. */\n scores: Record<string, number>\n violations: ContractViolation[]\n}\n\nexport interface ContractCheckResult {\n verdicts: ContractVerdict[]\n allValid: boolean\n}\n\n// ── Predicate matching ────────────────────────────────────────────────\n\nfunction isSerializedRegex(v: unknown): v is SerializedRegex {\n return (\n typeof v === 'object' &&\n v !== null &&\n typeof (v as SerializedRegex).$regex === 'string' &&\n typeof (v as SerializedRegex).flags === 'string'\n )\n}\n\nfunction matchText(actual: string | undefined, matcher: TextMatcher): boolean {\n if (typeof actual !== 'string') return false\n if (typeof matcher === 'string') return actual === matcher\n if (matcher instanceof RegExp) return matcher.test(actual)\n return new RegExp(matcher.$regex, matcher.flags).test(actual)\n}\n\nfunction resolveToolName(span: ContractSpan): string | undefined {\n if (typeof span.toolName === 'string') return span.toolName\n const fromAttr = span.attributes?.['tool.name'] ?? span.attributes?.toolName\n if (typeof fromAttr === 'string') return fromAttr\n if (span.kind === 'tool' && typeof span.name === 'string') return span.name\n return undefined\n}\n\nfunction assertPredicate(value: unknown, where: string): asserts value is SpanPredicate {\n if (value === null || typeof value !== 'object') {\n throw new ValidationError(`${where}: predicate must be an object, got ${typeof value}`)\n }\n const p = value as SpanPredicate\n for (const field of ['name', 'tool'] as const) {\n const m = p[field]\n if (\n m !== undefined &&\n typeof m !== 'string' &&\n !(m instanceof RegExp) &&\n !isSerializedRegex(m)\n ) {\n throw new ValidationError(`${where}: \"${field}\" must be string | RegExp | SerializedRegex`)\n }\n }\n if (\n p.attr !== undefined &&\n (p.attr === null || typeof p.attr !== 'object' || Array.isArray(p.attr))\n ) {\n throw new ValidationError(`${where}: \"attr\" must be a plain object`)\n }\n if (p.requiresCustom && typeof p.custom !== 'function') {\n throw new ValidationError(\n `${where}: rule was built with a custom predicate function, which does not survive JSON ` +\n 'serialization — re-attach `custom` after deserializing or drop the rule',\n )\n }\n const hasAttr = p.attr !== undefined && Object.keys(p.attr).length > 0\n if (p.name === undefined && p.tool === undefined && !hasAttr && typeof p.custom !== 'function') {\n throw new ValidationError(\n `${where}: empty predicate would match every span — specify name, tool, attr, or custom`,\n )\n }\n}\n\n/** Test one span against one predicate. All specified fields must match. */\nexport function matchSpan(span: ContractSpan, predicate: SpanPredicate): boolean {\n assertPredicate(predicate, 'matchSpan')\n if (predicate.name !== undefined && !matchText(span.name, predicate.name)) return false\n if (predicate.tool !== undefined && !matchText(resolveToolName(span), predicate.tool))\n return false\n if (predicate.attr !== undefined) {\n for (const [key, expected] of Object.entries(predicate.attr)) {\n const actual = span.attributes?.[key]\n if (expected instanceof RegExp || isSerializedRegex(expected)) {\n if (!matchText(typeof actual === 'string' ? actual : undefined, expected as TextMatcher)) {\n return false\n }\n } else if (actual !== expected) {\n return false\n }\n }\n }\n if (predicate.custom !== undefined && !predicate.custom(span)) return false\n return true\n}\n\n// ── Builder ───────────────────────────────────────────────────────────\n\nfunction describeMatcher(m: TextMatcher): string {\n if (typeof m === 'string') return m\n if (m instanceof RegExp) return `/${m.source}/${m.flags}`\n return `/${m.$regex}/${m.flags}`\n}\n\nfunction describePredicate(p: SpanPredicate): string {\n const parts: string[] = []\n if (p.name !== undefined) parts.push(`name=${describeMatcher(p.name)}`)\n if (p.tool !== undefined) parts.push(`tool=${describeMatcher(p.tool)}`)\n if (p.attr !== undefined) {\n for (const [k, v] of Object.entries(p.attr)) {\n parts.push(\n `attr.${k}=${v instanceof RegExp || isSerializedRegex(v) ? describeMatcher(v as TextMatcher) : JSON.stringify(v)}`,\n )\n }\n }\n if (typeof p.custom === 'function') parts.push(`custom=${p.custom.name || 'fn'}`)\n return parts.join(',')\n}\n\nfunction normalizeMatcher(m: TextMatcher): string | SerializedRegex {\n return m instanceof RegExp ? { $regex: m.source, flags: m.flags } : m\n}\n\nfunction normalizePredicate(p: SpanPredicate, where: string): SpanPredicate {\n assertPredicate(p, where)\n const out: SpanPredicate = {}\n if (p.name !== undefined) out.name = normalizeMatcher(p.name)\n if (p.tool !== undefined) out.tool = normalizeMatcher(p.tool)\n if (p.attr !== undefined) {\n out.attr = Object.fromEntries(\n Object.entries(p.attr).map(([k, v]) => [k, v instanceof RegExp ? normalizeMatcher(v) : v]),\n )\n }\n if (typeof p.custom === 'function') {\n out.custom = p.custom\n out.requiresCustom = true\n }\n return out\n}\n\nexport class TraceContractBuilder {\n private readonly rules: ContractRule[] = []\n\n constructor(private readonly name: string) {}\n\n /** Every span in the trace must satisfy `p`. */\n always(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").always`)\n return this.add({ kind: 'always', label: label ?? `always(${describePredicate(np)})`, p: np })\n }\n\n /** No span in the trace may satisfy `p`. */\n never(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").never`)\n return this.add({ kind: 'never', label: label ?? `never(${describePredicate(np)})`, p: np })\n }\n\n /** At least one span in the trace must satisfy `p`. */\n eventually(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").eventually`)\n return this.add({\n kind: 'eventually',\n label: label ?? `eventually(${describePredicate(np)})`,\n p: np,\n })\n }\n\n /** Every `b`-match must have a strictly earlier `a`-match. */\n precedes(a: SpanPredicate, b: SpanPredicate, label?: string): this {\n const na = normalizePredicate(a, `traceContract(\"${this.name}\").precedes (a)`)\n const nb = normalizePredicate(b, `traceContract(\"${this.name}\").precedes (b)`)\n return this.add({\n kind: 'precedes',\n label: label ?? `precedes(${describePredicate(na)} -> ${describePredicate(nb)})`,\n a: na,\n b: nb,\n })\n }\n\n /** Every `p`-match is a violation unless a strictly earlier `prior`-match exists. */\n neverUnless(p: SpanPredicate, prior: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").neverUnless (p)`)\n const nprior = normalizePredicate(prior, `traceContract(\"${this.name}\").neverUnless (prior)`)\n return this.add({\n kind: 'neverUnless',\n label: label ?? `neverUnless(${describePredicate(np)} unless ${describePredicate(nprior)})`,\n p: np,\n prior: nprior,\n })\n }\n\n build(): TraceContract {\n if (this.rules.length === 0) {\n throw new ValidationError(\n `traceContract(\"${this.name}\").build(): no rules — an empty contract would vacuously pass`,\n )\n }\n return { name: this.name, rules: [...this.rules] }\n }\n\n private add(rule: ContractRule): this {\n // Labels key per-rule scores — auto-suffix duplicates so two identical\n // operator+predicate rules never collapse into one score entry.\n let label = rule.label\n let n = 2\n while (this.rules.some((r) => r.label === label)) {\n label = `${rule.label} #${n}`\n n += 1\n }\n this.rules.push({ ...rule, label })\n return this\n }\n}\n\nexport function traceContract(name: string): TraceContractBuilder {\n if (typeof name !== 'string' || name.length === 0) {\n throw new ValidationError('traceContract: name must be a non-empty string')\n }\n return new TraceContractBuilder(name)\n}\n\n// ── Evaluation ────────────────────────────────────────────────────────\n\nfunction assertContract(contract: TraceContract): void {\n if (typeof contract?.name !== 'string' || contract.name.length === 0) {\n throw new ValidationError('evaluateTraceContract: contract.name must be a non-empty string')\n }\n if (!Array.isArray(contract.rules) || contract.rules.length === 0) {\n throw new ValidationError(\n `evaluateTraceContract: contract \"${contract.name}\" has no rules — an empty contract would vacuously pass`,\n )\n }\n const seen = new Set<string>()\n for (const rule of contract.rules) {\n const where = `contract \"${contract.name}\" rule \"${rule?.label ?? '<unlabeled>'}\"`\n if (typeof rule?.label !== 'string' || rule.label.length === 0) {\n throw new ValidationError(`${where}: label must be a non-empty string`)\n }\n if (seen.has(rule.label)) {\n throw new ValidationError(`${where}: duplicate label would collapse per-rule scores`)\n }\n seen.add(rule.label)\n switch (rule.kind) {\n case 'always':\n case 'never':\n case 'eventually':\n assertPredicate(rule.p, `${where} (p)`)\n break\n case 'precedes':\n assertPredicate(rule.a, `${where} (a)`)\n assertPredicate(rule.b, `${where} (b)`)\n break\n case 'neverUnless':\n assertPredicate(rule.p, `${where} (p)`)\n assertPredicate(rule.prior, `${where} (prior)`)\n break\n default:\n throw new ValidationError(\n `${where}: unknown rule kind \"${String((rule as ContractRule).kind)}\"`,\n )\n }\n }\n}\n\n/**\n * Order spans for temporal evaluation: by `startedAt` when EVERY span carries\n * one (stable — ties keep array order), by array order when NONE does. Mixed\n * timestamps throw: neither time order nor array order is a trustworthy total\n * order over a partially-stamped sequence, and guessing would corrupt\n * `precedes` / `neverUnless` verdicts.\n */\nfunction orderSpans(spans: readonly ContractSpan[]): ContractSpan[] {\n const timed = spans.filter(\n (s) => typeof s.startedAt === 'number' && Number.isFinite(s.startedAt),\n ).length\n if (timed === spans.length) {\n return spans\n .map((span, i) => ({ span, i }))\n .sort((x, y) => x.span.startedAt! - y.span.startedAt! || x.i - y.i)\n .map((x) => x.span)\n }\n if (timed === 0) return [...spans]\n throw new ValidationError(\n `evaluateTraceContract: ${timed}/${spans.length} spans carry a finite startedAt — ` +\n 'mixed timestamps make ordering ambiguous; stamp every span or none',\n )\n}\n\nfunction spanRef(span: ContractSpan, index: number): string {\n return span.spanId ?? `#${index}`\n}\n\n// precedes(a, b) and neverUnless(p, prior) share one semantics: every\n// guarded-match must have a STRICTLY earlier guard-match. The guard flag\n// updates after the guarded check, so a span matching both cannot witness\n// itself.\nfunction checkGuarded(args: {\n label: string\n ordered: readonly ContractSpan[]\n guard: SpanPredicate\n guarded: SpanPredicate\n detail: (ref: string) => string\n}): ContractViolation[] {\n const out: ContractViolation[] = []\n let guardSeen = false\n for (let i = 0; i < args.ordered.length; i++) {\n const span = args.ordered[i]!\n if (!guardSeen && matchSpan(span, args.guarded)) {\n out.push({ rule: args.label, spanId: span.spanId, detail: args.detail(spanRef(span, i)) })\n }\n if (matchSpan(span, args.guard)) guardSeen = true\n }\n return out\n}\n\nfunction checkRule(rule: ContractRule, ordered: readonly ContractSpan[]): ContractViolation[] {\n switch (rule.kind) {\n case 'always': {\n const out: ContractViolation[] = []\n for (let i = 0; i < ordered.length; i++) {\n const span = ordered[i]!\n if (!matchSpan(span, rule.p!)) {\n out.push({\n rule: rule.label,\n spanId: span.spanId,\n detail: `span ${spanRef(span, i)} (\"${span.name ?? ''}\") fails always(${describePredicate(rule.p!)})`,\n })\n }\n }\n return out\n }\n case 'never': {\n const out: ContractViolation[] = []\n for (let i = 0; i < ordered.length; i++) {\n const span = ordered[i]!\n if (matchSpan(span, rule.p!)) {\n out.push({\n rule: rule.label,\n spanId: span.spanId,\n detail: `span ${spanRef(span, i)} (\"${span.name ?? ''}\") matches never(${describePredicate(rule.p!)})`,\n })\n }\n }\n return out\n }\n case 'eventually': {\n const hit = ordered.some((span) => matchSpan(span, rule.p!))\n return hit\n ? []\n : [\n {\n rule: rule.label,\n detail: `no span matches eventually(${describePredicate(rule.p!)}) over ${ordered.length} span(s)`,\n },\n ]\n }\n case 'precedes':\n return checkGuarded({\n label: rule.label,\n ordered,\n guard: rule.a!,\n guarded: rule.b!,\n detail: (ref) =>\n `span ${ref} matches ${describePredicate(rule.b!)} with no earlier ${describePredicate(rule.a!)} match`,\n })\n case 'neverUnless':\n return checkGuarded({\n label: rule.label,\n ordered,\n guard: rule.prior!,\n guarded: rule.p!,\n detail: (ref) =>\n `span ${ref} matches ${describePredicate(rule.p!)} with no earlier ${describePredicate(rule.prior!)} match`,\n })\n }\n}\n\n/**\n * Evaluate one contract over a span sequence. Pure and synchronous — works\n * on `Span[]` from a TraceStore, `ExportableSpan[]` from the otel-bridge\n * flattening, or any array satisfying `ContractSpan`.\n */\nexport function evaluateTraceContract(\n contract: TraceContract,\n spans: readonly ContractSpan[],\n): ContractVerdict {\n assertContract(contract)\n const ordered = orderSpans(spans)\n const scores: Record<string, number> = {}\n const violations: ContractViolation[] = []\n for (const rule of contract.rules) {\n const ruleViolations = checkRule(rule, ordered)\n scores[rule.label] = ruleViolations.length === 0 ? 1 : 0\n violations.push(...ruleViolations)\n }\n const ruleCount = contract.rules.length\n const passCount = Object.values(scores).filter((s) => s === 1).length\n // Steps the certificate rests on unverified: array ordering when no span\n // carries a timestamp, and any rule whose truth depends on a custom\n // predicate function that is not part of the serialized contract.\n const assumptions: string[] = []\n if (spans.length > 0 && ordered.every((s) => typeof s.startedAt !== 'number')) {\n assumptions.push('spans ordered by array position — no startedAt timestamps to order by')\n }\n for (const rule of contract.rules) {\n const predicates = [rule.p, rule.a, rule.b, rule.prior]\n if (predicates.some((p) => p !== undefined && typeof p.custom === 'function')) {\n assumptions.push(`rule '${rule.label}' rests on a custom predicate function`)\n }\n }\n return {\n contract: contract.name,\n valid: passCount === ruleCount,\n score: passCount / ruleCount,\n scores,\n violations,\n notes: `${passCount}/${ruleCount} rules passed`,\n certification: {\n strategy: 'invariant',\n checker: { name: 'agent-eval:trace-contracts', version: packageVersion() },\n assumptions,\n evidenceDigest: certificationEvidenceDigest({\n contract: contract.name,\n scores,\n violations,\n }),\n },\n }\n}\n\n/**\n * Evaluate many contracts over one span sequence. Throws on an empty\n * contract list — `allValid: true` over zero contracts is a silent pass.\n */\nexport function checkTraceContracts(\n spans: readonly ContractSpan[],\n contracts: readonly TraceContract[],\n): ContractCheckResult {\n if (contracts.length === 0) {\n throw new ValidationError(\n 'checkTraceContracts: empty contract list would vacuously pass — supply at least one contract',\n )\n }\n const verdicts = contracts.map((c) => evaluateTraceContract(c, spans))\n return { verdicts, allValid: verdicts.every((v) => v.valid) }\n}\n\n// ── Campaign judge adapter ────────────────────────────────────────────\n\nexport interface ContractJudgeOptions<TArtifact, TScenario extends Scenario = Scenario> {\n /**\n * Project the span sequence out of a cell's artifact. `JudgeConfig.score`\n * receives only `{ artifact, scenario, signal }` (src/campaign/types.ts) —\n * spans are NOT reachable generically — so the consumer supplies this\n * explicit extraction (e.g. dispatch writes spans into the artifact, or\n * closes over a per-cell TraceStore read).\n */\n spans: (input: { artifact: TArtifact; scenario: TScenario }) => readonly ContractSpan[]\n /** Judge name in campaign reports. Default 'trace-contracts'. */\n name?: string\n}\n\n/**\n * Adapt trace contracts to a campaign `JudgeConfig`. One judge dimension per\n * contract (key = contract name, value = its rule-pass fraction); composite\n * is the mean across contracts. Deterministic — no LLM call.\n */\nexport function contractJudge<TArtifact, TScenario extends Scenario = Scenario>(\n contracts: readonly TraceContract[],\n opts: ContractJudgeOptions<TArtifact, TScenario>,\n): JudgeConfig<TArtifact, TScenario> {\n if (contracts.length === 0) {\n throw new ValidationError('contractJudge: at least one contract required')\n }\n for (const c of contracts) assertContract(c)\n const names = new Set<string>()\n for (const c of contracts) {\n if (names.has(c.name)) {\n throw new ValidationError(\n `contractJudge: duplicate contract name \"${c.name}\" would collapse judge dimensions`,\n )\n }\n names.add(c.name)\n }\n if (typeof opts?.spans !== 'function') {\n throw new ValidationError('contractJudge: opts.spans extraction function is required')\n }\n const dimensions: JudgeDimension[] = contracts.map((c) => ({\n key: c.name,\n description: c.rules.map((r) => r.label).join('; '),\n }))\n return {\n name: opts.name ?? 'trace-contracts',\n dimensions,\n score({ artifact, scenario }) {\n const spans = opts.spans({ artifact, scenario })\n if (!Array.isArray(spans)) {\n throw new ValidationError(\n `contractJudge: spans() must return a span array, got ${typeof spans}`,\n )\n }\n const { verdicts } = checkTraceContracts(spans, contracts)\n const dims: Record<string, number> = {}\n const violations: ContractViolation[] = []\n for (const v of verdicts) {\n dims[v.contract] = v.score\n violations.push(...v.violations)\n }\n const composite = verdicts.reduce((acc, v) => acc + v.score, 0) / verdicts.length\n return {\n dimensions: dims,\n composite,\n notes:\n violations.length === 0\n ? 'all trace contracts satisfied'\n : violations\n .slice(0, 8)\n .map((x) => `${x.rule}: ${x.detail}`)\n .join('\\n'),\n }\n },\n }\n}\n","/**\n * Active learning — agent-as-scenario-author.\n *\n * Analyzes an existing Dataset + trace corpus for coverage gaps and\n * weak spots, returns a prioritized list of *synthesis targets*:\n * (gap description, existing-neighbor examples, suggested direction).\n *\n * Does NOT call an LLM itself — the proposer agent is caller-supplied.\n * This module's job is to identify WHERE new scenarios would compound\n * the most information, not to author them.\n *\n * Gaps we detect:\n * - dimensions with high score variance (unstable, need more data)\n * - dimensions with low coverage count (undersampled)\n * - failure classes with clusters (systematic weakness)\n * - difficulty bins with no coverage\n */\n\nimport type { Dataset, DatasetScenario } from './dataset'\nimport { classifyFailure } from './failure-taxonomy'\nimport type { Run } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport type SynthesisReason =\n | 'high-variance'\n | 'undersampled'\n | 'failure-cluster'\n | 'difficulty-gap'\n\nexport interface SynthesisTarget {\n reason: SynthesisReason\n description: string\n /** Existing scenarios that are closest to the gap; caller feeds these to\n * their LLM proposer as few-shot examples. */\n neighbors: DatasetScenario[]\n /** Suggested direction — e.g. \"harder variants\", \"edge cases of X\", \"failure class Y\". */\n direction: string\n /** Priority score — higher = more information-dense gap. 0..1. */\n priority: number\n}\n\nexport interface ActiveLearningOptions {\n /** Minimum scenarios per difficulty band to count as \"covered\". */\n minPerBand?: number\n /** Variance threshold above which a scenario's dimension is \"unstable\". */\n varianceThreshold?: number\n /** Max synthesis targets returned. */\n topK?: number\n}\n\nexport async function proposeSynthesisTargets(\n dataset: Dataset,\n traceStore: TraceStore,\n options: ActiveLearningOptions = {},\n): Promise<SynthesisTarget[]> {\n const minPerBand = options.minPerBand ?? 5\n const varianceThreshold = options.varianceThreshold ?? 0.05\n const topK = options.topK ?? 10\n const scenarios = dataset.all()\n\n const targets: SynthesisTarget[] = []\n\n // 1. Difficulty coverage gaps\n const BANDS: Array<DatasetScenario['difficulty']> = ['easy', 'medium', 'hard', 'extreme']\n for (const band of BANDS) {\n const count = scenarios.filter((s) => s.difficulty === band).length\n if (count < minPerBand) {\n const neighbors = scenarios.filter((s) => s.difficulty === band).slice(0, 3)\n targets.push({\n reason: 'difficulty-gap',\n description: `difficulty=\"${band}\" has ${count} scenario(s) — below minimum ${minPerBand}`,\n neighbors: [...neighbors],\n direction: `create more \"${band}\" scenarios; reuse domain but shift complexity`,\n priority: Math.max(0, 1 - count / minPerBand),\n })\n }\n }\n\n // 2. Undersampled scenarios (few runs per scenario)\n const runs = await traceStore.listRuns()\n const runCountByScenario = new Map<string, number>()\n for (const r of runs) {\n runCountByScenario.set(r.scenarioId, (runCountByScenario.get(r.scenarioId) ?? 0) + 1)\n }\n const runCounts = [...runCountByScenario.values()]\n const p25 = runCounts.length > 0 ? quantile(runCounts, 0.25) : 0\n for (const s of scenarios) {\n const count = runCountByScenario.get(s.id) ?? 0\n if (count <= p25 && count < 3) {\n targets.push({\n reason: 'undersampled',\n description: `scenario \"${s.id}\" has only ${count} run(s)`,\n neighbors: [s],\n direction: `create near-duplicates of \"${s.id}\" to stabilize its mean`,\n priority: Math.max(0, 1 - count / 3) * 0.7,\n })\n }\n }\n\n // 3. High-variance scenarios (same scenario scored inconsistently)\n for (const s of scenarios) {\n const sRuns = runs.filter((r) => r.scenarioId === s.id)\n const scores = sRuns\n .map((r) => r.outcome?.score)\n .filter((x): x is number => typeof x === 'number')\n if (scores.length < 3) continue\n const mean = scores.reduce((a, b) => a + b, 0) / scores.length\n const variance = scores.reduce((a, b) => a + (b - mean) ** 2, 0) / scores.length\n if (variance > varianceThreshold) {\n targets.push({\n reason: 'high-variance',\n description: `scenario \"${s.id}\" has unstable scoring (variance ${variance.toFixed(3)})`,\n neighbors: [s],\n direction: `disambiguate the scenario description — current wording admits too many valid interpretations`,\n priority: Math.min(1, variance * 5),\n })\n }\n }\n\n // 4. Failure-class clusters — run classifier across the corpus\n const failureByClass = new Map<string, Run[]>()\n for (const run of runs) {\n if (run.outcome?.pass === true) continue\n const spans = await traceStore.spans({ runId: run.runId })\n const events = await traceStore.events({ runId: run.runId })\n const { failureClass } = classifyFailure({ run, spans, events })\n if (failureClass === 'success' || failureClass === 'unknown') continue\n const arr = failureByClass.get(failureClass) ?? []\n arr.push(run)\n failureByClass.set(failureClass, arr)\n }\n for (const [cls, runs] of failureByClass) {\n if (runs.length < 3) continue\n const affectedScenarios = [...new Set(runs.map((r) => r.scenarioId))]\n const neighbors = scenarios.filter((s) => affectedScenarios.includes(s.id)).slice(0, 3)\n targets.push({\n reason: 'failure-cluster',\n description: `failure class \"${cls}\" observed ${runs.length}× across ${affectedScenarios.length} scenario(s)`,\n neighbors,\n direction: `create scenarios that exercise \"${cls}\" recovery — currently a systematic weakness`,\n priority: Math.min(1, runs.length / 10),\n })\n }\n\n return targets.sort((a, b) => b.priority - a.priority).slice(0, topK)\n}\n\nfunction quantile(xs: number[], p: number): number {\n const sorted = [...xs].sort((a, b) => a - b)\n const idx = p * (sorted.length - 1)\n const lo = Math.floor(idx)\n const hi = Math.ceil(idx)\n return sorted[lo]! + (sorted[hi]! - sorted[lo]!) * (idx - lo)\n}\n","/**\n * One-shot deprecation warnings. A deprecated surface warns the FIRST time it\n * is used in a process — loud enough to be seen, quiet enough not to flood a\n * matrix run that constructs it per cell.\n */\n\nconst warned = new Set<string>()\n\n/** Emit `message` on console.warn once per process per `key`. */\nexport function warnDeprecatedOnce(key: string, message: string): void {\n if (warned.has(key)) return\n warned.add(key)\n console.warn(`[agent-eval deprecation] ${message}`)\n}\n\n/** Test seam: forget prior warnings so once-semantics can be asserted. */\nexport function resetDeprecationWarnings(): void {\n warned.clear()\n}\n","import { warnDeprecatedOnce } from './deprecation'\nimport type { CheckResult, ProductClientConfig, RouteMap, TestResult } from './types'\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000\n\n/**\n * ProductClient — configurable HTTP client for exercising any agent's APIs.\n *\n * Routes are config, not hardcoded. Each agent provides its own RouteMap.\n *\n * @deprecated A one-product REST client does not belong in the generic\n * substrate. Moves to the product repo in the next major\n * (tangle-network/agent-runtime#694); vendor it if you construct it directly.\n */\nexport class ProductClient {\n private baseUrl: string\n private routes: RouteMap\n private cookies: string = ''\n private timeoutMs: number\n\n constructor(config: ProductClientConfig) {\n warnDeprecatedOnce(\n 'ProductClient',\n 'ProductClient is deprecated and moves to the product repo in the next major (tangle-network/agent-runtime#694).',\n )\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this.routes = config.routes\n this.timeoutMs = config.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS\n }\n\n private route(name: keyof RouteMap): string {\n const path = this.routes[name]\n if (!path) throw new Error(`Route \"${name}\" not configured`)\n return path\n }\n\n /**\n * Single HTTP boundary for every JSON request. Aborts after `timeoutMs`,\n * checks `res.ok` BEFORE parsing, and throws `${method} ${path} failed:\n * HTTP ${status} — ${body}` on a non-ok response so a 4xx/5xx error body\n * can never be parsed as a success shape. Callers inspect the resolved\n * value only after a successful return.\n */\n private async request(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs)\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n Origin: this.baseUrl,\n Cookie: this.cookies,\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n signal: controller.signal,\n })\n } finally {\n clearTimeout(timeout)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`${method} ${path} failed: HTTP ${res.status} — ${text.slice(0, 500)}`)\n }\n return res.json() as Promise<Record<string, unknown>>\n }\n\n /**\n * Read a required collection field. A missing/non-array field is a contract\n * violation (wrong route, drift, partial body) — surface it loud instead of\n * masking it as a healthy empty set. A genuinely empty `[]` passes through.\n */\n private requireArray<T>(res: Record<string, unknown>, field: string): T[] {\n const value = res[field]\n if (!Array.isArray(value)) {\n throw new Error(\n `Response missing array field \"${field}\" (got ${typeof value}: ${JSON.stringify(value)?.slice(0, 200)})`,\n )\n }\n return value as T[]\n }\n\n async signup(name: string, email: string, password: string): Promise<{ userId: string }> {\n const res = await this.post(this.route('signup'), { name, email, password })\n const user = res.user as Record<string, unknown> | undefined\n if (!user?.id) throw new Error(`Signup failed: ${JSON.stringify(res)}`)\n return { userId: user.id as string }\n }\n\n async login(email: string, password: string): Promise<void> {\n const res = await fetch(`${this.baseUrl}${this.route('login')}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Origin: this.baseUrl },\n body: JSON.stringify({ email, password }),\n redirect: 'manual',\n })\n const setCookie = res.headers.get('set-cookie')\n if (setCookie) {\n this.cookies = setCookie.split(';')[0] ?? ''\n }\n const body = (await res.json()) as Record<string, unknown>\n if (!body.user) throw new Error(`Login failed: ${JSON.stringify(body)}`)\n }\n\n async createWorkspace(name: string, type = 'project'): Promise<string> {\n const res = await this.post(this.route('workspaces'), { name, type })\n const ws = res.workspace as Record<string, unknown> | undefined\n if (!ws?.id) throw new Error(`Workspace creation failed: ${JSON.stringify(res)}`)\n return ws.id as string\n }\n\n async createThread(workspaceId: string): Promise<string> {\n const res = await this.post(this.route('threads'), { workspaceId })\n const thread = res.thread as Record<string, unknown> | undefined\n if (!thread?.id) throw new Error(`Thread creation failed: ${JSON.stringify(res)}`)\n return thread.id as string\n }\n\n async chat(\n workspaceId: string,\n threadId: string,\n content: string,\n _opts?: { blockPatterns?: RegExp[] },\n ): Promise<{ text: string; blocks: { type: string; title: string }[] }> {\n const res = await fetch(`${this.baseUrl}${this.route('chat')}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Origin: this.baseUrl,\n Cookie: this.cookies,\n },\n body: JSON.stringify({ workspaceId, threadId, content }),\n })\n\n if (!res.ok || !res.body) throw new Error(`Chat failed: ${res.status}`)\n\n // Parse NDJSON stream\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n let text = ''\n const blocks: { type: string; title: string }[] = []\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buf += decoder.decode(value, { stream: true })\n const lines = buf.split('\\n')\n buf = lines.pop() ?? ''\n for (const line of lines) {\n if (!line.trim()) continue\n try {\n const event = JSON.parse(line) as { type?: string; data?: { delta?: string } }\n if (event.type === 'message.part.updated' && event.data?.delta) {\n text += event.data.delta\n }\n } catch {\n /* skip non-JSON lines */\n }\n }\n }\n\n // Extract :::blocks from text\n const blockRe = /:::(\\w+)\\s*\\n([\\s\\S]*?)\\n\\s*:::/g\n let match: RegExpExecArray | null = blockRe.exec(text)\n while (match !== null) {\n const fields: Record<string, string> = {}\n for (const line of match[2]!.split('\\n')) {\n const idx = line.indexOf(':')\n if (idx > 0) fields[line.slice(0, idx).trim()] = line.slice(idx + 1).trim()\n }\n blocks.push({ type: match[1]!, title: fields.title ?? '' })\n match = blockRe.exec(text)\n }\n\n return { text, blocks }\n }\n\n async getTasks(\n workspaceId: string,\n ): Promise<{ id: string; title: string; status: string; priority: string }[]> {\n const res = await this.get(`${this.route('tasks')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; status: string; priority: string }>(\n res,\n 'tasks',\n )\n }\n\n async getEvents(workspaceId: string): Promise<{ id: string; title: string; type: string }[]> {\n const res = await this.get(`${this.route('events')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; type: string }>(res, 'events')\n }\n\n async getApprovals(\n workspaceId: string,\n ): Promise<{ id: string; title: string; status: string; type: string }[]> {\n const res = await this.get(`${this.route('approvals')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; status: string; type: string }>(\n res,\n 'actions',\n )\n }\n\n async getVaultTree(workspaceId: string): Promise<string[]> {\n const res = await this.get(`${this.route('vault')}?workspaceId=${workspaceId}`)\n const paths: string[] = []\n function extract(nodes: unknown[]) {\n for (const n of nodes) {\n const node = n as { path?: string; type?: string; children?: unknown[] }\n if (node.type === 'file' && node.path) paths.push(node.path)\n if (node.children) extract(node.children)\n }\n }\n extract(this.requireArray<unknown>(res, 'tree'))\n return paths\n }\n\n async approveAction(workspaceId: string, id: string): Promise<void> {\n await this.patch(this.route('approvals'), { workspaceId, id, status: 'approved' })\n }\n\n async rejectAction(workspaceId: string, id: string, reason: string): Promise<void> {\n await this.patch(this.route('approvals'), { workspaceId, id, status: 'rejected', reason })\n }\n\n async getGenerations(\n workspaceId: string,\n ): Promise<{ id: string; type: string; prompt: string }[]> {\n const res = await this.get(`${this.route('generations')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; type: string; prompt: string }>(res, 'generations')\n }\n\n /** Generic GET for custom routes */\n async get(path: string): Promise<Record<string, unknown>> {\n return this.request('GET', path)\n }\n\n /** Generic POST for custom routes */\n async post(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n return this.request('POST', path, body)\n }\n\n /** Generic PATCH for custom routes */\n async patch(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n return this.request('PATCH', path, body)\n }\n}\n\n/**\n * Run a full e2e workflow test against a live product.\n *\n * The `workflow` callback receives a ProductClient and returns CheckResults.\n * This is the generic harness — each agent defines its own workflow steps.\n */\nexport async function runE2EWorkflow(\n client: ProductClient,\n name: string,\n workflow: (client: ProductClient) => Promise<CheckResult[]>,\n): Promise<TestResult> {\n const start = Date.now()\n const checks: CheckResult[] = []\n\n try {\n const results = await workflow(client)\n checks.push(...results)\n } catch (err) {\n checks.push({\n name: 'fatal_error',\n passed: false,\n expected: 'no crash',\n actual: err instanceof Error ? err.message : String(err),\n })\n }\n\n return {\n name,\n passed: checks.every((c) => c.passed),\n duration: Date.now() - start,\n detail: `${checks.filter((c) => c.passed).length}/${checks.length} checks passed`,\n checks,\n }\n}\n","/**\n * CommandRunner — abstract subprocess execution surface.\n *\n * Layers in a {@link MultiLayerVerifier} that need to invoke external\n * tools (compilers, test runners, package managers) call out via this\n * interface rather than directly using `child_process`. Two reasons:\n *\n * 1. **Sandbox interchangeability.** A run that targets a sandbox box\n * (via SDK-specific Box.exec) and a run that targets the host both\n * satisfy this same contract. The harness doesn't care which.\n * 2. **Testability.** Tests inject a fake runner and assert on calls\n * without spawning real subprocesses.\n *\n * agent-eval ships only the local implementation (host-process). Sandbox\n * implementations live with their consumer because they depend on\n * SDK-specific Box / Sandbox types that don't belong in this package.\n */\n\nimport {\n accessSync,\n existsSync,\n constants as fsConstants,\n readdirSync,\n readFileSync,\n statSync,\n} from 'node:fs'\nimport { delimiter, join } from 'node:path'\nimport { DEFAULT_BOUNDED_PROCESS_TIMEOUT_MS, runBoundedProcess } from './bounded-process'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface RunCommandInput {\n /** Executable name, looked up via PATH unless absolute. */\n cmd: string\n /** Argument vector, NOT shell-interpolated. Each element passed to argv. */\n argv: string[]\n /** Working directory. Defaults to runner's notion of cwd if omitted. */\n cwd?: string\n /**\n * Wall-clock cap in ms. The runner SHOULD return `timedOut: true` when\n * exceeded; callers MAY treat status null + timedOut as \"killed.\"\n *\n * Omitting it does NOT mean unbounded: {@link localCommandRunner} then\n * applies {@link LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS}. A command that\n * legitimately runs longer than that names its own `capMs`; it is never\n * killed silently, because a run stopped by the bound comes back with\n * `timedOut: true` and `status: null`.\n */\n capMs?: number\n /** Env overrides merged on top of the runner's base environment. */\n env?: Record<string, string>\n /** Optional stdin payload. */\n stdin?: string\n}\n\nexport interface RunCommandResult {\n /** Exit code, or null when the process couldn't start / was killed. */\n status: number | null\n stdout: string\n stderr: string\n durationMs: number\n timedOut: boolean\n /** Non-fatal runner-side error (binary missing, signal, etc.). */\n runnerError?: string\n}\n\nexport interface DirEntry {\n name: string\n isDirectory: boolean\n isFile: boolean\n /** File size in bytes. `null` for directories (not stat'd). */\n sizeBytes: number | null\n}\n\nexport interface CommandRunner {\n /** Identifier for telemetry + logs. Open-ended literal-union for new runners. */\n readonly name: string\n /** Execute a command in the runner's environment. */\n run(input: RunCommandInput): Promise<RunCommandResult>\n /** True iff `<name>` resolves on the runner's PATH. */\n hasBin(name: string): Promise<boolean>\n /** True iff the given path exists in the runner's filesystem. */\n fileExists(path: string): Promise<boolean>\n /** Read a file. Returns `null` if missing or unreadable. */\n readFile(path: string): Promise<string | null>\n /** List a directory. Returns `[]` if unreadable / missing. */\n readDir(path: string): Promise<DirEntry[]>\n}\n\n// ─── Local runner ───────────────────────────────────────────────────────\n\n/**\n * Host-process runner, mapped onto {@link runBoundedProcess} so the package\n * has one spawn site rather than two.\n *\n * It used `spawnSync` and therefore had none of the bounds that runner exists\n * to provide: a `capMs` timeout killed the direct child and left any\n * descendant it had started running, a killed run could still report exit\n * code 0, captured output was unbounded, and the whole run blocked the event\n * loop. This runner spawns build, test and lint commands, which are exactly\n * the commands most likely to start descendants.\n *\n * It is not the package's last private spawn: `nodeProcessRunner`\n * (`src/trace-repair/docker-environment.ts`) and `runProcess`\n * (`src/campaign/external-optimizer-subprocess.ts`) still spawn their own\n * detached children, and several one-shot `spawnSync` git and CLI calls\n * remain. What this removes is the second spawn behind the `CommandRunner`\n * contract, which is the one that graded build, test and lint commands.\n *\n * Two behaviours the mapping changes on purpose:\n * - a run with no `capMs` is now bounded by\n * {@link LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS} instead of running forever;\n * - the run no longer blocks the event loop, so a minutes-long `capMs` no\n * longer stalls everything else in the process.\n */\n/**\n * Wall clock {@link localCommandRunner} applies when the caller names no\n * `capMs`. It is `runBoundedProcess`'s own default, stated here because this\n * runner used to be unbounded: a consumer whose command runs longer names its\n * own `capMs`, and a run the bound stops says so with `timedOut: true`.\n */\nexport const LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS = DEFAULT_BOUNDED_PROCESS_TIMEOUT_MS\n\nexport const localCommandRunner: CommandRunner = {\n name: 'local',\n async run(input: RunCommandInput): Promise<RunCommandResult> {\n const result = await runBoundedProcess({\n command: input.cmd,\n args: input.argv,\n envMode: 'merge',\n env: { CI: '1', ...(input.env ?? {}) },\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n ...(input.capMs === undefined ? {} : { timeoutMs: input.capMs }),\n ...(input.stdin === undefined ? {} : { stdin: input.stdin }),\n })\n // `status: null` keeps its documented meaning — the process could not\n // start, or it was killed. A stdin payload the child did not drain is\n // neither: that command ran and exited on its own, so it keeps its code.\n const killed = result.killedByTimeout || result.killedBySignal\n return {\n status: killed || !result.spawned ? null : result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n durationMs: result.wallMs,\n timedOut: result.killedByTimeout,\n ...(result.runnerError === undefined ? {} : { runnerError: result.runnerError }),\n }\n },\n async hasBin(name: string): Promise<boolean> {\n return resolveBinOnPath(name) !== null\n },\n async fileExists(path: string): Promise<boolean> {\n return existsSync(path)\n },\n async readFile(path: string): Promise<string | null> {\n try {\n return readFileSync(path, 'utf8')\n } catch (err) {\n // ENOENT is the only \"legitimately absent\" signal → null. Any other\n // errno (EACCES, EISDIR, EIO, …) is a real failure that must NOT\n // masquerade as \"file not present\" — surface it so callers don't\n // treat a permission/IO error as a missing artifact.\n if (isErrnoCode(err, 'ENOENT')) return null\n throw err\n }\n },\n async readDir(path: string): Promise<DirEntry[]> {\n let entries: string[]\n try {\n entries = readdirSync(path)\n } catch (err) {\n // Same ENOENT-vs-real-error split as readFile: a missing directory\n // is legitimately empty (→ []); EACCES/ENOTDIR/EIO must surface so\n // an unreadable directory isn't silently reported as having no files.\n if (isErrnoCode(err, 'ENOENT')) return []\n throw err\n }\n const out: DirEntry[] = []\n for (const name of entries) {\n try {\n const st = statSync(join(path, name))\n out.push({\n name,\n isDirectory: st.isDirectory(),\n isFile: st.isFile(),\n sizeBytes: st.isFile() ? st.size : null,\n })\n } catch (err) {\n // An entry that vanished between readdir and stat (TOCTOU) is a\n // benign race → skip. Any other errno surfaces.\n if (isErrnoCode(err, 'ENOENT')) continue\n throw err\n }\n }\n return out\n },\n}\n\nfunction isErrnoCode(err: unknown, code: NodeJS.ErrnoException['code']): boolean {\n return typeof err === 'object' && err !== null && (err as NodeJS.ErrnoException).code === code\n}\n\n/**\n * Resolve `name` to an executable absolute path using the runner's PATH,\n * or `null` if not found. Cross-platform: does not depend on `which`\n * (absent on Windows) or a `command -v` shell (absent on minimal\n * containers). On Windows, candidate extensions come from PATHEXT.\n *\n * Throws only on a non-ENOENT/EACCES filesystem error while probing a\n * candidate — those indicate a real IO fault, not \"binary absent.\"\n */\nfunction resolveBinOnPath(name: string): string | null {\n // An explicit path component means PATH lookup doesn't apply: probe directly.\n if (name.includes('/') || name.includes('\\\\')) {\n return isExecutable(name) ? name : null\n }\n const pathEnv = process.env.PATH ?? ''\n const dirs = pathEnv.split(delimiter).filter((d) => d.length > 0)\n const exts =\n process.platform === 'win32'\n ? (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';').filter((e) => e.length > 0)\n : ['']\n for (const dir of dirs) {\n for (const ext of exts) {\n const candidate = join(dir, name + ext)\n if (isExecutable(candidate)) return candidate\n }\n }\n return null\n}\n\nfunction isExecutable(path: string): boolean {\n try {\n // On win32 X_OK is a no-op; presence of the file (with a PATHEXT\n // extension) is the executability signal there.\n accessSync(path, process.platform === 'win32' ? fsConstants.F_OK : fsConstants.X_OK)\n return true\n } catch (err) {\n // Not found / not executable / not permitted → \"not a usable binary\n // here,\" keep scanning. A different errno (EIO, ELOOP, …) is a real\n // fault and must surface rather than silently yield a false negative.\n if (isErrnoCode(err, 'ENOENT') || isErrnoCode(err, 'EACCES') || isErrnoCode(err, 'ENOTDIR')) {\n return false\n }\n throw err\n }\n}\n","/**\n * Streaming detectors — the canonical, online failure-mode kernel.\n *\n * A `StreamingDetector` is a pure incremental reducer: fold one normalized step, get a signal the\n * moment a threshold trips (else null). The SAME kernel runs in two places, so the logic lives once:\n * - ONLINE, over a live agent pipe (a worker's tool-call stream) → raise a finding mid-run.\n * - INSIDE the control loop (`control-runtime`) → its `stopOn*` policies fold these detectors.\n *\n * Detectors are stateful but self-contained; `streak` is exposed for telemetry and `reset` clears it.\n * Fingerprinting is the CALLER's job — the control loop hashes state/action with `stableFingerprint`,\n * a tool-call pipe hashes args with `argHash` — so a detector stays agnostic to what it's watching.\n */\n\nimport type { FailureClass } from '../trace/schema'\n\nexport type DetectorSeverity = 'info' | 'warn' | 'critical'\n\n/** A normalized step a detector folds over. Fields are optional; each detector reads only what it\n * needs (repeated-action → `actionFingerprint`; no-progress → `stateFingerprint` + `score`;\n * error-streak → `status`). */\nexport interface DetectorEvent {\n /** Fingerprint of the action/tool-call this step took (caller pre-hashes). */\n readonly actionFingerprint?: string\n /** Fingerprint of observable state AFTER this step. */\n readonly stateFingerprint?: string\n /** Score after this step (the score-flat half of no-progress). */\n readonly score?: number\n /** Whether this step errored. */\n readonly status?: 'ok' | 'error'\n /** Free-form label carried into the signal evidence (e.g. the tool name). */\n readonly label?: string\n}\n\nexport interface DetectorSignal {\n readonly detector: string\n readonly severity: DetectorSeverity\n readonly failureClass?: FailureClass\n readonly reason: string\n /** Consecutive matching steps at the moment the signal fired. */\n readonly streak: number\n readonly evidence?: Record<string, unknown>\n}\n\nexport interface StreamingDetector {\n readonly id: string\n /** Current streak (consecutive matching steps) — for telemetry/introspection between observes. */\n readonly streak: number\n /** Fold one event; return a signal when the threshold trips, else null. */\n observe(event: DetectorEvent): DetectorSignal | null\n /** Clear all state. */\n reset(): void\n}\n\nexport interface RepeatedActionOptions {\n /** Signal once the same action fingerprint repeats this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal (the streak is still tracked, for telemetry). */\n readonly maxRepeated?: number\n readonly severity?: DetectorSeverity\n /** Failure class to stamp on the signal (default `tool_recovery_failure`). */\n readonly failureClass?: FailureClass\n}\n\n/** Same action fingerprint N consecutive steps = a stuck loop (the #1 long-horizon failure mode). */\nexport function repeatedActionDetector(opts: RepeatedActionOptions = {}): StreamingDetector {\n const max = opts.maxRepeated ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let last: string | undefined\n let streak = 0\n return {\n id: 'repeated-action',\n get streak() {\n return streak\n },\n observe(event) {\n const fp = event.actionFingerprint\n if (fp === undefined) return null\n streak = fp === last ? streak + 1 : 1\n last = fp\n if (max <= 0 || streak < max) return null\n return {\n detector: 'repeated-action',\n severity,\n failureClass,\n reason: `stuck: repeated same action for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { action: event.label } } : {}),\n }\n },\n reset() {\n last = undefined\n streak = 0\n },\n }\n}\n\nexport interface NoProgressOptions {\n /** Signal once state is unchanged AND score is flat for this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal. */\n readonly maxNoProgress?: number\n /** Minimum |score change| that counts as progress (default 0.001). */\n readonly minScoreDelta?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** State + score unchanged across N steps = spinning wheels. Compares each step to the previous one,\n * so prime with the initial state (observe it once before the first real step) to detect on step 1. */\nexport function noProgressDetector(opts: NoProgressOptions = {}): StreamingDetector {\n const max = opts.maxNoProgress ?? 3\n const minScoreDelta = opts.minScoreDelta ?? 0.001\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let lastState: string | undefined\n let lastScore: number | undefined\n let streak = 0\n return {\n id: 'no-progress',\n get streak() {\n return streak\n },\n observe(event) {\n const stateUnchanged = lastState !== undefined && lastState === event.stateFingerprint\n const scoreFlat = Math.abs((event.score ?? 0) - (lastScore ?? 0)) < minScoreDelta\n streak = stateUnchanged && scoreFlat ? streak + 1 : 0\n lastState = event.stateFingerprint\n lastScore = event.score\n if (max <= 0 || streak < max) return null\n return {\n detector: 'no-progress',\n severity,\n failureClass,\n reason: `stuck: no state/score progress for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { state: event.label } } : {}),\n }\n },\n reset() {\n lastState = undefined\n lastScore = undefined\n streak = 0\n },\n }\n}\n\nexport interface ErrorStreakOptions {\n /** Signal once this many CONSECUTIVE steps errored (default 3). `<= 0` disables. */\n readonly maxErrors?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** N consecutive tool errors = the worker is hammering a broken approach. */\nexport function errorStreakDetector(opts: ErrorStreakOptions = {}): StreamingDetector {\n const max = opts.maxErrors ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let streak = 0\n return {\n id: 'error-streak',\n get streak() {\n return streak\n },\n observe(event) {\n if (event.status === undefined) return null\n streak = event.status === 'error' ? streak + 1 : 0\n if (max <= 0 || streak < max) return null\n return {\n detector: 'error-streak',\n severity,\n failureClass,\n reason: `stuck: ${streak} consecutive errored step(s)`,\n streak,\n ...(event.label ? { evidence: { lastError: event.label } } : {}),\n }\n },\n reset() {\n streak = 0\n },\n }\n}\n\n/** Fold one event through many detectors at once; returns every signal that fired this step. The\n * natural shape for an online pipe watching with a whole panel of detectors. */\nexport function observeAll(\n detectors: ReadonlyArray<StreamingDetector>,\n event: DetectorEvent,\n): DetectorSignal[] {\n const signals: DetectorSignal[] = []\n for (const d of detectors) {\n const s = d.observe(event)\n if (s) signals.push(s)\n }\n return signals\n}\n","/**\n * Policy-based agent control runtime.\n *\n * This is the minimal reusable loop behind driver-agent patterns:\n *\n * observe state -> validate -> decide next action -> act -> observe -> ...\n *\n * It deliberately does not model named \"topologies\". Direct execution,\n * critic/revise, driver intervention, specialist calls, and human escalation\n * are all just actions chosen by the control policy.\n */\n\nimport { noProgressDetector, repeatedActionDetector } from './detectors'\nimport { canonicalString } from './ledger-core/canonical'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport type ControlSeverity = 'info' | 'warning' | 'error' | 'critical'\nexport type ControlActionFailureMode = 'continue' | 'stop'\n\nexport interface ControlEvalResult {\n /** Stable validator or judge id. */\n id: string\n /** Whether this check passed. */\n passed: boolean\n /** Optional normalized score. 1 = best, 0 = worst. */\n score?: number\n /** Objective validators should usually be \"error\" or \"critical\" when failed. */\n severity?: ControlSeverity\n /** Human-readable result. */\n detail?: string\n /** Small evidence string or pointer. Avoid large payloads. */\n evidence?: string\n /** True when the result came from deterministic state, not LLM judgment. */\n objective?: boolean\n /** Structured details for downstream control policies and reports. */\n metadata?: Record<string, unknown>\n}\n\nexport interface ControlBudget {\n maxSteps: number\n maxWallMs?: number\n maxCostUsd?: number\n}\n\nexport interface ControlStopPolicies<TState, TAction> {\n /**\n * Stop after N consecutive steps with no state fingerprint change and\n * less than `minScoreDelta` score movement. Disabled when omitted.\n */\n maxNoProgressSteps?: number\n /**\n * Stop after the same action fingerprint is selected N consecutive\n * times. Disabled when omitted.\n */\n maxRepeatedActions?: number\n /** Minimum score movement that counts as progress. Default 0.001. */\n minScoreDelta?: number\n /** Override the default JSON/string fingerprint for state comparisons. */\n stateFingerprint?: (state: TState) => string\n /** Override the default JSON/string fingerprint for repeated-action checks. */\n actionFingerprint?: (action: TAction) => string\n}\n\nexport interface ControlContext<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n budget: ControlBudget\n stepIndex: number\n wallMs: number\n spentCostUsd: number\n remainingCostUsd?: number\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport type ControlDecision<TAction> =\n | {\n type: 'continue'\n action: TAction\n reason?: string\n }\n | {\n type: 'stop'\n reason: string\n pass?: boolean\n score?: number\n /** Canonical task-failure class when this stop represents a failed task. */\n failureClass?: FailureClass\n }\n\nexport interface StopDecision {\n stop: boolean\n pass: boolean\n reason: string\n score?: number\n failureClass?: FailureClass\n}\n\nexport interface ControlActionOutcome<TActionResult> {\n ok: boolean\n result?: TActionResult\n error?: string\n costUsd?: number\n durationMs: number\n}\n\nexport interface ControlRuntimeError {\n phase: 'observe' | 'validate' | 'decide' | 'act' | 'stop-policy' | 'on-step' | 'trace'\n stepIndex: number\n message: string\n}\n\nexport interface ControlStep<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n index: number\n decision: ControlDecision<TAction>\n beforeState: TState\n afterState: TState\n evalsBefore: TEval[]\n evalsAfter: TEval[]\n actionOutcome?: ControlActionOutcome<TActionResult>\n startedAt: string\n endedAt: string\n}\n\nexport interface ControlRunResult<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n pass: boolean\n completed: boolean\n reason: string\n score?: number\n steps: ControlStep<TState, TAction, TActionResult, TEval>[]\n finalState: TState | undefined\n finalEvals: TEval[]\n wallMs: number\n spentCostUsd: number\n /** null when the run executed without a TraceEmitter wired (no run record was persisted). */\n runId: string | null\n failureClass?: FailureClass\n runtimeErrors: ControlRuntimeError[]\n stoppedBy: 'policy' | 'stop-policy' | 'budget' | 'abort' | 'runtime-error'\n}\n\nexport interface ControlRuntimeConfig<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n budget?: Partial<ControlBudget>\n signal?: AbortSignal\n /** Defaults to `continue`: action failures are recorded, then the policy gets another chance. */\n actionFailure?: ControlActionFailureMode\n /**\n * Extract cost from an action result. Used for `maxCostUsd` budget\n * enforcement and trace budget ledger emission.\n */\n getActionCostUsd?: (ctx: {\n action: TAction\n result: TActionResult\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n }) => number | undefined\n\n /** Read typed task/product state. Prefer structured state over transcript-only context. */\n observe: (ctx: {\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TState> | TState\n\n /** Objective validators first, subjective judges only where objective state is insufficient. */\n validate: (ctx: {\n intent: string\n state: TState\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TEval[]> | TEval[]\n\n /** Choose the next control action. Can call a worker, ask user, run critic, inspect state, or stop. */\n decide: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<ControlDecision<TAction>> | ControlDecision<TAction>\n\n /** Execute the action selected by the policy. */\n act: (\n action: TAction,\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<TActionResult> | TActionResult\n\n /** Final stopping policy. Called before decide and after each action. */\n shouldStop?: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<StopDecision> | StopDecision\n\n /** Optional hook for tracing or live progress updates. */\n onStep?: (step: ControlStep<TState, TAction, TActionResult, TEval>) => Promise<void> | void\n\n /** Optional generic stuck-loop policies. Custom `shouldStop` still runs first. */\n stopPolicies?: ControlStopPolicies<TState, TAction>\n\n /** Optional trace sink. Emits one run plus one span per control step. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n}\n\nconst DEFAULT_BUDGET: ControlBudget = {\n maxSteps: 8,\n maxWallMs: 5 * 60 * 1000,\n}\n\nexport async function runAgentControlLoop<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n>(\n config: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n const budget = normalizeBudget(config.budget)\n const actionFailure = config.actionFailure ?? 'continue'\n const controller = new AbortController()\n const upstreamAbort = () => controller.abort(config.signal?.reason)\n if (config.signal) {\n if (config.signal.aborted) controller.abort(config.signal.reason)\n else config.signal.addEventListener('abort', upstreamAbort, { once: true })\n }\n\n const started = Date.now()\n const wallTimer = budget.maxWallMs\n ? setTimeout(\n () => controller.abort(new Error('control runtime wall timeout')),\n budget.maxWallMs,\n )\n : undefined\n const history: ControlStep<TState, TAction, TActionResult, TEval>[] = []\n const emitter = config.store ? new TraceEmitter(config.store) : undefined\n let spentCostUsd = 0\n const runtimeErrors: ControlRuntimeError[] = []\n // The stuck-detection kernels (shared with the online detectors). Thresholds 0 = disabled; the\n // streak is still tracked for telemetry. Both stops report `tool_recovery_failure`.\n const repeatedDetector = repeatedActionDetector({\n maxRepeated: config.stopPolicies?.maxRepeatedActions ?? 0,\n })\n const progressDetector = noProgressDetector({\n maxNoProgress: config.stopPolicies?.maxNoProgressSteps ?? 0,\n minScoreDelta: config.stopPolicies?.minScoreDelta ?? 0.001,\n })\n\n try {\n if (emitter) {\n await runTrace(runtimeErrors, 0, () =>\n emitter.startRun({\n scenarioId: config.scenarioId ?? 'agent-control-loop',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n intent: config.intent.slice(0, 120),\n maxSteps: String(budget.maxSteps),\n ...(budget.maxCostUsd !== undefined ? { maxCostUsd: String(budget.maxCostUsd) } : {}),\n },\n }),\n )\n }\n\n let state: TState\n let evals: TEval[]\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n const error = runtimeError('observe', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(emitter, evals, 'initial', runtimeErrors, 0)\n } catch (err) {\n const error = runtimeError('validate', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: state,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n // Prime the no-progress detector with the initial state + score so step 0 can already detect a\n // no-op (mirrors the pre-loop fingerprint baseline). The priming observe never signals (streak 0).\n progressDetector.observe({\n stateFingerprint: fingerprintState(state, config.stopPolicies),\n score: averageScore(evals),\n })\n\n for (let stepIndex = 0; stepIndex < budget.maxSteps; stepIndex++) {\n if (controller.signal.aborted) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: abortReason(controller.signal),\n score: undefined,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'timeout',\n runtimeErrors,\n stoppedBy: 'abort',\n })\n }\n\n const budgetStop = budgetStopDecision(budget, spentCostUsd)\n if (budgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: budgetStop.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const ctx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let stop: StopDecision\n try {\n stop = config.shouldStop ? await config.shouldStop(ctx) : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (stop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: stop.pass,\n completed: true,\n reason: stop.reason,\n score: stop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: stop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n let decision: ControlDecision<TAction>\n try {\n decision = await config.decide(ctx)\n } catch (err) {\n runtimeErrors.push(runtimeError('decide', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (decision.type === 'stop') {\n const pass = decision.pass ?? false\n return finish(emitter, {\n intent: config.intent,\n pass,\n completed: true,\n reason: decision.reason,\n score: decision.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: pass ? undefined : (decision.failureClass ?? 'unknown'),\n runtimeErrors,\n stoppedBy: 'policy',\n })\n }\n\n const actionFingerprint = fingerprintAction(decision.action, config.stopPolicies)\n const repeatedActionSignal = repeatedDetector.observe({ actionFingerprint })\n const repeatedActionStreak = repeatedDetector.streak\n if (repeatedActionSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: repeatedActionSignal.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const beforeState = state\n const evalsBefore = evals\n const scoreBefore = averageScore(evals)\n const actionStarted = Date.now()\n const stepHandle = emitter\n ? await runTrace(runtimeErrors, stepIndex, () =>\n emitter.tool({\n name: `control-step-${stepIndex}`,\n toolName: 'agent-control-action',\n args: decision.action,\n attributes: {\n decision: decision.reason ?? 'continue',\n repeatedActionStreak,\n },\n }),\n )\n : undefined\n let actionOutcome: ControlActionOutcome<TActionResult>\n try {\n const result = await config.act(decision.action, ctx)\n const rawCostUsd = config.getActionCostUsd?.({\n action: decision.action,\n result,\n state,\n evals,\n history,\n })\n const costUsd = normalizeActionCostUsd(rawCostUsd, runtimeErrors, stepIndex)\n if (costUsd !== undefined && Number.isFinite(costUsd) && costUsd > 0) {\n spentCostUsd += costUsd\n await recordCostBudget(\n emitter,\n budget,\n spentCostUsd,\n stepHandle,\n runtimeErrors,\n stepIndex,\n )\n }\n actionOutcome = {\n ok: true,\n result,\n ...(costUsd !== undefined ? { costUsd } : {}),\n durationMs: Date.now() - actionStarted,\n }\n } catch (err) {\n runtimeErrors.push(runtimeError('act', stepIndex, err))\n actionOutcome = {\n ok: false,\n error: runtimeErrors[runtimeErrors.length - 1]!.message,\n durationMs: Date.now() - actionStarted,\n }\n if (actionFailure === 'stop') {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed'),\n )\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: actionOutcome.error ?? 'action failed',\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n }\n\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n runtimeErrors.push(runtimeError('observe', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: beforeState,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: beforeState,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(\n emitter,\n evals,\n `step-${stepIndex}`,\n runtimeErrors,\n stepIndex,\n stepHandle?.span.spanId,\n )\n } catch (err) {\n runtimeErrors.push(runtimeError('validate', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n const scoreAfter = averageScore(evals)\n const stateFingerprint = fingerprintState(state, config.stopPolicies)\n const noProgressSignal = progressDetector.observe({ stateFingerprint, score: scoreAfter })\n const noProgressStreak = progressDetector.streak\n\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n if (actionOutcome.ok) {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.end({\n attributes: {\n actionCostUsd: actionOutcome.costUsd ?? null,\n spentCostUsd,\n scoreBefore: scoreBefore ?? null,\n scoreAfter: scoreAfter ?? null,\n noProgressStreak,\n },\n }),\n )\n } else {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed', {\n attributes: {\n spentCostUsd,\n noProgressStreak,\n },\n }),\n )\n }\n await runOnStep(config.onStep, step, runtimeErrors)\n\n if (noProgressSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: noProgressSignal.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const postStepBudgetStop = budgetStopDecision(budget, spentCostUsd)\n if (postStepBudgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: postStepBudgetStop.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const postStepCtx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex + 1,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let postStepStop: StopDecision\n try {\n postStepStop = config.shouldStop\n ? await config.shouldStop(postStepCtx)\n : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex + 1, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (postStepStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: postStepStop.pass,\n completed: true,\n reason: postStepStop.reason,\n score: postStepStop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: postStepStop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n }\n\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: `budget exhausted: maxSteps=${budget.maxSteps}`,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n } catch (err) {\n runtimeErrors.push(runtimeError('act', history.length, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n } finally {\n if (wallTimer) clearTimeout(wallTimer)\n if (config.signal) config.signal.removeEventListener('abort', upstreamAbort)\n }\n}\n\nexport function stopOnNoProgress<TState, TAction>(\n maxNoProgressSteps: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxNoProgressSteps'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxNoProgressSteps }\n}\n\nexport function stopOnRepeatedAction<TState, TAction>(\n maxRepeatedActions: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxRepeatedActions'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxRepeatedActions }\n}\n\nexport function objectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: true }\n}\n\nexport function subjectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: false }\n}\n\nfunction normalizeBudget(input: Partial<ControlBudget> | undefined): ControlBudget {\n const raw = { ...DEFAULT_BUDGET, ...input } as Record<string, unknown>\n if (!Number.isInteger(raw.maxSteps) || (raw.maxSteps as number) < 1) {\n throw new RangeError(\n `ControlRuntime budget.maxSteps must be an integer >= 1, got ${String(raw.maxSteps)}`,\n )\n }\n const budget: ControlBudget = { maxSteps: raw.maxSteps as number }\n if (raw.maxWallMs !== undefined) {\n if (\n typeof raw.maxWallMs !== 'number' ||\n !Number.isFinite(raw.maxWallMs) ||\n raw.maxWallMs <= 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxWallMs must be a positive finite number, got ${String(raw.maxWallMs)}`,\n )\n }\n budget.maxWallMs = raw.maxWallMs\n }\n if (raw.maxCostUsd !== undefined) {\n if (\n typeof raw.maxCostUsd !== 'number' ||\n !Number.isFinite(raw.maxCostUsd) ||\n raw.maxCostUsd < 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxCostUsd must be a nonnegative finite number, got ${String(raw.maxCostUsd)}`,\n )\n }\n budget.maxCostUsd = raw.maxCostUsd\n }\n return budget\n}\n\nfunction normalizeActionCostUsd(\n costUsd: number | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): number | undefined {\n if (costUsd === undefined) return undefined\n if (!Number.isFinite(costUsd) || costUsd < 0) {\n runtimeErrors.push(\n runtimeError('act', stepIndex, new Error(`invalid action costUsd: ${String(costUsd)}`)),\n )\n return undefined\n }\n return costUsd\n}\n\nexport function allCriticalPassed(evals: ControlEvalResult[]): boolean {\n return evals.every(\n (result) => result.passed || (result.severity !== 'critical' && result.severity !== 'error'),\n )\n}\n\nfunction makeContext<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n intent: string,\n state: TState,\n evals: TEval[],\n history: ControlStep<TState, TAction, TActionResult, TEval>[],\n budget: ControlBudget,\n stepIndex: number,\n started: number,\n spentCostUsd: number,\n abortSignal: AbortSignal,\n emitter?: TraceEmitter,\n): ControlContext<TState, TAction, TActionResult, TEval> {\n return {\n intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n wallMs: Date.now() - started,\n spentCostUsd,\n remainingCostUsd:\n budget.maxCostUsd === undefined ? undefined : Math.max(0, budget.maxCostUsd - spentCostUsd),\n abortSignal,\n emitter,\n }\n}\n\nfunction defaultStopDecision(evals: ControlEvalResult[]): StopDecision {\n if (!evals.length) return { stop: false, pass: false, reason: 'no evals yet' }\n const pass = allCriticalPassed(evals)\n return pass\n ? { stop: true, pass: true, reason: 'all critical evals passed', score: averageScore(evals) }\n : {\n stop: false,\n pass: false,\n reason: 'critical evals still failing',\n score: averageScore(evals),\n }\n}\n\nfunction averageScore(evals: ControlEvalResult[]): number | undefined {\n const scored = evals\n .map((result) => result.score)\n .filter((score): score is number => typeof score === 'number')\n if (!scored.length) return undefined\n return Math.round((scored.reduce((sum, score) => sum + score, 0) / scored.length) * 1000) / 1000\n}\n\nfunction budgetStopDecision(\n budget: ControlBudget,\n spentCostUsd: number,\n): { stop: boolean; reason: string } {\n if (budget.maxCostUsd !== undefined && spentCostUsd >= budget.maxCostUsd) {\n return {\n stop: true,\n reason: `budget exhausted: maxCostUsd=${budget.maxCostUsd}`,\n }\n }\n return { stop: false, reason: '' }\n}\n\nasync function recordCostBudget(\n emitter: TraceEmitter | undefined,\n budget: ControlBudget,\n spentCostUsd: number,\n handle: SpanHandle | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): Promise<void> {\n if (!emitter || budget.maxCostUsd === undefined) return\n const maxCostUsd = budget.maxCostUsd\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordBudget({\n dimension: 'usd',\n limit: maxCostUsd,\n consumed: spentCostUsd,\n remaining: Math.max(0, maxCostUsd - spentCostUsd),\n breached: spentCostUsd >= maxCostUsd,\n spanId: handle?.span.spanId,\n }),\n )\n}\n\nasync function recordEvalSpans(\n emitter: TraceEmitter | undefined,\n evals: ControlEvalResult[],\n phase: string,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n targetSpanId?: string,\n): Promise<void> {\n if (!emitter) return\n for (const result of evals) {\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordJudge({\n judgeId: result.objective ? 'objective-validator' : 'subjective-judge',\n targetSpanId: targetSpanId ?? emitter.runId,\n name: `control-eval/${result.id}`,\n dimension: result.id,\n score: typeof result.score === 'number' ? result.score : result.passed ? 1 : 0,\n rationale: result.detail,\n evidence: result.evidence,\n attributes: {\n phase,\n passed: result.passed,\n severity: result.severity,\n objective: result.objective,\n },\n }),\n )\n }\n}\n\nasync function runOnStep<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n onStep: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>['onStep'] | undefined,\n step: ControlStep<TState, TAction, TActionResult, TEval>,\n runtimeErrors: ControlRuntimeError[],\n): Promise<void> {\n if (!onStep) return\n try {\n await onStep(step)\n } catch (err) {\n runtimeErrors.push(runtimeError('on-step', step.index, err))\n }\n}\n\nasync function runTrace<T>(\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n write: () => Promise<T | undefined> | T | undefined,\n): Promise<T | undefined> {\n try {\n return await write()\n } catch (err) {\n runtimeErrors.push(runtimeError('trace', stepIndex, err))\n return undefined\n }\n}\n\nfunction fingerprintState<TState, TAction>(\n state: TState,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.stateFingerprint) return policies.stateFingerprint(state)\n return stableFingerprint(state)\n}\n\nfunction fingerprintAction<TState, TAction>(\n action: TAction,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.actionFingerprint) return policies.actionFingerprint(action)\n return stableFingerprint(action)\n}\n\n/** Default state/action fingerprint: the value itself for a string, `String(value)`\n * for a number, boolean, null or undefined, and RFC 8785 canonical JSON for\n * everything else. A value with no canonical JSON form (an `undefined`-valued\n * field, a non-finite number, a class instance) throws: two states that differ\n * in such a field must not fingerprint alike, and a caller with such state\n * supplies `stopPolicies.stateFingerprint` / `actionFingerprint`. */\nfunction stableFingerprint(value: unknown): string {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || value == null) return String(value)\n return canonicalString(value)\n}\n\nfunction abortReason(signal: AbortSignal): string {\n const reason = signal.reason\n if (reason instanceof Error) return reason.message\n return reason ? String(reason) : 'aborted'\n}\n\nfunction runtimeError(\n phase: ControlRuntimeError['phase'],\n stepIndex: number,\n err: unknown,\n): ControlRuntimeError {\n const message = err instanceof Error ? err.message : String(err)\n return { phase, stepIndex, message }\n}\n\nasync function finish<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n emitter: TraceEmitter | undefined,\n result: ControlRunResult<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n await runTrace(result.runtimeErrors, result.steps.length, () =>\n emitter?.endRun({\n pass: result.pass,\n score: result.score ?? averageScore(result.finalEvals),\n failureClass: result.failureClass,\n notes: result.reason,\n }),\n )\n return result\n}\n","/**\n * Walk a personas directory and return every file matching the convention\n * `NN-slug.{yaml,yml,json,md}`. Sorted by filename so the numeric prefix\n * gives stable persona ordering for reproducibility. Consumers filter\n * through `include` / `exclude`.\n */\n\nimport { promises as fs } from 'node:fs'\nimport { basename, extname, join } from 'node:path'\n\nexport interface DiscoverPersonasOptions {\n /**\n * Regex applied to filenames. Files that don't match are skipped.\n * Default: `^[0-9]{2}-.+\\.(yaml|yml|json|md)$`.\n */\n pattern?: RegExp\n /**\n * Filenames (or basenames) to skip. Use this to exclude WIP / archived\n * personas without removing the file.\n */\n exclude?: readonly string[]\n /**\n * If set, return only personas whose basename contains one of these\n * substrings (post-pattern filter).\n */\n include?: readonly string[]\n /** Recurse into subdirectories. Default false. */\n recursive?: boolean\n}\n\nexport interface DiscoveredPersona {\n /** Absolute file path. */\n path: string\n /** Filename without directory. */\n filename: string\n /** Filename without extension — the conventional persona id. */\n id: string\n}\n\nconst DEFAULT_PATTERN = /^\\d{2}-.+\\.(yaml|yml|json|md)$/\n\nexport async function discoverPersonas(\n dir: string,\n opts: DiscoverPersonasOptions = {},\n): Promise<DiscoveredPersona[]> {\n const pattern = opts.pattern ?? DEFAULT_PATTERN\n const exclude = new Set(opts.exclude ?? [])\n const include = opts.include\n\n async function walk(d: string): Promise<DiscoveredPersona[]> {\n let entries: Array<{ name: string; isDir: boolean }>\n try {\n const raw = await fs.readdir(d, { withFileTypes: true })\n entries = raw.map((e) => ({ name: e.name, isDir: e.isDirectory() }))\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code === 'ENOENT') return []\n throw err\n }\n const out: DiscoveredPersona[] = []\n for (const entry of entries) {\n const full = join(d, entry.name)\n if (entry.isDir) {\n if (opts.recursive) out.push(...(await walk(full)))\n continue\n }\n if (!pattern.test(entry.name)) continue\n if (exclude.has(entry.name) || exclude.has(basename(entry.name, extname(entry.name))))\n continue\n if (include && include.length > 0) {\n const id = basename(entry.name, extname(entry.name))\n const matched = include.some((needle) => entry.name.includes(needle) || id.includes(needle))\n if (!matched) continue\n }\n out.push({\n path: full,\n filename: entry.name,\n id: basename(entry.name, extname(entry.name)),\n })\n }\n return out\n }\n\n const results = await walk(dir)\n results.sort((a, b) => a.filename.localeCompare(b.filename))\n return results\n}\n","/**\n * Propose / Verify / Review — the core multi-shot primitive.\n *\n * shot N: propose(state, priorReview) → new state\n * verify(state) → pass/fail, optional layers\n * review(state, verification, memory) → observations + next-shot\n * instruction + shouldContinue\n * memory.append(entry)\n *\n * Roles are strictly separated:\n *\n * - The WORKER is whatever the caller wraps in `propose`. It is\n * stateful — caller owns its resume/session mechanism.\n * - The VERIFIER grades the state. It produces the ground truth.\n * The reviewer cannot overturn or downgrade a verification layer.\n * - The REVIEWER is stateless per call. Its continuity is the\n * `ReviewMemoryStore` — durable JSONL by default, or any store\n * implementing the interface. It reads memory + trace summary +\n * verification and directs the NEXT proposer shot.\n *\n * This shape is load-bearing. The reviewer never grades; the verifier\n * never directs. Two processes, two prompts, two concerns — which is\n * what keeps the loop from confirmation-biasing itself into \"all\n * passed\" when it didn't.\n *\n * Short-circuits and soft-fails are both first-class:\n * - verify.pass === true → reviewer LLM call is skipped, memory\n * records a success entry, loop exits.\n * - review throws → the shot still counts; the loop uses the\n * last-known instruction (or `fallbackInstruction`) for the next\n * propose call. A transient reviewer failure must NEVER abort a\n * valid arc.\n *\n * Composable: `propose` itself can be another `runProposeReview` call.\n * That's the dogfooding path — a harness built on this primitive is in\n * turn evaluable by it.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface Verification {\n pass: boolean\n score?: number\n failingLayers?: string[]\n details?: unknown\n}\n\nexport interface Review {\n observations: string\n diagnosis: string\n nextShotInstruction: string\n shouldContinue: boolean\n confidence: number\n}\n\nexport interface ReviewMemoryEntry extends Review {\n shot: number\n timestamp: number\n verification: {\n pass: boolean\n score?: number\n failingLayers?: string[]\n }\n}\n\nexport interface ProposeInput<State> {\n shot: number\n goal: string\n state: State\n priorReview: Review | null\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport interface ProposeOutput<State, Summary = unknown> {\n state: State\n traceSummary?: Summary\n}\n\nexport interface ReviewInput<State, Summary = unknown> {\n shot: number\n goal: string\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n memory: ReviewMemoryEntry[]\n}\n\nexport type ProposeFn<State, Summary = unknown> = (\n input: ProposeInput<State>,\n) => Promise<ProposeOutput<State, Summary>>\n\nexport type VerifyFn<State> = (state: State) => Promise<Verification>\n\nexport type ReviewFn<State, Summary = unknown> = (\n input: ReviewInput<State, Summary>,\n) => Promise<Review>\n\nexport interface ReviewMemoryStore {\n load(): Promise<ReviewMemoryEntry[]>\n append(entry: ReviewMemoryEntry): Promise<void>\n}\n\nexport interface ProposeReviewConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n /** Hard shot cap. Default 10. */\n maxShots?: number\n /** Wall-clock cap in ms. Default 10 min. */\n maxWallMs?: number\n /**\n * If the reviewer returns confidence ≤ floor on `confidenceFloorWindow`\n * consecutive shots, terminate early. Default floor 0.3, window 2.\n * Set window to 0 or floor to <0 to disable.\n */\n confidenceFloor?: number\n confidenceFloorWindow?: number\n /** Defaults to an in-memory store if omitted. */\n memory?: ReviewMemoryStore\n /** If provided, emit a Run + per-shot spans. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n /**\n * Used when the reviewer soft-fails on shot 1 (no prior instruction to\n * fall back to). Default is a generic \"inspect failures and fix\".\n */\n fallbackInstruction?: string\n}\n\nexport interface ProposeReviewShot<State, Summary = unknown> {\n shot: number\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n review: Review\n reviewAvailable: boolean\n reviewError?: string\n durationMs: number\n}\n\nexport interface ProposeReviewReport<State, Summary = unknown> {\n runId: string | null\n completed: boolean\n shots: ProposeReviewShot<State, Summary>[]\n finalState: State\n finalVerification: Verification\n failureClass?: FailureClass\n wallMs: number\n score: number\n}\n\n// ── Memory stores ────────────────────────────────────────────────────\n\nexport function inMemoryReviewStore(initial: ReviewMemoryEntry[] = []): ReviewMemoryStore {\n const entries: ReviewMemoryEntry[] = [...initial]\n return {\n async load() {\n return [...entries]\n },\n async append(entry) {\n entries.push(entry)\n },\n }\n}\n\nexport function jsonlReviewStore(path: string): ReviewMemoryStore {\n return {\n async load() {\n if (!existsSync(path)) return []\n const raw = readFileSync(path, 'utf8')\n const out: ReviewMemoryEntry[] = []\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n out.push(JSON.parse(trimmed) as ReviewMemoryEntry)\n } catch {\n // A corrupt line is an observability problem, not a correctness\n // one — skip it rather than aborting the loop.\n }\n }\n return out\n },\n async append(entry) {\n mkdirSync(dirname(path), { recursive: true })\n appendFileSync(path, `${JSON.stringify(entry)}\\n`)\n },\n }\n}\n\n// ── Core loop ────────────────────────────────────────────────────────\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReview<State, Summary = unknown>(\n config: ProposeReviewConfig<State, Summary>,\n): Promise<ProposeReviewReport<State, Summary>> {\n const maxShots = config.maxShots ?? 10\n const maxWallMs = config.maxWallMs ?? 10 * 60 * 1000\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n\n const emitter = config.store ? new TraceEmitter(config.store) : null\n if (emitter) {\n await emitter.startRun({\n scenarioId: config.scenarioId ?? 'propose-review',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n goal: config.goal.slice(0, 120),\n maxShots: String(maxShots),\n },\n })\n }\n\n const abort = new AbortController()\n const wallStart = Date.now()\n const wallTimer = setTimeout(\n () => abort.abort(new Error('propose-review wall timeout')),\n maxWallMs,\n )\n\n const shots: ProposeReviewShot<State, Summary>[] = []\n let state = config.initialState\n let priorReview: Review | null = null\n let lastVerification: Verification = { pass: false }\n let failureClass: FailureClass | undefined\n let completed = false\n let lowConfidenceStreak = 0\n\n try {\n for (let shot = 1; shot <= maxShots; shot++) {\n if (abort.signal.aborted) {\n failureClass = 'timeout'\n break\n }\n\n const shotStart = Date.now()\n const shotHandle = emitter ? await emitter.span({ kind: 'tool', name: `shot-${shot}` }) : null\n\n // 1. Propose.\n let proposeOut: ProposeOutput<State, Summary>\n try {\n proposeOut = await config.propose({\n shot,\n goal: config.goal,\n state,\n priorReview,\n abortSignal: abort.signal,\n emitter: emitter ?? undefined,\n })\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n state = proposeOut.state\n const traceSummary = proposeOut.traceSummary\n\n // 2. Verify.\n let verification: Verification\n try {\n verification = await config.verify(state)\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n lastVerification = verification\n\n // 3. Review — short-circuit on pass; soft-fail on throw.\n const memorySnapshot = await memory.load()\n const verificationDigest = {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers ?? [],\n }\n\n let review: Review\n let reviewAvailable = true\n let reviewError: string | undefined\n\n if (verification.pass) {\n review = {\n observations: 'verification passed — skipping reviewer LLM call',\n diagnosis: 'no failures to diagnose',\n nextShotInstruction: '(done)',\n shouldContinue: false,\n confidence: 1,\n }\n } else {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state,\n verification,\n traceSummary,\n memory: memorySnapshot,\n })\n review = coerceReview(review)\n } catch (err) {\n reviewAvailable = false\n reviewError = err instanceof Error ? err.message : String(err)\n const lastInstruction =\n memorySnapshot.length > 0\n ? memorySnapshot[memorySnapshot.length - 1]!.nextShotInstruction\n : fallbackInstruction\n review = {\n observations: '(reviewer unavailable — using last-known instruction)',\n diagnosis: reviewError,\n nextShotInstruction: lastInstruction,\n shouldContinue: true,\n confidence: 0.3,\n }\n }\n }\n\n const entry: ReviewMemoryEntry = {\n shot,\n timestamp: Date.now(),\n ...review,\n verification: verificationDigest,\n }\n await memory.append(entry)\n\n const shotRecord: ProposeReviewShot<State, Summary> = {\n shot,\n state,\n verification,\n traceSummary,\n review,\n reviewAvailable,\n reviewError,\n durationMs: Date.now() - shotStart,\n }\n shots.push(shotRecord)\n\n await shotHandle?.end({\n attributes: {\n verificationPass: verification.pass,\n verificationScore: verification.score ?? null,\n reviewShouldContinue: review.shouldContinue,\n reviewConfidence: review.confidence,\n reviewAvailable,\n },\n } as Partial<SpanHandle['span']>)\n\n // 4. Exit rules.\n if (verification.pass) {\n completed = true\n break\n }\n if (!review.shouldContinue) {\n break\n }\n if (confidenceFloorWindow > 0 && review.confidence <= confidenceFloor) {\n lowConfidenceStreak += 1\n if (lowConfidenceStreak >= confidenceFloorWindow) break\n } else {\n lowConfidenceStreak = 0\n }\n\n priorReview = review\n }\n\n if (!completed && !failureClass) {\n failureClass = shots.length >= maxShots ? 'budget_exceeded' : 'unknown'\n }\n } finally {\n clearTimeout(wallTimer)\n }\n\n const score = lastVerification.pass\n ? 1\n : typeof lastVerification.score === 'number'\n ? lastVerification.score\n : 0\n\n if (emitter) {\n await emitter.endRun({\n pass: completed,\n score,\n failureClass,\n notes: `${shots.length} shot(s); final pass=${lastVerification.pass}`,\n })\n }\n\n return {\n runId: emitter?.runId ?? null,\n completed,\n shots,\n finalState: state,\n finalVerification: lastVerification,\n failureClass,\n wallMs: Date.now() - wallStart,\n score,\n }\n}\n\n// ── Reviewer helper (LLM-backed) ─────────────────────────────────────\n\nexport type LlmJsonCall = (req: { system: string; user: string }) => Promise<unknown>\n\nexport interface LlmReviewerConfig<State, Summary = unknown> {\n callJson: LlmJsonCall\n renderState?: (state: State) => string\n renderTraceSummary?: (summary: Summary | undefined) => string\n /** Appended to the default system prompt. */\n systemPromptAddendum?: string\n}\n\nconst REVIEWER_SYSTEM_PROMPT = `You are a senior reviewer directing a multi-shot build loop.\nYou do NOT grade — the verifier already did. Your job is to direct the worker's next shot.\nYou are blind to the worker's inner monologue. You see what it DID, not what it thought.\nReturn STRICT JSON matching the schema. No prose outside the JSON.`\n\nexport function createLlmReviewer<State, Summary = unknown>(\n cfg: LlmReviewerConfig<State, Summary>,\n): ReviewFn<State, Summary> {\n const renderState = cfg.renderState ?? ((s: State) => safeJson(s))\n const renderTraceSummary =\n cfg.renderTraceSummary ??\n ((s: Summary | undefined) => (s === undefined ? '(none)' : safeJson(s)))\n const system = cfg.systemPromptAddendum\n ? `${REVIEWER_SYSTEM_PROMPT}\\n\\n${cfg.systemPromptAddendum}`\n : REVIEWER_SYSTEM_PROMPT\n\n return async (input) => {\n const memoryBlock =\n input.memory.length === 0\n ? '(no prior shots — this is shot 1)'\n : input.memory\n .map((m) =>\n [\n `shot ${m.shot} — verification.pass=${m.verification.pass}` +\n (typeof m.verification.score === 'number'\n ? ` score=${m.verification.score.toFixed(2)}`\n : '') +\n ` confidence=${m.confidence.toFixed(2)} failing=[${(m.verification.failingLayers ?? []).join(',')}]`,\n ` observations: ${m.observations.slice(0, 400)}`,\n ` diagnosis: ${m.diagnosis.slice(0, 400)}`,\n ` instruction given: ${m.nextShotInstruction.slice(0, 400)}`,\n ].join('\\n'),\n )\n .join('\\n\\n')\n\n const user = [\n `=== GOAL ===`,\n input.goal,\n ``,\n `=== SHOT NUMBER ===`,\n String(input.shot),\n ``,\n `=== CURRENT STATE ===`,\n renderState(input.state),\n ``,\n `=== TRACE SUMMARY ===`,\n renderTraceSummary(input.traceSummary),\n ``,\n `=== VERIFICATION ===`,\n summarizeVerification(input.verification),\n ``,\n `=== REVIEWER MEMORY (prior shots) ===`,\n memoryBlock,\n ``,\n `=== YOUR TASK ===`,\n `Return STRICT JSON:`,\n `{`,\n ` \"observations\": string (20..2000 chars, first-person worker behavior — quote counts, errors, loops)`,\n ` \"diagnosis\": string (20..1500 chars, root cause, NOT a restatement of verification)`,\n ` \"nextShotInstruction\": string (40..3000 chars, concrete directive to the worker)`,\n ` \"shouldContinue\": boolean (false if verification.pass, or if thrashing, or unachievable)`,\n ` \"confidence\": number in [0,1]`,\n `}`,\n ].join('\\n')\n\n const raw = await cfg.callJson({ system, user })\n return coerceReview(raw as Partial<Review>)\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction coerceReview(raw: Partial<Review> | null | undefined): Review {\n if (!raw || typeof raw !== 'object') {\n throw new Error('reviewer returned non-object')\n }\n const observations = typeof raw.observations === 'string' ? raw.observations : ''\n const diagnosis = typeof raw.diagnosis === 'string' ? raw.diagnosis : ''\n const nextShotInstruction =\n typeof raw.nextShotInstruction === 'string' ? raw.nextShotInstruction : ''\n if (!observations || !diagnosis || !nextShotInstruction) {\n throw new Error('reviewer missing required string fields')\n }\n if (typeof raw.shouldContinue !== 'boolean') {\n throw new Error('reviewer missing shouldContinue boolean')\n }\n const confidenceRaw = Number(raw.confidence)\n if (!Number.isFinite(confidenceRaw)) {\n throw new Error('reviewer confidence not finite')\n }\n return {\n observations,\n diagnosis,\n nextShotInstruction,\n shouldContinue: raw.shouldContinue,\n confidence: Math.max(0, Math.min(1, confidenceRaw)),\n }\n}\n\nfunction summarizeVerification(v: Verification): string {\n const header =\n `pass=${v.pass}` +\n (typeof v.score === 'number' ? ` score=${v.score.toFixed(3)}` : '') +\n (v.failingLayers && v.failingLayers.length > 0\n ? ` failing=[${v.failingLayers.join(', ')}]`\n : '')\n const details = v.details === undefined ? '' : `\\n${safeJson(v.details).slice(0, 1500)}`\n return header + details\n}\n\nfunction safeJson(x: unknown): string {\n try {\n return JSON.stringify(x, null, 2)\n } catch {\n return String(x)\n }\n}\n","import {\n type ControlRunResult,\n type ControlRuntimeConfig,\n objectiveEval,\n runAgentControlLoop,\n} from './control-runtime'\nimport {\n inMemoryReviewStore,\n type ProposeFn,\n type ProposeOutput,\n type Review,\n type ReviewFn,\n type ReviewMemoryEntry,\n type ReviewMemoryStore,\n type Verification,\n type VerifyFn,\n} from './propose-review'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport interface ProposeReviewControlState<State, Summary = unknown> {\n shot: number\n state: State\n priorReview: Review | null\n verification: Verification\n traceSummary?: Summary\n memory: ReviewMemoryEntry[]\n completed: boolean\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlAction {\n type: 'propose-review-shot'\n shot: number\n}\n\nexport interface ProposeReviewControlResult<State, Summary = unknown> {\n state: State\n verification: Verification\n traceSummary?: Summary\n review: Review | null\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n maxShots?: number\n maxWallMs?: number\n memory?: ReviewMemoryStore\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n fallbackInstruction?: string\n confidenceFloor?: number\n confidenceFloorWindow?: number\n failureClassFromVerification?: (verification: Verification) => FailureClass | undefined\n actionFailure?: ControlRuntimeConfig<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >['actionFailure']\n}\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReviewAsControlLoop<State, Summary = unknown>(\n config: ProposeReviewControlConfig<State, Summary>,\n): Promise<\n ControlRunResult<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >\n> {\n const maxShots = config.maxShots ?? 10\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n const failureClassFromVerification =\n config.failureClassFromVerification ?? controlFailureClassFromVerification\n let lowConfidenceStreak = 0\n\n let current: ProposeReviewControlState<State, Summary> = {\n shot: 0,\n state: config.initialState,\n priorReview: null,\n verification: { pass: false },\n memory: await memory.load(),\n completed: false,\n reviewAvailable: false,\n }\n\n return runAgentControlLoop({\n intent: config.goal,\n budget: { maxSteps: maxShots, maxWallMs: config.maxWallMs },\n store: config.store,\n scenarioId: config.scenarioId ?? 'propose-review-control',\n projectId: config.projectId,\n variantId: config.variantId,\n actionFailure: config.actionFailure ?? 'stop',\n observe: () => current,\n validate: ({ state }) => [\n objectiveEval({\n id: 'verification',\n passed: state.verification.pass,\n score: state.verification.score,\n severity: 'critical',\n detail: state.verification.pass\n ? 'verification passed'\n : `verification failed${state.verification.failingLayers?.length ? `: ${state.verification.failingLayers.join(', ')}` : ''}`,\n }),\n ],\n shouldStop: ({ state }) => {\n if (state.verification.pass) {\n return {\n stop: true,\n pass: true,\n reason: 'verification passed',\n score: state.verification.score,\n }\n }\n if (state.completed) {\n return {\n stop: true,\n pass: false,\n reason: 'reviewer stopped continuation',\n score: state.verification.score,\n failureClass: failureClassFromVerification(state.verification),\n }\n }\n return {\n stop: false,\n pass: false,\n reason: 'verification still failing',\n score: state.verification.score,\n }\n },\n decide: ({ state }) => ({\n type: 'continue',\n action: { type: 'propose-review-shot', shot: state.shot + 1 },\n reason: state.priorReview?.nextShotInstruction ?? fallbackInstruction,\n }),\n act: async (action, ctx) => {\n const shot = action.shot\n const proposeOut: ProposeOutput<State, Summary> = await config.propose({\n shot,\n goal: config.goal,\n state: current.state,\n priorReview: current.priorReview,\n abortSignal: ctx.abortSignal,\n emitter: ctx.emitter,\n })\n\n const nextState = proposeOut.state\n const verification = await config.verify(nextState)\n let review: Review | null = null\n let reviewAvailable = false\n let reviewError: string | undefined\n let shouldContinue = !verification.pass\n\n if (!verification.pass) {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n })\n reviewAvailable = true\n shouldContinue = review.shouldContinue\n lowConfidenceStreak = review.confidence <= confidenceFloor ? lowConfidenceStreak + 1 : 0\n if (confidenceFloorWindow > 0 && lowConfidenceStreak >= confidenceFloorWindow)\n shouldContinue = false\n } catch (err) {\n reviewError = err instanceof Error ? err.message : String(err)\n review = current.priorReview ?? {\n observations: 'Reviewer unavailable.',\n diagnosis: reviewError,\n nextShotInstruction: fallbackInstruction,\n shouldContinue: true,\n confidence: 0,\n }\n shouldContinue = true\n }\n } else {\n review = {\n observations: 'Verification passed.',\n diagnosis: 'No further revision needed.',\n nextShotInstruction: '',\n shouldContinue: false,\n confidence: 1,\n }\n }\n\n const entry: ReviewMemoryEntry = {\n ...(review ?? {\n observations: 'No review.',\n diagnosis: '',\n nextShotInstruction: fallbackInstruction,\n shouldContinue,\n confidence: 0,\n }),\n shot,\n timestamp: Date.now(),\n verification: {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers,\n },\n }\n await memory.append(entry)\n\n current = {\n shot,\n state: nextState,\n priorReview: review,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n completed: verification.pass || !shouldContinue,\n reviewAvailable,\n reviewError,\n }\n\n return {\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n review,\n reviewAvailable,\n reviewError,\n }\n },\n })\n}\n\nexport function controlFailureClassFromVerification(\n verification: Verification,\n): FailureClass | undefined {\n if (verification.pass) return undefined\n return verification.failingLayers?.length ? 'instruction_following' : 'unknown'\n}\n","// The realness-oracle firewall (agent-runtime docs/learning-flywheel.md, \"The steer is f(trace)\" — the doctrine lives in the runtime repo).\n//\n// A realness/authenticity signal has TWO legitimate roles that must stay\n// separated by a firewall:\n// (a) anchor judge J — write-only: scores the chosen output, gates promotion,\n// NEVER seen by the worker/optimizer mid-run (else the loop games it).\n// (b) steer f(trace) — an analyst observes the agent's OWN behavior in the\n// trace (\"imported a stub\", \"used a non-crypto PRNG where encryption was\n// required\") and steers the next attempt. Legitimate, because it is derived\n// from OBSERVABLE BEHAVIOR, not from J's held-out verdict.\n//\n// The correct discriminator is PROVENANCE, not evidence presence. A judge verdict\n// lifted into a finding (createJudgeAdapter → liftJudgeScore) is a verdict even\n// when it cites an artifact; an evidence-less trace-analyst bullet is an\n// observation even though it cites nothing. So the firewall keys on\n// `AnalystFinding.derived_from_judge` (set at the judge lift site), NOT on whether\n// evidence_refs is populated. The instant a verdict steers the next attempt it is\n// a back-channel for J and the loop Goodharts realness exactly as it would\n// Goodhart pass-rate.\n\nimport type { AnalystFinding, EvidenceRef } from './types'\n\n/** Evidence grounded in the agent's OWN execution: OTLP trace elements\n * (`span`/`event`) or the artifact it produced (`artifact`). */\nconst OBSERVABLE_KINDS: ReadonlySet<EvidenceRef['kind']> = new Set<EvidenceRef['kind']>([\n 'span',\n 'event',\n 'artifact',\n])\n\n/** DESCRIPTIVE predicate: does the finding cite at least one observable\n * (span/event/artifact) evidence ref. Useful for ranking evidence quality or\n * rendering — it is NOT the steer gate. Evidence presence is the WRONG\n * discriminator for steering: a legitimate trace-analyst observation may cite\n * nothing (it would be wrongly rejected), and a judge verdict may cite an\n * artifact (it would be wrongly admitted). Use `assertNoJudgeVerdict` to gate\n * steering; use this only where \"is this grounded in observable evidence\" is the\n * literal question. */\nexport function isTraceObservable(finding: AnalystFinding): boolean {\n return finding.evidence_refs.some((ref) => OBSERVABLE_KINDS.has(ref.kind))\n}\n\n/** True iff the finding is a JUDGE VERDICT (an acceptance score lifted into a\n * finding), identified by provenance set at the lift site — independent of\n * whatever evidence it cites. */\nexport function isJudgeVerdict(finding: AnalystFinding): boolean {\n return finding.derived_from_judge === true\n}\n\n/**\n * THE steer firewall. Fail-loud guard for any path that admits analyst findings\n * as STEERING input (the `f(trace)` role): rejects — naming the offenders — any\n * finding whose provenance is a judge verdict, rather than let `J` leak into the\n * loop. Returns the findings unchanged for chaining.\n *\n * Call this at the chokepoint where a detector that ALSO scores/gates has its\n * findings turned into a steer (the judge-and-steer dual-role case). It keys on\n * provenance, so it correctly admits evidence-less trace-analyst observations and\n * correctly rejects an artifact-citing judge verdict — the cases an evidence\n * check gets backwards.\n *\n * It is necessary, not sufficient: it stops PROVENANCE-tagged verdicts. A judge\n * whose output is laundered through a hand-built finding with no provenance flag\n * is out of its reach — provenance must be honestly set at every judge→finding\n * lift (today: createJudgeAdapter). That is why the integrity rule lives at the\n * lift site, and why ProposeContext.judgeScores?: never is the complementary\n * compile-time tripwire on the obvious direct channel.\n */\nexport function assertNoJudgeVerdict(\n findings: ReadonlyArray<AnalystFinding>,\n context = 'steer',\n): ReadonlyArray<AnalystFinding> {\n const leaks = findings.filter(isJudgeVerdict)\n if (leaks.length > 0) {\n throw new Error(\n `${context}: a judge verdict cannot be admitted as steering input — that is the ` +\n `held-out judge leaking into the loop. Offending judge-derived findings: [${leaks\n .map((f) => f.finding_id)\n .join(', ')}]. Steering consumes observations of behavior, never acceptance verdicts.`,\n )\n }\n return findings\n}\n","import type { AgentProfileCell, AgentProfileJson } from '../agent-profile-cell'\nimport { validateAgentProfileCell } from '../agent-profile-cell'\nimport { ValidationError } from '../errors'\nimport { hashCanonical } from '../ledger-core/canonical'\nimport { type FindingSubject, parseFindingSubject } from './finding-subject'\nimport { assertNoJudgeVerdict } from './steer-firewall'\nimport type { AnalystFinding, EvidenceRef } from './types'\n\nexport type PolicyEditSchemaVersion = 'policy-edit/v1'\n\nexport const POLICY_EDIT_AXES = [\n 'carrier',\n 'representation',\n 'budget',\n 'sampling',\n 'output_contract',\n 'tool_contract',\n 'routing',\n 'memory',\n 'agent_profile',\n 'deployment_target',\n] as const\n\nexport type PolicyEditAxis = (typeof POLICY_EDIT_AXES)[number]\n\nexport const POLICY_EDIT_TARGET_SURFACES = [\n 'prompt',\n 'tool-contract',\n 'runtime-config',\n 'memory',\n 'agent-profile',\n 'code',\n 'deployment',\n] as const\n\nexport type PolicyEditTargetSurface = (typeof POLICY_EDIT_TARGET_SURFACES)[number]\nexport type PolicyEditRisk = 'low' | 'medium' | 'high' | 'unknown'\nexport type PolicyEditGainDirection = 'increase' | 'decrease'\nexport type PolicyEditGainUnit = 'absolute' | 'relative' | 'percent' | 'score'\n\nexport interface PolicyEditTarget {\n surface: PolicyEditTargetSurface\n /** Stable path inside the target surface, for example `system-prompt:tools`\n * or `budget.maxTurns`. */\n path?: string\n /** Optional canonical deployment identity. Store the existing cell, not a\n * local profile shape. */\n agentProfileCell?: AgentProfileCell\n /** Human label when the path is not enough for a readable audit trail. */\n label?: string\n}\n\nexport type PolicyEditChange =\n | {\n kind: 'text'\n mode: 'append' | 'prepend' | 'replace'\n value: string\n /** Required when `mode === 'replace'`; exact match only. */\n find?: string\n }\n | {\n kind: 'json'\n mode: 'set' | 'merge' | 'remove'\n path: string\n value?: AgentProfileJson\n }\n\nexport interface PolicyEditExpectedGain {\n /** Metric this edit is expected to move, e.g. `holdout.composite`. */\n metric: string\n direction: PolicyEditGainDirection\n /** Positive magnitude in the metric's native units. */\n amount: number\n unit?: PolicyEditGainUnit\n rationale?: string\n}\n\nexport interface PolicyEditSource {\n findingIds: string[]\n analystIds: string[]\n evidenceRefs: EvidenceRef[]\n /** Mirrors `AnalystFinding.derived_from_judge`; admission rejects it. */\n derivedFromJudge?: boolean\n}\n\nexport interface PolicyEdit {\n schemaVersion: PolicyEditSchemaVersion\n editId: string\n axis: PolicyEditAxis\n target: PolicyEditTarget\n change: PolicyEditChange\n claim: string\n expectedGain: PolicyEditExpectedGain\n confidence: number\n risk: PolicyEditRisk\n source: PolicyEditSource\n rationale?: string\n validationPlan?: string\n metadata?: Record<string, unknown>\n}\n\nexport const POLICY_EDIT_CANDIDATE_RECORD_SCHEMA = 'tangle.policy-edit-candidate.v1' as const\n\n/** JSON-safe attribution carried with a measured candidate and its scores. */\nexport interface PolicyEditCandidateRecord {\n schema: typeof POLICY_EDIT_CANDIDATE_RECORD_SCHEMA\n policyEdit: PolicyEdit\n}\n\nexport type PolicyEditInit = Omit<PolicyEdit, 'schemaVersion' | 'editId'> & {\n schemaVersion?: PolicyEditSchemaVersion\n editId?: string\n}\n\nexport class PolicyEditValidationError extends ValidationError {\n readonly path: string\n constructor(message: string, path = '') {\n super(path ? `${message} (at ${path})` : message)\n this.path = path\n }\n}\n\nexport interface FindingToPolicyEditOptions {\n expectedGain?:\n | PolicyEditExpectedGain\n | ((finding: AnalystFinding) => PolicyEditExpectedGain | null | undefined)\n risk?: PolicyEditRisk | ((finding: AnalystFinding) => PolicyEditRisk)\n defaultAxis?: PolicyEditAxis\n defaultTargetSurface?: PolicyEditTargetSurface\n}\n\nexport interface PolicyEditAdmissionOptions {\n minScore?: number\n minExpectedGain?: number\n allowHighRisk?: boolean\n requireEvidence?: boolean\n}\n\nexport interface PolicyEditAdmission {\n edit: PolicyEdit\n decision: 'admit' | 'reject'\n score: number\n reasons: string[]\n}\n\nconst DEFAULT_MIN_SCORE = 0.7\nconst DEFAULT_MIN_EXPECTED_GAIN = 0.01\nconst POLICY_EDIT_ID = /^policy-edit:sha256:[0-9a-f]{64}$/\n\nexport function makePolicyEdit(init: PolicyEditInit): PolicyEdit {\n const normalized = normalizePolicyEdit({\n schemaVersion: 'policy-edit/v1',\n ...init,\n source: normalizeSource(init.source),\n })\n const edit = {\n ...normalized,\n editId: init.editId ?? computePolicyEditId(normalized),\n }\n return validatePolicyEdit(edit)\n}\n\nexport function computePolicyEditId(edit: Omit<PolicyEdit, 'editId'> | PolicyEdit): string {\n const { editId: _editId, schemaVersion, ...material } = edit as PolicyEdit\n void _editId\n return `policy-edit:${hashCanonical({ schemaVersion, ...material })}`\n}\n\nexport function validatePolicyEdit(input: unknown): PolicyEdit {\n if (input === null || typeof input !== 'object') {\n throw new PolicyEditValidationError('expected object')\n }\n const obj = input as PolicyEdit\n expectLiteral(obj.schemaVersion, 'policy-edit/v1', 'schemaVersion')\n expectString(obj.editId, 'editId')\n if (!POLICY_EDIT_ID.test(obj.editId)) {\n throw new PolicyEditValidationError(\n 'editId must match policy-edit:sha256:<64 lowercase hex chars>',\n 'editId',\n )\n }\n expectOneOf(obj.axis, POLICY_EDIT_AXES, 'axis')\n validateTarget(obj.target)\n validateChange(obj.change)\n expectString(obj.claim, 'claim')\n validateExpectedGain(obj.expectedGain)\n expectConfidence(obj.confidence, 'confidence')\n expectOneOf(obj.risk, ['low', 'medium', 'high', 'unknown'] as const, 'risk')\n validateSource(obj.source)\n if (obj.rationale !== undefined) expectString(obj.rationale, 'rationale')\n if (obj.validationPlan !== undefined) expectString(obj.validationPlan, 'validationPlan')\n if (obj.metadata !== undefined && (obj.metadata === null || typeof obj.metadata !== 'object')) {\n throw new PolicyEditValidationError('expected object', 'metadata')\n }\n const expectedId = computePolicyEditId(obj)\n if (obj.editId !== expectedId) {\n throw new PolicyEditValidationError('editId does not match policy edit content', 'editId')\n }\n return obj\n}\n\nexport function makePolicyEditCandidateRecord(edit: PolicyEdit): PolicyEditCandidateRecord {\n return validatePolicyEditCandidateRecord({\n schema: POLICY_EDIT_CANDIDATE_RECORD_SCHEMA,\n policyEdit: edit,\n })\n}\n\nexport function validatePolicyEditCandidateRecord(input: unknown): PolicyEditCandidateRecord {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n throw new PolicyEditValidationError('expected object', 'candidateRecord')\n }\n const obj = input as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n if (keys.length !== 2 || keys[0] !== 'policyEdit' || keys[1] !== 'schema') {\n throw new PolicyEditValidationError('expected exactly schema and policyEdit', 'candidateRecord')\n }\n expectLiteral(obj.schema, POLICY_EDIT_CANDIDATE_RECORD_SCHEMA, 'candidateRecord.schema')\n const policyEdit = validatePolicyEdit(obj.policyEdit)\n assertJsonSafe(policyEdit, 'candidateRecord.policyEdit')\n const snapshot = JSON.parse(JSON.stringify(policyEdit)) as unknown\n return {\n schema: POLICY_EDIT_CANDIDATE_RECORD_SCHEMA,\n policyEdit: validatePolicyEdit(snapshot),\n }\n}\n\nexport function isPolicyEdit(input: unknown): input is PolicyEdit {\n try {\n validatePolicyEdit(input)\n return true\n } catch {\n return false\n }\n}\n\nexport function policyEditsFromFindings(\n findings: ReadonlyArray<AnalystFinding>,\n opts: FindingToPolicyEditOptions = {},\n): PolicyEdit[] {\n assertNoJudgeVerdict(findings, 'policyEditsFromFindings')\n const edits: PolicyEdit[] = []\n for (const finding of findings) {\n const edit = policyEditFromFinding(finding, opts)\n if (edit) edits.push(edit)\n }\n return edits\n}\n\nexport function policyEditFromFinding(\n finding: AnalystFinding,\n opts: FindingToPolicyEditOptions = {},\n): PolicyEdit | null {\n assertNoJudgeVerdict([finding], 'policyEditFromFinding')\n if (!finding.recommended_action?.trim()) return null\n\n const expectedGain = resolveExpectedGain(finding, opts)\n if (!expectedGain) return null\n // A confidence outside [0,1] is a malformed model-produced row: skip the\n // finding rather than let one poisoned row abort the whole batch.\n if (\n typeof finding.confidence !== 'number' ||\n !Number.isFinite(finding.confidence) ||\n finding.confidence < 0 ||\n finding.confidence > 1\n ) {\n return null\n }\n\n const routed = routeFindingSubject(finding.subject, opts)\n const risk = resolveRisk(finding, opts)\n return makePolicyEdit({\n axis: routed.axis,\n target: routed.target,\n change: { kind: 'text', mode: 'append', value: finding.recommended_action.trim() },\n claim: finding.claim,\n rationale: finding.rationale,\n expectedGain,\n confidence: finding.confidence,\n risk,\n validationPlan: finding.validation_plan,\n source: {\n findingIds: [finding.finding_id],\n analystIds: [finding.analyst_id],\n evidenceRefs: finding.evidence_refs,\n derivedFromJudge: finding.derived_from_judge,\n },\n })\n}\n\nexport function scorePolicyEditReadiness(\n edit: PolicyEdit,\n opts: PolicyEditAdmissionOptions = {},\n): number {\n validatePolicyEdit(edit)\n const minExpectedGain = opts.minExpectedGain ?? DEFAULT_MIN_EXPECTED_GAIN\n const requireEvidence = opts.requireEvidence ?? false\n const evidenceScore = Math.min(1, edit.source.evidenceRefs.length / 2)\n const confidenceScore = clamp01(edit.confidence)\n const gainScore = clamp01(\n Math.abs(edit.expectedGain.amount) / Math.max(minExpectedGain * 5, 0.001),\n )\n const targetScore = targetSpecificityScore(edit)\n const riskPenalty =\n edit.risk === 'high' && opts.allowHighRisk !== true ? 0.35 : edit.risk === 'unknown' ? 0.2 : 0\n\n // Evidence weighs into the base score only when the caller requires it.\n // Otherwise it is a bonus on top: the steer firewall's discriminator is\n // provenance, and an evidence-less trace observation must be able to clear\n // the default bar on confidence, gain, and target specificity alone.\n const base = requireEvidence\n ? 0.3 * evidenceScore + 0.25 * confidenceScore + 0.25 * gainScore + 0.2 * targetScore\n : 0.35 * confidenceScore + 0.35 * gainScore + 0.3 * targetScore + 0.1 * evidenceScore\n return clamp01(base - riskPenalty)\n}\n\nexport function admitPolicyEdit(\n edit: PolicyEdit,\n opts: PolicyEditAdmissionOptions = {},\n): PolicyEditAdmission {\n const validated = validatePolicyEdit(edit)\n const score = scorePolicyEditReadiness(validated, opts)\n const reasons: string[] = []\n const minExpectedGain = opts.minExpectedGain ?? DEFAULT_MIN_EXPECTED_GAIN\n // Default OFF, matching the steer firewall: the admission discriminator is\n // PROVENANCE (derivedFromJudge), not evidence presence — an evidence-less\n // trace-analyst observation is a legitimate edit source. Callers opt IN to\n // an evidence requirement where their domain demands citations.\n const requireEvidence = opts.requireEvidence ?? false\n\n if (validated.source.derivedFromJudge) {\n reasons.push('source is judge-derived; judge verdicts cannot steer policy edits')\n }\n if (requireEvidence && validated.source.evidenceRefs.length === 0) {\n reasons.push('missing evidence refs')\n }\n if (Math.abs(validated.expectedGain.amount) < minExpectedGain) {\n reasons.push(`expected gain below ${minExpectedGain}`)\n }\n if (validated.risk === 'high' && opts.allowHighRisk !== true) {\n reasons.push('high-risk edit requires explicit allowHighRisk')\n }\n if (score < (opts.minScore ?? DEFAULT_MIN_SCORE)) {\n reasons.push(\n `readiness score ${score.toFixed(3)} below ${(opts.minScore ?? DEFAULT_MIN_SCORE).toFixed(3)}`,\n )\n }\n\n return {\n edit: validated,\n decision: reasons.length === 0 ? 'admit' : 'reject',\n score,\n reasons,\n }\n}\n\nexport function applyPolicyEditToSurface(surface: unknown, edit: PolicyEdit): unknown {\n const validated = validatePolicyEdit(edit)\n if (validated.change.kind === 'text') return applyTextChange(surface, validated.change)\n return applyJsonChange(surface, validated.change)\n}\n\nfunction routeFindingSubject(\n subject: string | undefined,\n opts: FindingToPolicyEditOptions,\n): { axis: PolicyEditAxis; target: PolicyEditTarget } {\n const parsed = parseFindingSubject(subject)\n if (!parsed) {\n return {\n axis: opts.defaultAxis ?? 'representation',\n target: { surface: opts.defaultTargetSurface ?? 'prompt' },\n }\n }\n return routeParsedSubject(parsed)\n}\n\nfunction routeParsedSubject(subject: FindingSubject): {\n axis: PolicyEditAxis\n target: PolicyEditTarget\n} {\n switch (subject.kind) {\n case 'system-prompt':\n return {\n axis: 'representation',\n target: { surface: 'prompt', path: `system-prompt:${subject.section}` },\n }\n case 'skill':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `skill:${subject.name}` },\n }\n case 'tool-doc':\n return {\n axis: 'tool_contract',\n target: {\n surface: 'tool-contract',\n path: subject.aspect\n ? `tool-doc:${subject.tool}:${subject.aspect}`\n : `tool-doc:${subject.tool}`,\n },\n }\n case 'new-tool':\n return {\n axis: 'tool_contract',\n target: { surface: 'tool-contract', path: `new-tool:${subject.name}` },\n }\n case 'mcp':\n return {\n axis: 'tool_contract',\n target: {\n surface: 'agent-profile',\n path: subject.tool ? `mcp:${subject.server}:${subject.tool}` : `mcp:${subject.server}`,\n },\n }\n case 'hook':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `hook:${subject.name}` },\n }\n case 'subagent':\n return {\n axis: 'routing',\n target: { surface: 'agent-profile', path: `subagent:${subject.name}` },\n }\n case 'workflow':\n return {\n axis: 'routing',\n target: { surface: 'runtime-config', path: `workflow:${subject.name}` },\n }\n case 'rollout-policy':\n return {\n axis: rolloutPolicyAxis(subject.field),\n target: { surface: 'runtime-config', path: `rollout-policy:${subject.field}` },\n }\n case 'agent-profile':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `agent-profile:${subject.field}` },\n }\n case 'code':\n return {\n axis: 'representation',\n target: { surface: 'code', path: `code:${subject.path}` },\n }\n case 'rag':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `rag:${subject.corpus}:${subject.docId}` },\n }\n case 'memory':\n return { axis: 'memory', target: { surface: 'memory', path: `memory:${subject.key}` } }\n case 'scaffolding':\n return {\n axis: 'routing',\n target: { surface: 'runtime-config', path: `scaffolding:${subject.concern}` },\n }\n case 'output-schema':\n return {\n axis: 'output_contract',\n target: { surface: 'runtime-config', path: `output-schema:${subject.field}` },\n }\n case 'knowledge.wiki':\n return {\n axis: 'memory',\n target: {\n surface: 'memory',\n path: `agent-knowledge:wiki:${subject.slug}${subject.heading ? `#${subject.heading}` : ''}`,\n },\n }\n case 'knowledge.claim':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:claim:${subject.topic}` },\n }\n case 'knowledge.raw':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:raw:${subject.sourceId}` },\n }\n case 'knowledge.stale':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:stale:${subject.slug}` },\n }\n case 'websearch.outdated':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `websearch:outdated:${subject.topic}` },\n }\n case 'prior-run-summary':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `prior-run-summary:${subject.topic}` },\n }\n case 'cluster':\n return { axis: 'representation', target: { surface: 'prompt', path: subject.label } }\n }\n}\n\nfunction rolloutPolicyAxis(field: string): PolicyEditAxis {\n const normalized = field.toLowerCase()\n if (/budget|max(?:imum)?[-_. ]?(?:turns?|tokens?|cost)|timeout|deadline/.test(normalized)) {\n return 'budget'\n }\n if (/temperature|top[-_. ]?p|sampling|seed|shots?|parallel|concurrency/.test(normalized)) {\n return 'sampling'\n }\n if (/output|schema|format/.test(normalized)) return 'output_contract'\n return 'routing'\n}\n\nfunction resolveExpectedGain(\n finding: AnalystFinding,\n opts: FindingToPolicyEditOptions,\n): PolicyEditExpectedGain | null {\n if (typeof opts.expectedGain === 'function') return opts.expectedGain(finding) ?? null\n if (opts.expectedGain) return opts.expectedGain\n return readExpectedGainFromMetadata(finding.metadata)\n}\n\nfunction readExpectedGainFromMetadata(\n metadata: Record<string, unknown> | undefined,\n): PolicyEditExpectedGain | null {\n const raw =\n readPolicyEditMetadata(metadata)?.expectedGain ??\n readPolicyEditMetadata(metadata)?.expected_gain\n if (!raw || typeof raw !== 'object') return null\n const obj = raw as Record<string, unknown>\n // Metadata is model-produced. A malformed row degrades to null (the finding\n // is skipped) instead of throwing, so one poisoned row cannot abort the\n // whole batch — the same contract as a finding with no expected gain.\n if (\n typeof obj.metric !== 'string' ||\n (obj.direction !== 'increase' && obj.direction !== 'decrease') ||\n typeof obj.amount !== 'number' ||\n !Number.isFinite(obj.amount) ||\n obj.amount <= 0\n ) {\n return null\n }\n const out: PolicyEditExpectedGain = {\n metric: obj.metric,\n direction: obj.direction,\n amount: obj.amount,\n }\n if (\n obj.unit === 'absolute' ||\n obj.unit === 'relative' ||\n obj.unit === 'percent' ||\n obj.unit === 'score'\n ) {\n out.unit = obj.unit\n }\n if (typeof obj.rationale === 'string') out.rationale = obj.rationale\n return out\n}\n\nfunction readPolicyEditMetadata(\n metadata: Record<string, unknown> | undefined,\n): Record<string, unknown> | null {\n const raw = metadata?.policyEdit ?? metadata?.policy_edit\n return raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : null\n}\n\nfunction resolveRisk(finding: AnalystFinding, opts: FindingToPolicyEditOptions): PolicyEditRisk {\n if (typeof opts.risk === 'function') return opts.risk(finding)\n if (opts.risk) return opts.risk\n const raw = readPolicyEditMetadata(finding.metadata)?.risk\n if (raw === 'low' || raw === 'medium' || raw === 'high' || raw === 'unknown') return raw\n if (finding.severity === 'critical' || finding.severity === 'high') return 'medium'\n return 'low'\n}\n\nfunction applyTextChange(\n surface: unknown,\n change: Extract<PolicyEditChange, { kind: 'text' }>,\n): string {\n if (typeof surface !== 'string') {\n throw new PolicyEditValidationError('text policy edits require a string surface', 'change')\n }\n if (change.mode === 'append') {\n if (hasExactTextBlock(surface, change.value)) return surface\n return `${surface.trimEnd()}\\n\\n${change.value}`.trimStart()\n }\n if (change.mode === 'prepend') {\n if (hasExactTextBlock(surface, change.value)) return surface\n return `${change.value}\\n\\n${surface.trimStart()}`.trimEnd()\n }\n const find = expectNonEmpty(change.find, 'change.find')\n if (!surface.includes(find)) {\n throw new PolicyEditValidationError('replace target not found in surface', 'change.find')\n }\n return surface.replace(find, change.value)\n}\n\nfunction applyJsonChange(\n surface: unknown,\n change: Extract<PolicyEditChange, { kind: 'json' }>,\n): AgentProfileJson {\n const root = parseJsonSurface(surface)\n const path = splitPath(change.path)\n if (change.mode === 'remove') return setJsonAtPath(root, path, undefined, 'remove')\n if (change.mode === 'set') return setJsonAtPath(root, path, change.value ?? null, 'set')\n const prior = readJsonAtPath(root, path)\n const merged =\n prior &&\n typeof prior === 'object' &&\n !Array.isArray(prior) &&\n change.value &&\n typeof change.value === 'object' &&\n !Array.isArray(change.value)\n ? { ...prior, ...change.value }\n : (change.value ?? null)\n return setJsonAtPath(root, path, merged as AgentProfileJson, 'set')\n}\n\nfunction parseJsonSurface(surface: unknown): AgentProfileJson {\n if (typeof surface === 'string') {\n try {\n return JSON.parse(surface) as AgentProfileJson\n } catch {\n throw new PolicyEditValidationError(\n 'json policy edits require a JSON string surface',\n 'change',\n )\n }\n }\n assertJson(surface, 'surface')\n return surface as AgentProfileJson\n}\n\nfunction readJsonAtPath(root: AgentProfileJson, path: string[]): AgentProfileJson | undefined {\n let cursor: AgentProfileJson | undefined = root\n for (const part of path) {\n if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor)) return undefined\n cursor = cursor[part]\n }\n return cursor\n}\n\nfunction setJsonAtPath(\n root: AgentProfileJson,\n path: string[],\n value: AgentProfileJson | undefined,\n mode: 'set' | 'remove',\n): AgentProfileJson {\n if (path.length === 0) {\n if (mode === 'remove') return null\n return value ?? null\n }\n if (root === null || typeof root !== 'object' || Array.isArray(root)) {\n throw new PolicyEditValidationError('json edit root must be an object', 'change.path')\n }\n const out: Record<string, AgentProfileJson> = { ...root }\n let cursor: Record<string, AgentProfileJson> = out\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i]!\n const existing = cursor[key]\n if (\n mode === 'remove' &&\n (!existing || typeof existing !== 'object' || Array.isArray(existing))\n ) {\n return out\n }\n const next =\n existing && typeof existing === 'object' && !Array.isArray(existing) ? { ...existing } : {}\n cursor[key] = next\n cursor = next\n }\n const leaf = path[path.length - 1]!\n if (mode === 'remove') delete cursor[leaf]\n else cursor[leaf] = value ?? null\n return out\n}\n\nfunction normalizePolicyEdit(input: Omit<PolicyEdit, 'editId'>): Omit<PolicyEdit, 'editId'> {\n const out: Omit<PolicyEdit, 'editId'> = {\n schemaVersion: 'policy-edit/v1',\n axis: input.axis,\n target: normalizeTarget(input.target),\n change: normalizeChange(input.change),\n claim: input.claim.trim(),\n expectedGain: normalizeExpectedGain(input.expectedGain),\n confidence: input.confidence,\n risk: input.risk,\n source: normalizeSource(input.source),\n }\n if (input.rationale?.trim()) out.rationale = input.rationale.trim()\n if (input.validationPlan?.trim()) out.validationPlan = input.validationPlan.trim()\n if (input.metadata) out.metadata = input.metadata\n return out\n}\n\nfunction assertJsonSafe(value: unknown, path: string, ancestors = new WeakSet<object>()): void {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return\n throw new PolicyEditValidationError('expected finite JSON number', path)\n }\n if (typeof value !== 'object') {\n throw new PolicyEditValidationError('expected JSON-safe value', path)\n }\n if (ancestors.has(value)) {\n throw new PolicyEditValidationError('cyclic value is not JSON-safe', path)\n }\n ancestors.add(value)\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!(i in value)) {\n throw new PolicyEditValidationError('sparse array is not JSON-safe', `${path}.${i}`)\n }\n assertJsonSafe(value[i], `${path}.${i}`, ancestors)\n }\n } else {\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) {\n throw new PolicyEditValidationError('expected plain JSON object', path)\n }\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw new PolicyEditValidationError('symbol keys are not JSON-safe', path)\n }\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n assertJsonSafe(child, `${path}.${key}`, ancestors)\n }\n }\n ancestors.delete(value)\n}\n\nfunction normalizeTarget(target: PolicyEditTarget): PolicyEditTarget {\n const out: PolicyEditTarget = { surface: target.surface }\n if (target.path?.trim()) out.path = target.path.trim()\n if (target.agentProfileCell)\n out.agentProfileCell = validateAgentProfileCell(target.agentProfileCell)\n if (target.label?.trim()) out.label = target.label.trim()\n return out\n}\n\nfunction normalizeChange(change: PolicyEditChange): PolicyEditChange {\n if (change.kind === 'text') {\n const out: Extract<PolicyEditChange, { kind: 'text' }> = {\n kind: 'text',\n mode: change.mode,\n value: change.value.trim(),\n }\n if (change.find?.trim()) out.find = change.find.trim()\n return out\n }\n const out: Extract<PolicyEditChange, { kind: 'json' }> = {\n kind: 'json',\n mode: change.mode,\n path: change.path.trim(),\n }\n if (change.value !== undefined) out.value = change.value\n return out\n}\n\nfunction normalizeExpectedGain(gain: PolicyEditExpectedGain): PolicyEditExpectedGain {\n const out: PolicyEditExpectedGain = {\n metric: gain.metric.trim(),\n direction: gain.direction,\n amount: gain.amount,\n }\n if (gain.unit) out.unit = gain.unit\n if (gain.rationale?.trim()) out.rationale = gain.rationale.trim()\n return out\n}\n\nfunction normalizeSource(source: PolicyEditSource): PolicyEditSource {\n const out: PolicyEditSource = {\n findingIds: uniqueSorted(source.findingIds.map((s) => s.trim()).filter(Boolean)),\n analystIds: uniqueSorted(source.analystIds.map((s) => s.trim()).filter(Boolean)),\n evidenceRefs: source.evidenceRefs,\n }\n if (source.derivedFromJudge) out.derivedFromJudge = true\n return out\n}\n\nfunction validateTarget(target: unknown): asserts target is PolicyEditTarget {\n if (!target || typeof target !== 'object')\n throw new PolicyEditValidationError('expected object', 'target')\n const obj = target as PolicyEditTarget\n expectOneOf(obj.surface, POLICY_EDIT_TARGET_SURFACES, 'target.surface')\n if (obj.path !== undefined) expectString(obj.path, 'target.path')\n if (obj.label !== undefined) expectString(obj.label, 'target.label')\n if (obj.agentProfileCell !== undefined) validateAgentProfileCell(obj.agentProfileCell)\n}\n\nfunction validateChange(change: unknown): asserts change is PolicyEditChange {\n if (!change || typeof change !== 'object')\n throw new PolicyEditValidationError('expected object', 'change')\n const obj = change as PolicyEditChange\n if (obj.kind !== 'text' && obj.kind !== 'json') {\n throw new PolicyEditValidationError('kind must be text or json', 'change.kind')\n }\n if (obj.kind === 'text') {\n expectOneOf(obj.mode, ['append', 'prepend', 'replace'] as const, 'change.mode')\n expectString(obj.value, 'change.value')\n if (obj.mode === 'replace') expectString(obj.find, 'change.find')\n return\n }\n expectOneOf(obj.mode, ['set', 'merge', 'remove'] as const, 'change.mode')\n expectString(obj.path, 'change.path')\n splitPath(obj.path)\n if (obj.value !== undefined) assertJson(obj.value, 'change.value')\n}\n\nfunction validateExpectedGain(gain: unknown): asserts gain is PolicyEditExpectedGain {\n if (!gain || typeof gain !== 'object')\n throw new PolicyEditValidationError('expected object', 'expectedGain')\n const obj = gain as PolicyEditExpectedGain\n expectString(obj.metric, 'expectedGain.metric')\n expectOneOf(obj.direction, ['increase', 'decrease'] as const, 'expectedGain.direction')\n if (!Number.isFinite(obj.amount) || obj.amount <= 0) {\n throw new PolicyEditValidationError(\n 'amount must be a positive finite number',\n 'expectedGain.amount',\n )\n }\n if (obj.unit !== undefined) {\n expectOneOf(\n obj.unit,\n ['absolute', 'relative', 'percent', 'score'] as const,\n 'expectedGain.unit',\n )\n }\n if (obj.rationale !== undefined) expectString(obj.rationale, 'expectedGain.rationale')\n}\n\nfunction validateSource(source: unknown): asserts source is PolicyEditSource {\n if (!source || typeof source !== 'object')\n throw new PolicyEditValidationError('expected object', 'source')\n const obj = source as PolicyEditSource\n expectNonEmptyStringArray(obj.findingIds, 'source.findingIds')\n expectNonEmptyStringArray(obj.analystIds, 'source.analystIds')\n if (!Array.isArray(obj.evidenceRefs)) {\n throw new PolicyEditValidationError('expected array', 'source.evidenceRefs')\n }\n for (const [i, ref] of obj.evidenceRefs.entries())\n validateEvidenceRef(ref, `source.evidenceRefs.${i}`)\n if (obj.derivedFromJudge !== undefined && typeof obj.derivedFromJudge !== 'boolean') {\n throw new PolicyEditValidationError('expected boolean', 'source.derivedFromJudge')\n }\n}\n\nfunction validateEvidenceRef(ref: unknown, path: string): asserts ref is EvidenceRef {\n if (!ref || typeof ref !== 'object') throw new PolicyEditValidationError('expected object', path)\n const obj = ref as EvidenceRef\n expectOneOf(obj.kind, ['span', 'event', 'artifact', 'finding', 'metric'] as const, `${path}.kind`)\n expectString(obj.uri, `${path}.uri`)\n if (obj.excerpt !== undefined) expectString(obj.excerpt, `${path}.excerpt`)\n}\n\nfunction assertJson(value: unknown, path: string): asserts value is AgentProfileJson {\n if (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value))\n ) {\n return\n }\n if (Array.isArray(value)) {\n for (const [i, item] of value.entries()) assertJson(item, `${path}.${i}`)\n return\n }\n if (typeof value === 'object') {\n for (const [key, item] of Object.entries(value)) {\n if (!key) throw new PolicyEditValidationError('empty object key', path)\n assertJson(item, `${path}.${key}`)\n }\n return\n }\n throw new PolicyEditValidationError('expected JSON-compatible value', path)\n}\n\nfunction targetSpecificityScore(edit: PolicyEdit): number {\n let score = 0.4\n if (edit.target.path) score += 0.25\n if (edit.target.agentProfileCell) score += 0.15\n if (edit.change.kind === 'json' || edit.change.mode === 'replace') score += 0.2\n else if (edit.change.value.length > 0) score += 0.1\n return clamp01(score)\n}\n\n// Assigning through these keys on a plain object mutates the prototype chain\n// instead of writing an own property: the edit silently no-ops after\n// JSON.stringify, or crashes the canonical hasher. Edits are analyst- and\n// LLM-authored input, so the refusal is loud, at parse time.\nconst FORBIDDEN_PATH_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\nfunction splitPath(path: string): string[] {\n const parts = path\n .split('.')\n .map((p) => p.trim())\n .filter(Boolean)\n if (parts.length === 0)\n throw new PolicyEditValidationError('path must not be empty', 'change.path')\n for (const part of parts) {\n if (FORBIDDEN_PATH_KEYS.has(part)) {\n throw new PolicyEditValidationError(\n `path segment \"${part}\" would write through the prototype chain`,\n 'change.path',\n )\n }\n }\n return parts\n}\n\nfunction expectLiteral<T extends string>(\n value: unknown,\n expected: T,\n path: string,\n): asserts value is T {\n if (value !== expected) throw new PolicyEditValidationError(`expected ${expected}`, path)\n}\n\nfunction expectString(value: unknown, path: string): asserts value is string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new PolicyEditValidationError('expected non-empty string', path)\n }\n}\n\nfunction expectNonEmpty(value: unknown, path: string): string {\n expectString(value, path)\n return value\n}\n\nfunction expectConfidence(value: unknown, path: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {\n throw new PolicyEditValidationError('expected finite number in [0,1]', path)\n }\n}\n\nfunction hasExactTextBlock(surface: string, value: string): boolean {\n const needle = normalizeTextBlock(value)\n const normalizedSurface = surface.replace(/\\r\\n/g, '\\n')\n return [...normalizedSurface.split(/\\n{2,}/), ...normalizedSurface.split('\\n')].some(\n (block) => normalizeTextBlock(block) === needle,\n )\n}\n\nfunction normalizeTextBlock(value: string): string {\n return value.replace(/\\r\\n/g, '\\n').trim()\n}\n\nfunction expectOneOf<const T extends readonly string[]>(\n value: unknown,\n allowed: T,\n path: string,\n): asserts value is T[number] {\n if (typeof value !== 'string' || !allowed.includes(value)) {\n throw new PolicyEditValidationError(`expected one of ${allowed.join(', ')}`, path)\n }\n}\n\nfunction expectStringArray(value: unknown, path: string): asserts value is string[] {\n if (!Array.isArray(value)) throw new PolicyEditValidationError('expected array', path)\n for (const [i, item] of value.entries()) expectString(item, `${path}.${i}`)\n}\n\nfunction expectNonEmptyStringArray(value: unknown, path: string): asserts value is string[] {\n expectStringArray(value, path)\n if (value.length === 0) throw new PolicyEditValidationError('expected non-empty array', path)\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return [...new Set(values)].sort()\n}\n\nfunction clamp01(n: number): number {\n if (!Number.isFinite(n)) return 0\n if (n < 0) return 0\n if (n > 1) return 1\n return n\n}\n","/**\n * Capability-headroom gate — \"can this task set even SEE the capability\n * you're about to A/B?\"\n *\n * A capability A/B (grant one arm a tool, a skill, extra context — anything)\n * can only detect the capability on tasks the capability-ABSENT baseline\n * FAILS. A task the baseline already passes is saturated: the treatment arm\n * has no headroom to demonstrate anything, and averaging saturated tasks into\n * the comparison dilutes a real effect toward a false null. Calibrate before\n * measuring: run the baseline arm first, classify every task's headroom, and\n * refuse to run the comparison when no task has a gap.\n *\n * Fail-closed on unknown outcomes: a baseline run whose outcome could not be\n * determined (infra loss, unverified, missing) NEVER counts as a failure —\n * treating \"couldn't tell\" as \"failed\" would manufacture headroom out of\n * telemetry gaps and launder infra noise into a treatment effect.\n *\n * Domain-free by construction: the capability under test never appears here.\n * Callers decide what the baseline arm lacks; this module only classifies\n * baseline outcomes per task.\n */\n\nimport { ValidationError } from './errors'\n\n/** One baseline-arm (capability-absent) observation of one task. */\nexport interface HeadroomInput {\n /** Stable task identity; multiple rows per task are multiple baseline reps. */\n taskId: string\n /** Baseline outcome. 'unknown' = the outcome could not be determined —\n * distinct from 'fail' and never counted as one. */\n baselineOutcome: 'pass' | 'fail' | 'unknown'\n}\n\n/** Headroom classification for one task.\n * - 'gap': the baseline fails it — the comparison can see the capability here.\n * - 'saturated': the baseline already passes it — no headroom.\n * - 'unknown': every baseline outcome is unknown — fail-closed, not a gap. */\nexport type HeadroomClass = 'gap' | 'saturated' | 'unknown'\n\nexport interface TaskHeadroom {\n taskId: string\n /** Total baseline observations for this task (known + unknown). */\n n: number\n /** Observations with a known ('pass' | 'fail') outcome — the evidence the\n * classification actually rests on. A large `n` with a small `nKnown`\n * means the headroom verdict is thin, not well-replicated. */\n nKnown: number\n /** Pass rate over KNOWN outcomes only; NaN when every outcome is unknown\n * (no data ≠ measured zero). */\n baselinePassRate: number\n headroom: HeadroomClass\n}\n\nexport interface CapabilityHeadroomOptions {\n /** A task counts as 'gap' when its baseline pass rate is ≤ this. Default 0\n * (the baseline must fail every known rep). Must be in [0, 1) — a\n * threshold of 1 would classify a fully-saturated task as a gap. */\n keepThreshold?: number\n}\n\nexport interface CapabilityHeadroomResult {\n /** Per-task classification, sorted by `taskId`. */\n tasks: TaskHeadroom[]\n summary: {\n tasksWithGap: number\n tasksSaturated: number\n tasksUnknown: number\n /** Total unknown-outcome reps across ALL tasks (including tasks that\n * still classified via their known reps) — the size of the telemetry\n * hole behind the classifications. */\n repsUnknown: number\n }\n}\n\n/**\n * Classify every task's baseline headroom from capability-absent baseline\n * outcomes.\n *\n * A task is 'gap' when it has ≥ 1 known outcome and its pass rate over known\n * outcomes is ≤ `keepThreshold`; 'saturated' when the rate exceeds the\n * threshold; 'unknown' when every outcome is unknown. Unknown reps never\n * count toward the rate in either direction (fail-closed — see the module\n * doc), and evidence strength stays visible: each task reports `nKnown`\n * alongside `n`, and the summary totals the unknown reps in `repsUnknown`.\n * Throws on empty input, an out-of-range `keepThreshold`, or an\n * unrecognized outcome value (rows are often projected from untyped records).\n */\nexport function capabilityHeadroom(\n rows: readonly HeadroomInput[],\n opts: CapabilityHeadroomOptions = {},\n): CapabilityHeadroomResult {\n const keepThreshold = opts.keepThreshold ?? 0\n if (!Number.isFinite(keepThreshold) || keepThreshold < 0 || keepThreshold >= 1) {\n throw new ValidationError(\n `capabilityHeadroom: keepThreshold must be in [0, 1), got ${keepThreshold}`,\n )\n }\n if (rows.length === 0) {\n throw new ValidationError(\n 'capabilityHeadroom: no baseline rows supplied — run the capability-absent baseline arm first',\n )\n }\n\n // taskId → { n, passes, known }\n const byTask = new Map<string, { n: number; passes: number; known: number }>()\n for (const row of rows) {\n if (\n row.baselineOutcome !== 'pass' &&\n row.baselineOutcome !== 'fail' &&\n row.baselineOutcome !== 'unknown'\n ) {\n throw new ValidationError(\n `capabilityHeadroom: unrecognized baselineOutcome '${row.baselineOutcome}' for task '${row.taskId}' (expected 'pass' | 'fail' | 'unknown')`,\n )\n }\n const agg = byTask.get(row.taskId) ?? { n: 0, passes: 0, known: 0 }\n agg.n++\n if (row.baselineOutcome !== 'unknown') {\n agg.known++\n if (row.baselineOutcome === 'pass') agg.passes++\n }\n byTask.set(row.taskId, agg)\n }\n\n const tasks: TaskHeadroom[] = [...byTask.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([taskId, agg]) => {\n if (agg.known === 0) {\n return {\n taskId,\n n: agg.n,\n nKnown: 0,\n baselinePassRate: Number.NaN,\n headroom: 'unknown' as const,\n }\n }\n const baselinePassRate = agg.passes / agg.known\n return {\n taskId,\n n: agg.n,\n nKnown: agg.known,\n baselinePassRate,\n headroom: baselinePassRate <= keepThreshold ? ('gap' as const) : ('saturated' as const),\n }\n })\n\n const summary = {\n tasksWithGap: tasks.filter((t) => t.headroom === 'gap').length,\n tasksSaturated: tasks.filter((t) => t.headroom === 'saturated').length,\n tasksUnknown: tasks.filter((t) => t.headroom === 'unknown').length,\n repsUnknown: tasks.reduce((sum, t) => sum + (t.n - t.nKnown), 0),\n }\n return { tasks, summary }\n}\n\nexport interface AssertCapabilityHeadroomOptions {\n /** Minimum tasks classified 'gap' for the comparison to proceed. Default 1. */\n minTasksWithGap?: number\n}\n\n/**\n * The go/no-go guard: throws when fewer than `minTasksWithGap` tasks have\n * baseline headroom — i.e. the benchmark cannot see the capability, so any\n * comparison run on it would measure noise. Call between the baseline\n * calibration run and the treatment run.\n */\nexport function assertCapabilityHeadroom(\n result: CapabilityHeadroomResult,\n opts: AssertCapabilityHeadroomOptions = {},\n): void {\n const minTasksWithGap = opts.minTasksWithGap ?? 1\n if (!Number.isInteger(minTasksWithGap) || minTasksWithGap < 1) {\n throw new ValidationError(\n `assertCapabilityHeadroom: minTasksWithGap must be an integer ≥ 1, got ${minTasksWithGap}`,\n )\n }\n const { tasksWithGap, tasksSaturated, tasksUnknown } = result.summary\n if (tasksWithGap < minTasksWithGap) {\n const total = result.tasks.length\n throw new ValidationError(\n `assertCapabilityHeadroom: only ${tasksWithGap} of ${total} task(s) have baseline headroom ` +\n `(need ≥ ${minTasksWithGap}). ${tasksSaturated} saturated (baseline already passes), ` +\n `${tasksUnknown} unknown (no determinable baseline outcome). A capability A/B on this ` +\n `task set cannot detect the capability — add tasks the baseline fails, or fix baseline ` +\n `outcome capture, before measuring.`,\n )\n }\n}\n","/**\n * Cost tracker — token + USD accounting per scenario and per run.\n *\n * Adapted from generic usage-event accounting. Every\n * optimizer needs to know \"is the quality gain worth the cost delta?\",\n * and every dashboard needs dollars-per-completed-task. MODEL_PRICING\n * from metrics.ts stays authoritative for estimate math; this module\n * adds the aggregation + per-scenario roll-up that was duplicated\n * across 4 verticals.\n */\n\nimport { estimateCost } from './metrics'\n\nexport interface TokenSpec {\n inputTokens: number\n outputTokens: number\n cachedTokens?: number\n reasoningTokens?: number\n}\n\nexport interface CostEntry extends TokenSpec {\n scenarioId: string\n model: string\n /** Override estimate with an observed cost (e.g. from provider response). */\n actualCostUsd?: number\n timestamp: number\n /** Free-form tags (variant id, round #, etc.). */\n tags?: Record<string, string>\n}\n\nexport interface ScenarioCost {\n scenarioId: string\n entries: CostEntry[]\n totalInputTokens: number\n totalOutputTokens: number\n totalCachedTokens: number\n totalCostUsd: number\n /** Pass flag — set by consumer via markOutcome; used for cost-per-completed-task. */\n completed?: boolean\n}\n\nexport class CostTracker {\n private byScenario = new Map<string, ScenarioCost>()\n\n record(entry: Omit<CostEntry, 'timestamp'> & { timestamp?: number }): CostEntry {\n const full: CostEntry = { timestamp: entry.timestamp ?? Date.now(), ...entry }\n assertNonNegative(full.inputTokens, 'inputTokens')\n assertNonNegative(full.outputTokens, 'outputTokens')\n let bucket = this.byScenario.get(full.scenarioId)\n if (!bucket) {\n bucket = {\n scenarioId: full.scenarioId,\n entries: [],\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCachedTokens: 0,\n totalCostUsd: 0,\n }\n this.byScenario.set(full.scenarioId, bucket)\n }\n bucket.entries.push(full)\n bucket.totalInputTokens += full.inputTokens\n bucket.totalOutputTokens += full.outputTokens\n bucket.totalCachedTokens += full.cachedTokens ?? 0\n bucket.totalCostUsd += costFor(full)\n return full\n }\n\n markOutcome(scenarioId: string, completed: boolean): void {\n const bucket = this.byScenario.get(scenarioId)\n if (!bucket) throw new Error(`CostTracker.markOutcome: unknown scenario \"${scenarioId}\"`)\n bucket.completed = completed\n }\n\n /**\n * Convenience: record + markOutcome in one call from a\n * `{ usage, verdict }`-shaped response (starter-foundry's\n * `invokeMetaJudge` returns this shape; consumers that wrap any\n * judge/critic can follow the same convention).\n *\n * `usage.model` must be present in `MODEL_PRICING` for cost math to\n * populate; otherwise totalCostUsd stays at 0 for the entry but\n * tokens still aggregate.\n */\n recordVerdict(\n verdict: {\n usage?: {\n inputTokens: number\n outputTokens: number\n model: string\n cachedTokens?: number\n reasoningTokens?: number\n }\n verdict?: 'pass' | 'fail' | 'borderline' | string\n },\n scenarioId: string,\n tags?: Record<string, string>,\n ): CostEntry | null {\n if (!verdict.usage) return null\n const entry = this.record({\n scenarioId,\n model: verdict.usage.model,\n inputTokens: verdict.usage.inputTokens,\n outputTokens: verdict.usage.outputTokens,\n cachedTokens: verdict.usage.cachedTokens,\n reasoningTokens: verdict.usage.reasoningTokens,\n tags,\n })\n this.markOutcome(scenarioId, verdict.verdict === 'pass')\n return entry\n }\n\n get(scenarioId: string): ScenarioCost | undefined {\n return this.byScenario.get(scenarioId)\n }\n\n list(): ScenarioCost[] {\n return [...this.byScenario.values()]\n }\n\n summary(): CostSummary {\n const scenarios = this.list()\n const completed = scenarios.filter((s) => s.completed === true)\n const totalCost = scenarios.reduce((a, s) => a + s.totalCostUsd, 0)\n const totalInput = scenarios.reduce((a, s) => a + s.totalInputTokens, 0)\n const totalOutput = scenarios.reduce((a, s) => a + s.totalOutputTokens, 0)\n const totalCompletedCost = completed.reduce((a, s) => a + s.totalCostUsd, 0)\n return {\n scenarioCount: scenarios.length,\n completedCount: completed.length,\n totalInputTokens: totalInput,\n totalOutputTokens: totalOutput,\n totalCostUsd: totalCost,\n avgCostPerScenarioUsd: scenarios.length ? totalCost / scenarios.length : 0,\n costPerCompletedTaskUsd: completed.length ? totalCompletedCost / completed.length : null,\n }\n }\n}\n\nexport interface CostSummary {\n scenarioCount: number\n completedCount: number\n totalInputTokens: number\n totalOutputTokens: number\n totalCostUsd: number\n avgCostPerScenarioUsd: number\n /** Total USD / completed scenarios — null when nothing completed. */\n costPerCompletedTaskUsd: number | null\n}\n\nfunction costFor(entry: CostEntry): number {\n if (typeof entry.actualCostUsd === 'number' && Number.isFinite(entry.actualCostUsd)) {\n return entry.actualCostUsd\n }\n return estimateCost(entry.inputTokens, entry.outputTokens, entry.model)\n}\n\nfunction assertNonNegative(n: number, name: string): void {\n if (!Number.isFinite(n) || n < 0) {\n throw new Error(`CostTracker: ${name} must be a non-negative finite number, got ${n}`)\n }\n}\n","/**\n * Toolchain error-count extractor.\n *\n * Given stderr/stdout from a compiler or test runner, count the number\n * of reported errors/failures. Patterns are deliberately narrow —\n * unknown stderr returns `null` rather than zero so callers can\n * distinguish \"no errors\" from \"different toolchain, couldn't parse\".\n *\n * All patterns are anchored to the start of a line and use bounded\n * character classes to avoid catastrophic backtracking on pathological\n * inputs.\n *\n * Add new toolchains by appending to {@link ERROR_COUNT_PATTERNS};\n * order matters only in the sense that the first matching pattern wins.\n */\n\nexport interface ErrorCountPattern {\n /** Stable identifier for logging + tests. */\n name: string\n /** Must be global (`g` flag) — the extractor counts matches. */\n regex: RegExp\n /** Optional post-processing to extract a count from a single captured match. */\n transform?: (match: RegExpMatchArray) => number\n}\n\nexport const ERROR_COUNT_PATTERNS: ErrorCountPattern[] = [\n {\n // tsc / ts-node: `src/foo.ts(12,3): error TS1234: ...`\n name: 'typescript-tsc',\n regex: /[\\w./-]+\\(\\d+,\\d+\\): error TS\\d+:/g,\n },\n {\n // pytest: `FAILED tests/test_foo.py::test_bar`\n name: 'pytest-failed',\n regex: /^FAILED\\s+\\S+/gm,\n },\n {\n // rustc: `error[E0308]: ...` or `error: ...`\n name: 'rustc',\n regex: /^error(?:\\[[A-Z]\\d+\\])?:/gm,\n },\n {\n // go build: `./foo.go:12:3: ...` — any file:line:col: is an error line\n name: 'golang',\n regex: /^\\.\\/[\\w./-]+\\.go:\\d+:\\d+:/gm,\n },\n {\n // eslint default formatter per-line: ` 12:34 error message rule-id`\n name: 'eslint',\n regex: /^\\s+\\d+:\\d+\\s+error\\s+/gm,\n },\n {\n // eslint summary line: `✖ 17 problems (12 errors, 5 warnings)`\n // Use this only when the per-line formatter isn't present; transform\n // reads the errors count directly.\n name: 'eslint-summary',\n regex: /✖\\s+\\d+\\s+problems?\\s+\\((\\d+)\\s+errors?/gm,\n transform: (m) => Number(m[1] ?? 0),\n },\n]\n\nexport interface ExtractOptions {\n /** Restrict to named patterns — default: all patterns. */\n only?: string[]\n /** Additional patterns to consider BEFORE the built-in list. */\n extra?: ErrorCountPattern[]\n}\n\nexport interface ExtractResult {\n /** Total count of matched errors, or null when no pattern matched. */\n count: number | null\n /** Name of the pattern that matched, or null. */\n matched: string | null\n /** Original matches for callers that want to surface specifics. */\n samples: string[]\n}\n\n/**\n * Try each pattern in order; return the first with matches.\n *\n * Returning `null` (instead of zero) on no-match is deliberate — a\n * callsite that greps for \"typescript errors\" on cargo output should\n * NOT treat that as \"zero TS errors\" because the toolchain is wrong.\n */\nexport function extractErrorCount(text: string, opts: ExtractOptions = {}): ExtractResult {\n if (!text) return { count: null, matched: null, samples: [] }\n\n const patterns = [...(opts.extra ?? []), ...ERROR_COUNT_PATTERNS].filter(\n (p) => !opts.only || opts.only.includes(p.name),\n )\n\n for (const p of patterns) {\n const matches = Array.from(text.matchAll(p.regex))\n if (matches.length === 0) continue\n\n const count = p.transform\n ? matches.reduce((sum, m) => sum + p.transform!(m), 0)\n : matches.length\n\n return {\n count,\n matched: p.name,\n samples: matches.slice(0, 5).map((m) => m[0]),\n }\n }\n\n return { count: null, matched: null, samples: [] }\n}\n","import { type ControlEvalResult, objectiveEval } from '../control-runtime'\nimport type { TraceEmitter } from '../trace/emitter'\nimport type {\n DataAcquisitionPlan,\n KnowledgeAcquisitionMode,\n KnowledgeBundle,\n KnowledgeImportance,\n KnowledgeReadinessReport,\n KnowledgeRecommendedAction,\n KnowledgeRequirement,\n UserQuestion,\n} from './types'\n\nexport interface ScoreKnowledgeReadinessOptions {\n taskId: string\n requirements: KnowledgeRequirement[]\n evidenceIds?: string[]\n claimIds?: string[]\n wikiPageIds?: string[]\n userAnswers?: Record<string, string>\n metadata?: Record<string, unknown>\n now?: Date\n}\n\nexport function scoreKnowledgeReadiness(\n options: ScoreKnowledgeReadinessOptions,\n): KnowledgeReadinessReport {\n const now = options.now ?? new Date()\n const requirements = options.requirements.map(normalizeRequirement)\n const missing = requirements.filter((requirement) => isRequirementMissing(requirement, now))\n const blockingMissingRequirements = missing.filter(isBlockingGap)\n const nonBlockingGaps = missing.filter((requirement) => !isBlockingGap(requirement))\n const readinessScore = weightedReadinessAt(requirements, now)\n const bundle: KnowledgeBundle = {\n taskId: options.taskId,\n requirements,\n evidenceIds: unique([\n ...(options.evidenceIds ?? []),\n ...requirements.flatMap((r) => r.evidenceIds),\n ]),\n claimIds: unique(options.claimIds ?? []),\n wikiPageIds: unique(options.wikiPageIds ?? []),\n userAnswers: options.userAnswers ?? {},\n missing,\n readinessScore,\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n }\n const recommendedAction = chooseRecommendedAction(blockingMissingRequirements, nonBlockingGaps)\n const severity =\n blockingMissingRequirements.length > 0\n ? 'critical'\n : nonBlockingGaps.some((gap) => gap.importance === 'high')\n ? 'warning'\n : 'info'\n const reason =\n blockingMissingRequirements.length > 0\n ? `${blockingMissingRequirements.length} blocking knowledge requirement(s) are missing.`\n : nonBlockingGaps.length > 0\n ? `${nonBlockingGaps.length} non-blocking knowledge gap(s) remain.`\n : 'All declared knowledge requirements are ready.'\n\n return {\n taskId: options.taskId,\n readinessScore,\n blockingMissingRequirements,\n nonBlockingGaps,\n recommendedAction,\n bundle,\n severity,\n reason,\n }\n}\n\nexport function blockingKnowledgeEval(\n report: KnowledgeReadinessReport,\n options: { id?: string; minimumScore?: number; emitter?: TraceEmitter } = {},\n): ControlEvalResult {\n const minimumScore = options.minimumScore ?? 0.7\n const passed =\n report.blockingMissingRequirements.length === 0 && report.readinessScore >= minimumScore\n if (options.emitter) {\n void options.emitter\n .emit({\n kind: 'custom',\n payload: knowledgeReadinessTracePayload(report, { passed, minimumScore }),\n })\n .catch(() => undefined)\n }\n return objectiveEval({\n id: options.id ?? 'knowledge-ready',\n passed,\n score: report.readinessScore,\n severity: passed ? 'info' : report.severity,\n detail: report.reason,\n evidence: report.blockingMissingRequirements.map((r) => r.id).join(', ') || undefined,\n metadata: { knowledgeReadiness: report },\n })\n}\n\nexport function knowledgeReadinessTracePayload(\n report: KnowledgeReadinessReport,\n options: { passed?: boolean; minimumScore?: number } = {},\n): Record<string, unknown> {\n return {\n kind: 'readiness_scored',\n taskId: report.taskId,\n passed: options.passed ?? report.blockingMissingRequirements.length === 0,\n readinessScore: report.readinessScore,\n minimumScore: options.minimumScore,\n blockingRequirementIds: report.blockingMissingRequirements.map((r) => r.id),\n nonBlockingRequirementIds: report.nonBlockingGaps.map((r) => r.id),\n recommendedAction: report.recommendedAction,\n severity: report.severity,\n reason: report.reason,\n }\n}\n\nexport function userQuestionsForKnowledgeGaps(gaps: KnowledgeRequirement[]): UserQuestion[] {\n return gaps\n .filter((gap) => gap.acquisitionMode === 'ask_user' || gap.fallbackPolicy === 'ask')\n .map((gap) => ({\n id: `question_${gap.id}`,\n question: `Please provide: ${gap.description}`,\n reason: `Required for ${gap.requiredFor.join(', ') || 'the task'}.`,\n requirementId: gap.id,\n importance: gap.importance,\n answerType: gap.sensitivity === 'secret' ? 'credential' : 'free_text',\n impactIfUnknown: impactFor(gap),\n }))\n}\n\nexport function acquisitionPlansForKnowledgeGaps(\n gaps: KnowledgeRequirement[],\n): DataAcquisitionPlan[] {\n const byMode = new Map<string, KnowledgeRequirement[]>()\n for (const gap of gaps) {\n const mode = planMode(gap.acquisitionMode)\n if (!mode) continue\n const bucket = byMode.get(mode) ?? []\n bucket.push(gap)\n byMode.set(mode, bucket)\n }\n return [...byMode.entries()].map(([mode, requirements]) => ({\n id: `acquire_${mode}`,\n requirementIds: requirements.map((r) => r.id),\n mode: mode as DataAcquisitionPlan['mode'],\n description: descriptionForPlan(mode as DataAcquisitionPlan['mode'], requirements),\n priority: maxImportance(requirements.map((r) => r.importance)),\n ...(mode === 'ask_user' ? { questions: userQuestionsForKnowledgeGaps(requirements) } : {}),\n }))\n}\n\nfunction normalizeRequirement(requirement: KnowledgeRequirement): KnowledgeRequirement {\n return {\n ...requirement,\n confidenceNeeded: clamp01(requirement.confidenceNeeded),\n currentConfidence: clamp01(requirement.currentConfidence),\n evidenceIds: unique(requirement.evidenceIds),\n }\n}\n\nfunction weightedReadinessAt(requirements: KnowledgeRequirement[], now: Date): number {\n if (requirements.length === 0) return 1\n let weightSum = 0\n let scoreSum = 0\n for (const requirement of requirements) {\n const weight = importanceWeight(requirement.importance)\n const score = isExpired(requirement, now)\n ? 0\n : requirement.confidenceNeeded <= 0\n ? 1\n : Math.min(1, requirement.currentConfidence / requirement.confidenceNeeded)\n weightSum += weight\n scoreSum += weight * score\n }\n return clamp01(scoreSum / weightSum)\n}\n\nfunction isRequirementMissing(requirement: KnowledgeRequirement, now: Date): boolean {\n return isExpired(requirement, now) || requirement.currentConfidence < requirement.confidenceNeeded\n}\n\nfunction isExpired(requirement: KnowledgeRequirement, now: Date): boolean {\n if (!requirement.validUntil) return false\n const deadline = Date.parse(requirement.validUntil)\n if (!Number.isFinite(deadline)) return true\n return deadline <= now.getTime()\n}\n\nfunction isBlockingGap(requirement: KnowledgeRequirement): boolean {\n return (\n requirement.importance === 'blocking' ||\n requirement.fallbackPolicy === 'block' ||\n requirement.sensitivity === 'secret'\n )\n}\n\nfunction chooseRecommendedAction(\n blocking: KnowledgeRequirement[],\n nonBlocking: KnowledgeRequirement[],\n): KnowledgeRecommendedAction {\n const gaps = blocking.length > 0 ? blocking : nonBlocking\n if (gaps.length === 0) return 'run_agent'\n if (gaps.some((gap) => gap.acquisitionMode === 'ask_user' || gap.fallbackPolicy === 'ask'))\n return 'ask_user'\n if (gaps.some((gap) => gap.acquisitionMode === 'query_connector')) return 'query_connectors'\n if (\n gaps.some(\n (gap) => gap.acquisitionMode === 'inspect_repo' || gap.acquisitionMode === 'run_command',\n )\n )\n return 'inspect_repo'\n if (gaps.some((gap) => gap.acquisitionMode === 'search_web')) return 'collect_web_data'\n if (gaps.some((gap) => gap.acquisitionMode === 'not_available')) return 'abort_or_rescope'\n if (nonBlocking.some((gap) => gap.importance === 'high')) return 'build_domain_wiki'\n return 'continue_with_caveat'\n}\n\nfunction planMode(mode: KnowledgeAcquisitionMode): DataAcquisitionPlan['mode'] | null {\n if (mode === 'infer_low_confidence' || mode === 'not_available') return null\n return mode\n}\n\nfunction descriptionForPlan(\n mode: DataAcquisitionPlan['mode'],\n requirements: KnowledgeRequirement[],\n): string {\n const labels = requirements.map((r) => r.description).join('; ')\n if (mode === 'ask_user') return `Ask the user for: ${labels}`\n if (mode === 'search_web') return `Search web or documentation sources for: ${labels}`\n if (mode === 'query_connector') return `Query configured connectors for: ${labels}`\n if (mode === 'inspect_repo') return `Inspect repository context for: ${labels}`\n if (mode === 'run_command') return `Run local commands to collect: ${labels}`\n return `Build domain wiki evidence for: ${labels}`\n}\n\nfunction impactFor(requirement: KnowledgeRequirement): string {\n if (requirement.fallbackPolicy === 'block') return 'The agent should not run until this is known.'\n if (requirement.fallbackPolicy === 'continue_with_caveat')\n return 'The agent may continue, but must disclose uncertainty.'\n if (requirement.fallbackPolicy === 'use_default')\n return 'The agent will use the configured default if skipped.'\n return 'The agent should ask before continuing.'\n}\n\nfunction maxImportance(values: KnowledgeImportance[]): KnowledgeImportance {\n const order: KnowledgeImportance[] = ['blocking', 'high', 'medium', 'low']\n return order.find((value) => values.includes(value)) ?? 'low'\n}\n\nfunction importanceWeight(importance: KnowledgeImportance): number {\n if (importance === 'blocking') return 8\n if (importance === 'high') return 4\n if (importance === 'medium') return 2\n return 1\n}\n\nfunction clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n\nfunction unique<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n","/**\n * Cross-profile leaderboard — rank agent profiles (or any grouping) over a corpus\n * of RunRecords on pass-rate with a Wilson CI, joined with the cost / token /\n * latency rollup every benchmark wants next to the score.\n *\n * This is substrate, not benchmark-specific: any consumer of agent-eval gets a\n * cross-harness × model leaderboard without re-implementing grouping, binomial\n * CIs, or the observability join. The benchmark supplies only what \"passed\"\n * means; everything else composes existing primitives (`wilson`, the RunRecord\n * cost/token/wall fields, the AgentProfileCell grouping key).\n */\nimport type { RunRecord } from './run-record'\nimport { wilson } from './statistics'\n\nexport interface LeaderboardRow {\n /** Group key — the agent-profile cellId by default, else a caller dimension. */\n key: string\n /** Display label: `harness · model` when the profile carries them, else the key. */\n label: string\n harness?: string\n model?: string\n rank: number\n /** Measured runs in this group. */\n n: number\n passRate: number\n passRateCi95: [number, number]\n /** Observability rollup — means over the group; null when no run reported it. */\n meanCostUsd: number | null\n meanTokensIn: number | null\n meanTokensOut: number | null\n meanWallMs: number | null\n}\n\nexport interface LeaderboardOptions {\n /** Per-run pass predicate — the benchmark defines what \"passed\" means (real-build\n * hit-rate, test-pass, etc.). The leaderboard owns only the grouping + stats. */\n passed: (record: RunRecord) => boolean\n /** Group key. Default: the agent-profile cellId (harness × model × dimensions),\n * so persona/harness/model sweeps separate without parsing labels. */\n groupBy?: (record: RunRecord) => string\n}\n\nfunction mean(xs: number[]): number | null {\n return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : null\n}\n\n/**\n * Group `records`, compute pass-rate + Wilson CI + cost/token/latency means per\n * group, and rank by pass-rate (cost as the tiebreaker — cheaper wins a tie).\n * Pure projection: no I/O, deterministic, safe to call on any RunRecord[].\n */\nexport function leaderboard(records: RunRecord[], opts: LeaderboardOptions): LeaderboardRow[] {\n const keyOf = opts.groupBy ?? ((r: RunRecord) => r.agentProfile?.cellId ?? 'ungrouped')\n const groups = new Map<string, RunRecord[]>()\n for (const r of records) {\n const k = keyOf(r)\n const g = groups.get(k)\n if (g) g.push(r)\n else groups.set(k, [r])\n }\n\n const rows: LeaderboardRow[] = [...groups.entries()].map(([key, rs]) => {\n const passes = rs.filter((r) => opts.passed(r)).length\n const ci = wilson(passes, rs.length)\n const profile = rs[0]!.agentProfile\n const harness = profile?.harness?.id\n const model = profile?.model\n const knownCosts = rs.map((r) => r.costUsd).filter(isFiniteNumber)\n return {\n key,\n label: harness && model ? `${harness} · ${model}` : key,\n ...(harness ? { harness } : {}),\n ...(model ? { model } : {}),\n rank: 0,\n n: rs.length,\n passRate: ci.estimate,\n passRateCi95: [ci.lower, ci.upper],\n meanCostUsd: knownCosts.length === rs.length ? mean(knownCosts) : null,\n meanTokensIn: mean(rs.map((r) => r.tokenUsage.input)),\n meanTokensOut: mean(rs.map((r) => r.tokenUsage.output)),\n meanWallMs: mean(rs.map((r) => r.wallMs)),\n }\n })\n\n rows.sort(\n (a, b) => b.passRate - a.passRate || (a.meanCostUsd ?? Infinity) - (b.meanCostUsd ?? Infinity),\n )\n rows.forEach((row, i) => {\n row.rank = i + 1\n })\n return rows\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n","/**\n * Deterministic held-out partitioning over stable ids.\n *\n * A promotion gate's paired-delta math needs a fixed partition: the same\n * scenario id lands in the same bucket forever, regardless of when it ran or\n * which loop emitted the record — otherwise the gate has nothing paired to\n * compare against. Picking one global split per run is wrong: every run then\n * stamps either ALL search or ALL holdout, and no id is ever observed on both\n * sides. Per-id deterministic hashing fixes that.\n *\n * Two consumers hand-roll this (agent-builder's `deterministicSplit` and the\n * frontier persona-splitter). The substrate already has a 3-way benchmark\n * `deterministicSplit` in `./benchmarks`; this is the generic, validated batch\n * partitioner: it takes a list of ids, splits them by a stable FNV-1a hash, and\n * fails loud when the inputs can't support a trustworthy held-out comparison\n * (duplicate ids, or a holdout set below the significance floor).\n */\n\nimport { ValidationError } from './errors'\n\n/** 32-bit FNV-1a over UTF-16 code units masked to a byte. Stable,\n * allocation-free, deterministic across runtimes — the same id+seed maps to\n * the same bucket on every machine and process.\n *\n * Frozen: this value picks the held-out bucket, so changing the masking or\n * the accumulator re-partitions every split already decided under it and\n * silently invalidates the comparisons made against them. The other FNV-1a\n * loops in this package mask differently and are not interchangeable with\n * this one. */\nexport function fnv1a32(input: string): number {\n let h = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i) & 0xff\n h = Math.imul(h, 0x01000193)\n }\n return h >>> 0\n}\n\n/** Map an id+seed to the half-open unit interval [0, 1) deterministically. */\nexport function hashToUnit(id: string, seed: string): number {\n // Newline separator: 'ab' + '\\n' + 'c' can't collide with 'a' + '\\n' + 'bc'.\n return fnv1a32(`${id}\\n${seed}`) / 0x1_0000_0000\n}\n\nexport interface PartitionHeldOutOptions {\n /** Partition seed. Bumping it reshuffles every assignment — do that only when\n * the corpus/policy changes meaningfully so old and new records can't pair.\n * Default 'held-out-v1'. */\n seed?: string\n /** Fraction routed to the held-out bucket, in (0, 1). Default 0.5. */\n holdoutFraction?: number\n /**\n * Minimum held-out ids required for the split to be admissible. Below this,\n * a paired comparison has too few observations to be significant, so the\n * partition throws rather than hand back an underpowered holdout. Default 1\n * (only the empty-holdout degenerate case is rejected). Raise it to enforce\n * real statistical power. */\n minHoldout?: number\n /** Same floor for the search side. Default 1. */\n minSearch?: number\n}\n\nexport interface HeldOutPartition {\n /** Ids the optimizer is allowed to read/optimize against. */\n search: string[]\n /** Ids reserved for gated, held-out evaluation. */\n holdout: string[]\n seed: string\n holdoutFraction: number\n}\n\n/**\n * Assign a single id to `'search'` or `'holdout'` deterministically. Same\n * `(id, seed)` always returns the same tag — the invariant the gate relies on.\n * Use this in a `splitTag:` field literal when stamping records one at a time;\n * use `partitionHeldOut` when you have the whole id list up front and want the\n * validated disjoint split.\n */\nexport function assignHeldOutTag(\n id: string,\n options: { seed?: string; holdoutFraction?: number } = {},\n): 'search' | 'holdout' {\n const seed = options.seed ?? 'held-out-v1'\n const holdoutFraction = options.holdoutFraction ?? 0.5\n assertFraction(holdoutFraction)\n return hashToUnit(id, seed) < holdoutFraction ? 'holdout' : 'search'\n}\n\n/**\n * Partition a list of stable ids into disjoint `search` / `holdout` sets by a\n * deterministic hash. Fail-loud:\n * - empty input throws,\n * - duplicate ids throw (a dup would be observed on both sides, double-counting),\n * - a holdout (or search) set below its floor throws (underpowered comparison).\n *\n * Order within each bucket follows the input order, so the result is stable and\n * reproducible.\n */\nexport function partitionHeldOut(\n ids: string[],\n options: PartitionHeldOutOptions = {},\n): HeldOutPartition {\n const seed = options.seed ?? 'held-out-v1'\n const holdoutFraction = options.holdoutFraction ?? 0.5\n const minHoldout = options.minHoldout ?? 1\n const minSearch = options.minSearch ?? 1\n assertFraction(holdoutFraction)\n if (ids.length === 0) {\n throw new ValidationError('partitionHeldOut: no ids supplied')\n }\n\n const seen = new Set<string>()\n const search: string[] = []\n const holdout: string[] = []\n for (const id of ids) {\n if (typeof id !== 'string' || id.length === 0) {\n throw new ValidationError(\n `partitionHeldOut: ids must be non-empty strings, got ${JSON.stringify(id)}`,\n )\n }\n if (seen.has(id)) {\n throw new ValidationError(\n `partitionHeldOut: duplicate id \"${id}\" — a paired comparison must not double-count`,\n )\n }\n seen.add(id)\n if (hashToUnit(id, seed) < holdoutFraction) holdout.push(id)\n else search.push(id)\n }\n\n if (holdout.length < minHoldout) {\n throw new ValidationError(\n `partitionHeldOut: holdout set has ${holdout.length} id(s), below the floor of ${minHoldout} ` +\n `(n=${ids.length}, holdoutFraction=${holdoutFraction}) — too few for a significant comparison`,\n )\n }\n if (search.length < minSearch) {\n throw new ValidationError(\n `partitionHeldOut: search set has ${search.length} id(s), below the floor of ${minSearch} ` +\n `(n=${ids.length}, holdoutFraction=${holdoutFraction})`,\n )\n }\n\n return { search, holdout, seed, holdoutFraction }\n}\n\nfunction assertFraction(f: number): void {\n if (!Number.isFinite(f) || f <= 0 || f >= 1) {\n throw new ValidationError(`partitionHeldOut: holdoutFraction must be in (0, 1), got ${f}`)\n }\n}\n","/**\n * Export side of the product benchmark bundle contract: convert product\n * eval run directories (`records.jsonl` of `RunRecord` rows + trace/raw\n * artifacts) into a portable `product-benchmark-manifest.json` +\n * `product-benchmark-records.jsonl` bundle that\n * `validateProductBenchmarkRun` accepts.\n *\n * Product-specific policy (safety-split detection, tool-call recovery,\n * profile id fallback, artifact materialization) enters through explicit\n * options; everything else is the shared union of the tax/legal/creative\n * exporters. Scenario catalogs, smoke runners, and CLIs stay in the\n * products.\n *\n * Input rows are checked structurally, not with `validateRunRecord`:\n * product harnesses record bare model aliases and partial provenance, and\n * the bundle contract's own validators re-check every field that matters\n * on the way out.\n */\n\nimport { spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { ValidationError } from '../errors'\nimport { type RunRecord, runTaskScore } from '../run-record'\nimport type {\n ProductBenchmarkManifest,\n ProductBenchmarkRecord,\n ProductBenchmarkSplit,\n RuntimeResolution,\n} from './index'\nimport { validateProductBenchmarkManifest, validateProductBenchmarkRecord } from './index'\n\n/** Full mutable-surface superset a product arm may declare. */\nexport const productBenchmarkMutableSurfaces = [\n 'prompt',\n 'resources.files',\n 'tools',\n 'mcp',\n 'hooks',\n 'subagents',\n] as const\n\nexport interface ProductBenchmarkExportOptions {\n /** Source eval run directories, each containing a `records.jsonl` of RunRecord rows. */\n readonly runDirs: readonly string[]\n /** Destination directory for the bundle (manifest + records + materialized source runs). */\n readonly outDir: string\n readonly projectId: string\n readonly benchmarkId: string\n /** Repo-relative path of the product's canonical agent profile source. */\n readonly agentProfilePath: string\n /** Pass threshold applied when a row carries no explicit `outcome.raw.pass`. Default 0.7. */\n readonly passThreshold?: number\n /**\n * First scenario tag. Defaults to `projectId` with a trailing `-agent`\n * stripped (`tax-agent` → `tax`), matching the product exporters.\n */\n readonly scenarioTagPrefix?: string\n /** Profile id used when a row has no `agentProfile.profileId`. Defaults to the row's arm id. */\n readonly fallbackProfileId?: string\n /** Arm mutable surfaces recorded in the manifest. Defaults to the full superset. */\n readonly mutableSurfaces?: readonly string[]\n /**\n * Copy each run dir into `<outDir>/source-runs/` and record\n * bundle-relative artifact paths (portable, self-contained). When false,\n * artifacts keep absolute paths into the original run dirs. Default true.\n */\n readonly materializeSourceRuns?: boolean\n /**\n * Override split classification for a row. Return undefined to fall back\n * to the default (`outcome.raw.safety === 1` → safety, then splitTag).\n */\n readonly classifySplit?: (record: RunRecord) => ProductBenchmarkSplit | undefined\n /** Recovers a tool-call count when the row's raw bag carries none (e.g. from turn artifacts). */\n readonly toolCallFallback?: (record: RunRecord, runDir: string) => number\n /** Backend version recorded per row. Defaults to the cwd package.json's `@tangle-network/sandbox` range. */\n readonly backendVersion?: string\n /**\n * Explicit substrate versions for the manifest, merged over what the cwd\n * package.json / node_modules resolve. Use when a substrate package is not\n * installed where the export runs — the validator refuses an `'unknown'`\n * version, so provide the real one rather than shipping the sentinel.\n */\n readonly substrate?: Partial<ProductBenchmarkManifest['substrate']>\n}\n\nexport interface ProductBenchmarkSingleRunExportOptions\n extends Omit<ProductBenchmarkExportOptions, 'runDirs'> {\n readonly runDir: string\n}\n\nexport interface ProductBenchmarkExportResult {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly records: number\n}\n\ninterface ResolvedExportOptions {\n readonly projectId: string\n readonly benchmarkId: string\n readonly agentProfilePath: string\n readonly passThreshold: number\n readonly scenarioTagPrefix: string\n readonly fallbackProfileId?: string\n readonly mutableSurfaces: readonly string[]\n readonly classifySplit?: (record: RunRecord) => ProductBenchmarkSplit | undefined\n readonly toolCallFallback?: (record: RunRecord, runDir: string) => number\n readonly backendVersion: string\n}\n\n// ── Provenance helpers ───────────────────────────────────────────────\n\nfunction sha256(value: string): string {\n return `sha256:${createHash('sha256').update(value).digest('hex')}`\n}\n\nfunction safePathPart(value: string): string {\n return (\n value\n .replace(/[^a-zA-Z0-9_.-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80) || 'artifact'\n )\n}\n\nfunction git(args: readonly string[], fallback: string): string {\n const res = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8' })\n const value = res.status === 0 ? res.stdout.trim() : ''\n return value.length > 0 ? value : fallback\n}\n\nfunction knownEnv(name: string): string | undefined {\n const value = process.env[name]?.trim()\n return value && value !== 'unknown' ? value : undefined\n}\n\nfunction ciBranchName(): string | undefined {\n const direct =\n knownEnv('GITHUB_HEAD_REF') ?? knownEnv('GITHUB_REF_NAME') ?? knownEnv('VERCEL_GIT_COMMIT_REF')\n if (direct) return direct\n const ref = knownEnv('GITHUB_REF')\n return ref?.startsWith('refs/heads/') ? ref.slice('refs/heads/'.length) : undefined\n}\n\nfunction repoBranch(): string {\n const ci = ciBranchName()\n if (ci) return ci\n const branch = git(['branch', '--show-current'], '')\n if (branch) return branch\n const name = git(['name-rev', '--name-only', '--exclude=tags/*', 'HEAD'], '')\n if (name && name !== 'undefined') return name\n return `detached:${git(['rev-parse', '--short', 'HEAD'], 'unknown')}`\n}\n\n/** Repo identity from the exporting process's cwd. `'unknown'` values are flagged by `validateProductBenchmarkRun`. */\nexport function productBenchmarkRepoIdentity(): ProductBenchmarkManifest['repo'] {\n return {\n url: git(['config', '--get', 'remote.origin.url'], 'unknown'),\n commit: git(['rev-parse', 'HEAD'], 'unknown'),\n branch: repoBranch(),\n }\n}\n\n/** The declared range from the cwd package.json when present, else the\n * INSTALLED version read from node_modules (covers transitive installs —\n * a product that gets sandbox via agent-runtime still records real\n * provenance), else the `'unknown'` sentinel the validator refuses. */\nfunction packageVersion(name: string): string {\n const pkg = JSON.parse(readFileSync(resolve('package.json'), 'utf8')) as {\n name?: string\n version?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n if (pkg.name === name && pkg.version) return pkg.version\n const declared = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]\n if (declared) return declared\n const installed = resolve('node_modules', name, 'package.json')\n if (existsSync(installed)) {\n const installedPkg = JSON.parse(readFileSync(installed, 'utf8')) as { version?: string }\n if (installedPkg.version) return installedPkg.version\n }\n return 'unknown'\n}\n\n// ── Run record ingestion ─────────────────────────────────────────────\n\nfunction readRunRecords(path: string): RunRecord[] {\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n return lines.map((line, index) => {\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch (err) {\n throw new ValidationError(\n `${path}:${index + 1}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n )\n }\n return expectRunRecordShape(parsed, `${path}:${index + 1}`)\n })\n}\n\nfunction expectRunRecordShape(value: unknown, path: string): RunRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new ValidationError(`${path}: run record must be an object`)\n }\n const obj = value as Record<string, unknown>\n for (const key of ['runId', 'model'] as const) {\n if (typeof obj[key] !== 'string' || obj[key].length === 0) {\n throw new ValidationError(`${path}: run record ${key} must be a non-empty string`)\n }\n }\n for (const key of ['costUsd', 'wallMs'] as const) {\n if (typeof obj[key] !== 'number' || !Number.isFinite(obj[key])) {\n throw new ValidationError(`${path}: run record ${key} must be a finite number`)\n }\n }\n const tokenUsage = obj.tokenUsage as Record<string, unknown> | undefined\n if (\n !tokenUsage ||\n typeof tokenUsage.input !== 'number' ||\n typeof tokenUsage.output !== 'number'\n ) {\n throw new ValidationError(`${path}: run record tokenUsage.input/output must be numbers`)\n }\n const outcome = obj.outcome as Record<string, unknown> | undefined\n if (!outcome?.raw || typeof outcome.raw !== 'object') {\n throw new ValidationError(`${path}: run record outcome.raw must be an object`)\n }\n return value as RunRecord\n}\n\n// ── Row mapping ──────────────────────────────────────────────────────\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value))\n}\n\nfunction splitOf(record: RunRecord, opts: ResolvedExportOptions): ProductBenchmarkSplit {\n const custom = opts.classifySplit?.(record)\n if (custom) return custom\n if ((record.outcome.raw as Record<string, number>).safety === 1) return 'safety'\n if (record.splitTag === 'holdout') return 'holdout'\n if (record.splitTag === 'dev') return 'dev'\n return 'practice'\n}\n\n/** Ungated: a published benchmark record is audit evidence, so the score must\n * stay the measured one. KNOWN HOLE: a realness-gated run still publishes with\n * `pass: true`. The fix mirrors `RolloutLine` — carry the gate as a field on\n * `ProductBenchmarkRecord` and force `pass: false` — which is a schema change,\n * not a call swap, and is tracked separately from this correctness fix. */\nfunction scoreOf(record: RunRecord): number {\n const score = runTaskScore(record)\n if (score !== undefined) return clamp01(score)\n if (\n (record.outcome.judgeScores?.failedJudges?.length ?? 0) > 0 ||\n (record.outcome.raw.judge_error_count ?? 0) > 0\n ) {\n throw new ValidationError(\n `Run ${record.runId} has incomplete judge evidence; product benchmark rows require a complete task score`,\n )\n }\n throw new ValidationError(\n `Run ${record.runId} has no task score; product benchmark rows require an explicit score`,\n )\n}\n\nfunction rawPassOf(record: RunRecord): boolean | null {\n const rawPass = (record.outcome.raw as Record<string, unknown>).pass\n if (typeof rawPass === 'boolean') return rawPass\n if (typeof rawPass === 'number' && Number.isFinite(rawPass)) return rawPass >= 1\n return null\n}\n\nfunction passOf(record: RunRecord, score: number, threshold: number): boolean {\n const rawPass = rawPassOf(record)\n const hasTaskFailure = record.failureClass !== undefined && record.failureClass !== 'success'\n if (rawPass !== null) return rawPass && !hasTaskFailure\n return score >= threshold && !hasTaskFailure\n}\n\nfunction failureOf(\n record: RunRecord,\n score: number,\n threshold: number,\n): Pick<ProductBenchmarkRecord['outcome'], 'failureClass' | 'failureDetail'> {\n if (record.failureClass !== undefined && record.failureClass !== 'success') {\n return {\n failureClass: record.failureClass,\n failureDetail: record.failureMode ?? null,\n }\n }\n const belowThreshold = `quality-below-threshold: ${Math.round(score * 100)}% < ${Math.round(threshold * 100)}%`\n if (rawPassOf(record) === false) {\n return {\n failureClass: 'unknown',\n failureDetail: score < threshold ? belowThreshold : 'product-pass-failed',\n }\n }\n if (passOf(record, score, threshold)) {\n return { failureClass: null, failureDetail: null }\n }\n return { failureClass: 'unknown', failureDetail: belowThreshold }\n}\n\nfunction numericDimensions(record: RunRecord): Record<string, number> {\n const dimensions: Record<string, number> = {}\n for (const [key, value] of Object.entries(record.outcome.raw ?? {})) {\n if (typeof value === 'number' && Number.isFinite(value)) dimensions[key] = value\n }\n if (Object.keys(dimensions).length === 0) dimensions.score = scoreOf(record)\n return dimensions\n}\n\nfunction armIdOf(record: RunRecord): string {\n if (record.candidateId) return record.candidateId\n const variant = record.agentProfile?.dimensions?.variant\n if (typeof variant === 'string' && variant.length > 0) return variant\n const variantId = record.agentProfile?.dimensions?.variantId\n if (typeof variantId === 'string' && variantId.length > 0) return variantId\n return 'production-profile'\n}\n\nfunction backendOf(record: RunRecord): string {\n const backend = record.agentProfile?.dimensions?.backend\n return typeof backend === 'string' && backend.length > 0 ? backend : 'unknown'\n}\n\nfunction modelProvider(record: RunRecord): string {\n const backend = backendOf(record)\n if (backend === 'cli-bridge') return 'cli-bridge'\n if (backend === 'sandbox') return 'router'\n if (record.model.startsWith('router/')) return 'router'\n return backend === 'unknown' ? 'router' : backend\n}\n\nfunction runtimeResolution(record: RunRecord, opts: ResolvedExportOptions): RuntimeResolution {\n const reasoningEffort = record.agentProfile?.dimensions?.reasoningLevel\n return {\n model: record.agentProfile?.model ?? record.model,\n harness: record.agentProfile?.harness?.id ?? `${opts.projectId}-canonical-eval`,\n backend: backendOf(record),\n ...(typeof reasoningEffort === 'string' && reasoningEffort.length > 0\n ? { reasoningEffort }\n : {}),\n }\n}\n\nfunction sourceProfileHash(record: RunRecord): string {\n return (\n record.agentProfile?.sourceProfile?.hash ??\n record.agentProfile?.cellId ??\n sha256(\n JSON.stringify({\n candidateId: record.candidateId,\n promptHash: record.promptHash,\n configHash: record.configHash,\n }),\n )\n )\n}\n\nfunction materializedProfileHash(record: RunRecord, runtime: RuntimeResolution): string {\n return sha256(\n JSON.stringify({ sourceProfileHash: sourceProfileHash(record), model: runtime.model }),\n )\n}\n\nfunction profileIdOf(\n record: RunRecord,\n armId: string,\n runtime: RuntimeResolution,\n opts: ResolvedExportOptions,\n): string {\n const base = record.agentProfile?.profileId ?? opts.fallbackProfileId ?? armId\n const withArm = base.endsWith(`:${armId}`) ? base : `${base}:${armId}`\n return `${withArm}:${runtime.model}`\n}\n\nfunction toolCallsOf(record: RunRecord, runDir: string, opts: ResolvedExportOptions): number {\n const raw = record.outcome.raw as Record<string, unknown>\n const primary = Number(raw.tool_call_count ?? raw.tool_calls ?? raw.toolCalls ?? 0)\n if (Number.isFinite(primary) && primary > 0) return primary\n const fallback = opts.toolCallFallback?.(record, runDir)\n if (fallback !== undefined && Number.isFinite(fallback) && fallback > 0) return fallback\n return Number.isFinite(primary) ? primary : 0\n}\n\n// ── Artifact layout ──────────────────────────────────────────────────\n\nconst TRACE_CANDIDATES = ['traces.jsonl', 'traces', 'trace', 'trace-store'] as const\nconst RAW_CANDIDATES = ['raws.jsonl', 'raw-events'] as const\nconst SCORE_CANDIDATES = ['scores.json', 'manifest.json'] as const\n\nfunction firstExisting(runDir: string, candidates: readonly string[]): string {\n return candidates.find((candidate) => existsSync(join(runDir, candidate))) ?? candidates[0]!\n}\n\nfunction relativeArtifacts(runDir: string): ProductBenchmarkRecord['artifacts'] {\n return {\n records: 'records.jsonl',\n traces: firstExisting(runDir, TRACE_CANDIDATES),\n raws: firstExisting(runDir, RAW_CANDIDATES),\n scores: firstExisting(runDir, SCORE_CANDIDATES),\n workspace: existsSync(join(runDir, 'workspace')) ? 'workspace' : '.',\n }\n}\n\nfunction absoluteArtifacts(runDir: string): ProductBenchmarkRecord['artifacts'] {\n const rel = relativeArtifacts(runDir)\n return {\n records: resolve(runDir, rel.records),\n traces: resolve(runDir, rel.traces),\n raws: resolve(runDir, rel.raws),\n scores: resolve(runDir, rel.scores),\n workspace: resolve(runDir, rel.workspace),\n }\n}\n\nfunction materializeRunArtifacts(\n runDir: string,\n outDir: string,\n index: number,\n): ProductBenchmarkRecord['artifacts'] {\n if (resolve(runDir) === resolve(outDir)) return relativeArtifacts(runDir)\n const rel = relative(runDir, outDir)\n if (rel && !rel.startsWith('..') && !isAbsolute(rel)) {\n throw new ValidationError(`outDir must not be nested inside runDir: ${outDir}`)\n }\n const id = `${String(index + 1).padStart(2, '0')}-${safePathPart(basename(runDir))}-${sha256(runDir).slice(7, 19)}`\n const destRel = join('source-runs', id)\n const destAbs = join(outDir, destRel)\n mkdirSync(dirname(destAbs), { recursive: true })\n cpSync(runDir, destAbs, { recursive: true, force: true })\n const source = relativeArtifacts(runDir)\n return {\n records: join(destRel, source.records),\n traces: join(destRel, source.traces),\n raws: join(destRel, source.raws),\n scores: join(destRel, source.scores),\n workspace: source.workspace === '.' ? destRel : join(destRel, source.workspace),\n }\n}\n\nfunction existsArtifact(artifactRoot: string, value: string): boolean {\n return existsSync(resolve(artifactRoot, value))\n}\n\n// ── Record + manifest construction ───────────────────────────────────\n\n/** Map one RunRecord row to a validated product benchmark record. */\nexport function runRecordToProductBenchmarkRecord(\n record: RunRecord,\n runDir: string,\n artifactRoot: string,\n artifacts: ProductBenchmarkRecord['artifacts'],\n options: ProductBenchmarkExportOptions | ProductBenchmarkSingleRunExportOptions,\n): ProductBenchmarkRecord {\n const opts = resolveOptions(options)\n const runtime = runtimeResolution(record, opts)\n const score = scoreOf(record)\n const failure = failureOf(record, score, opts.passThreshold)\n const armId = armIdOf(record)\n const inputTokens = record.tokenUsage.input\n const outputTokens = record.tokenUsage.output\n const toolCallCount = toolCallsOf(record, runDir, opts)\n const dimensions = numericDimensions(record)\n if (record.costUsd === null) {\n throw new ValidationError(\n `run '${record.runId}' has no USD cost; product benchmark exports require priced runs`,\n )\n }\n const costUsd = record.costUsd\n if (!('tool_calls' in dimensions)) dimensions.tool_calls = toolCallCount\n const product: ProductBenchmarkRecord = {\n schemaVersion: 1,\n projectId: opts.projectId,\n benchmarkId: opts.benchmarkId,\n runId: record.runId,\n scenarioId: record.scenarioId,\n split: splitOf(record, opts),\n armId,\n rep: Number(record.seed ?? 0) + 1,\n agentProfile: {\n id: profileIdOf(record, armId, runtime, opts),\n hash: materializedProfileHash(record, runtime),\n path: opts.agentProfilePath,\n declared: runtime,\n resolved: runtime,\n },\n model: { provider: modelProvider(record), id: record.model },\n backend: { kind: backendOf(record), version: opts.backendVersion },\n outcome: {\n pass: passOf(record, score, opts.passThreshold),\n score,\n dimensions,\n ...failure,\n },\n usage: {\n inputTokens,\n outputTokens,\n costUsd,\n // Rounded: the bundle contract requires integer milliseconds.\n wallMs: Math.round(record.wallMs),\n toolCalls: toolCallCount,\n },\n integrity: {\n realBackend: inputTokens + outputTokens > 0,\n rawCapture: existsArtifact(artifactRoot, artifacts.raws),\n traceCapture: existsArtifact(artifactRoot, artifacts.traces),\n noStubRows: inputTokens + outputTokens > 0,\n priced: costUsd > 0,\n profileMaterialized: Boolean(record.agentProfile?.cellId),\n },\n artifacts,\n }\n return validateProductBenchmarkRecord(product)\n}\n\n/** One record per arm id, failing loud when records sharing an arm id\n * disagree on any attribute the manifest arm carries (profile, model,\n * backend, harness, reasoning effort) — an id-only dedup would silently\n * keep one policy and misrepresent the rest. */\nfunction uniqueArmRecords(records: readonly ProductBenchmarkRecord[]): ProductBenchmarkRecord[] {\n const byArm = new Map<string, ProductBenchmarkRecord>()\n for (const record of records) {\n const prior = byArm.get(record.armId)\n if (!prior) {\n byArm.set(record.armId, record)\n continue\n }\n const fields = [\n ['profileId', prior.agentProfile.id, record.agentProfile.id],\n ['model', prior.agentProfile.resolved.model, record.agentProfile.resolved.model],\n ['backend', prior.agentProfile.resolved.backend, record.agentProfile.resolved.backend],\n ['harness', prior.agentProfile.resolved.harness, record.agentProfile.resolved.harness],\n [\n 'reasoningEffort',\n prior.agentProfile.resolved.reasoningEffort,\n record.agentProfile.resolved.reasoningEffort,\n ],\n ] as const\n for (const [name, a, b] of fields) {\n if (a !== b) {\n throw new ValidationError(\n `records for arm '${record.armId}' disagree on ${name} (${String(a)} vs ${String(b)}) — one arm id must map to one policy`,\n )\n }\n }\n }\n return [...byArm.values()]\n}\n\n/** One record per scenario id, failing loud on a divergent split — the\n * manifest scenario carries one split, so two records disagreeing would be\n * silently misfiled. */\nfunction uniqueScenarioRecords(\n records: readonly ProductBenchmarkRecord[],\n): ProductBenchmarkRecord[] {\n const byScenario = new Map<string, ProductBenchmarkRecord>()\n for (const record of records) {\n const prior = byScenario.get(record.scenarioId)\n if (!prior) {\n byScenario.set(record.scenarioId, record)\n continue\n }\n if (prior.split !== record.split) {\n throw new ValidationError(\n `records for scenario '${record.scenarioId}' disagree on split (${prior.split} vs ${record.split})`,\n )\n }\n }\n return [...byScenario.values()]\n}\n\n/** Derive the bundle manifest from already-normalized records. */\nexport function buildProductBenchmarkManifest(\n records: readonly ProductBenchmarkRecord[],\n options: Pick<\n ProductBenchmarkExportOptions,\n 'outDir' | 'projectId' | 'benchmarkId' | 'scenarioTagPrefix' | 'mutableSurfaces' | 'substrate'\n >,\n): ProductBenchmarkManifest {\n if (records.length === 0) {\n throw new ValidationError('cannot build a product benchmark manifest from zero records')\n }\n const scenarioTagPrefix = options.scenarioTagPrefix ?? defaultScenarioTagPrefix(options.projectId)\n const mutableSurfaces = options.mutableSurfaces ?? productBenchmarkMutableSurfaces\n const byProfile = new Map<string, ProductBenchmarkManifest['profiles'][number]>()\n for (const record of records) {\n byProfile.set(record.agentProfile.id, {\n id: record.agentProfile.id,\n profileHash: record.agentProfile.hash,\n agentProfilePath: record.agentProfile.path,\n })\n }\n const manifest: ProductBenchmarkManifest = {\n schemaVersion: 1,\n projectId: options.projectId,\n benchmarkId: options.benchmarkId,\n repo: productBenchmarkRepoIdentity(),\n substrate: {\n agentEval: packageVersion('@tangle-network/agent-eval'),\n agentRuntime: packageVersion('@tangle-network/agent-runtime'),\n agentInterface: packageVersion('@tangle-network/agent-interface'),\n sandbox: packageVersion('@tangle-network/sandbox'),\n ...options.substrate,\n },\n profiles: [...byProfile.values()],\n arms: uniqueArmRecords(records).map((record) => ({\n id: record.armId,\n profileId: record.agentProfile.id,\n mutableSurfaces: [...mutableSurfaces],\n policyAxes: {\n carrier: record.armId.includes('policy') ? 'resource-file' : 'profile',\n model: record.agentProfile.resolved.model,\n backend: record.agentProfile.resolved.backend,\n harness: record.agentProfile.resolved.harness,\n ...(record.agentProfile.resolved.reasoningEffort !== undefined\n ? { reasoningEffort: record.agentProfile.resolved.reasoningEffort }\n : {}),\n },\n })),\n scenarios: uniqueScenarioRecords(records).map((record) => ({\n id: record.scenarioId,\n split: record.split,\n tags: [scenarioTagPrefix, options.benchmarkId, record.split],\n sourceAllowedForSynthesis: false,\n })),\n budgets: {\n maxUsd: records.reduce((sum, record) => sum + record.usage.costUsd, 0),\n maxCells: records.length,\n maxWallMs: records.reduce((sum, record) => sum + record.usage.wallMs, 0),\n },\n expectedArtifactDir: resolve(options.outDir),\n }\n return validateProductBenchmarkManifest(manifest)\n}\n\n// ── Entry points ─────────────────────────────────────────────────────\n\n/** Single-run convenience wrapper over `exportProductBenchmarkRuns`. */\nexport function exportProductBenchmark(\n options: ProductBenchmarkSingleRunExportOptions,\n): ProductBenchmarkExportResult {\n const { runDir, ...rest } = options\n return exportProductBenchmarkRuns({ ...rest, runDirs: [runDir] })\n}\n\n/**\n * Export one or more product eval run dirs into a validated product\n * benchmark bundle at `outDir`. Both the manifest and every record are\n * run through the contract validators before anything is written.\n */\nexport function exportProductBenchmarkRuns(\n options: ProductBenchmarkExportOptions,\n): ProductBenchmarkExportResult {\n const opts = resolveOptions(options)\n const outDir = resolve(options.outDir)\n const runDirs = options.runDirs.map((runDir) => resolve(runDir))\n if (runDirs.length === 0) throw new ValidationError('export requires at least one run directory')\n const materialize = options.materializeSourceRuns !== false\n const rows = runDirs.flatMap((runDir) => {\n const sourceRecordsPath = join(runDir, 'records.jsonl')\n if (!existsSync(sourceRecordsPath)) throw new ValidationError(`missing ${sourceRecordsPath}`)\n const records = readRunRecords(sourceRecordsPath)\n if (records.length === 0) throw new ValidationError(`${sourceRecordsPath} is empty`)\n return records.map((record) => ({ record, runDir }))\n })\n mkdirSync(outDir, { recursive: true })\n const artifactsByRunDir = new Map<string, ProductBenchmarkRecord['artifacts']>()\n for (const [index, runDir] of runDirs.entries()) {\n artifactsByRunDir.set(\n runDir,\n materialize ? materializeRunArtifacts(runDir, outDir, index) : absoluteArtifacts(runDir),\n )\n }\n const artifactRoot = materialize ? outDir : '/'\n const normalized = rows.map(({ record, runDir }) =>\n runRecordToProductBenchmarkRecord(\n record,\n runDir,\n artifactRoot,\n artifactsByRunDir.get(runDir)!,\n { ...options, runDirs, backendVersion: opts.backendVersion },\n ),\n )\n const manifest = buildProductBenchmarkManifest(normalized, {\n outDir,\n projectId: opts.projectId,\n benchmarkId: opts.benchmarkId,\n scenarioTagPrefix: opts.scenarioTagPrefix,\n mutableSurfaces: opts.mutableSurfaces,\n ...(options.substrate !== undefined ? { substrate: options.substrate } : {}),\n })\n const manifestPath = join(outDir, 'product-benchmark-manifest.json')\n const recordsPath = join(outDir, 'product-benchmark-records.jsonl')\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n writeFileSync(recordsPath, `${normalized.map((record) => JSON.stringify(record)).join('\\n')}\\n`)\n return { manifestPath, recordsPath, records: normalized.length }\n}\n\nfunction defaultScenarioTagPrefix(projectId: string): string {\n return projectId.replace(/-agent$/, '') || projectId\n}\n\nfunction resolveOptions(\n options: ProductBenchmarkExportOptions | ProductBenchmarkSingleRunExportOptions,\n): ResolvedExportOptions {\n return {\n projectId: options.projectId,\n benchmarkId: options.benchmarkId,\n agentProfilePath: options.agentProfilePath,\n passThreshold: options.passThreshold ?? 0.7,\n scenarioTagPrefix: options.scenarioTagPrefix ?? defaultScenarioTagPrefix(options.projectId),\n ...(options.fallbackProfileId !== undefined\n ? { fallbackProfileId: options.fallbackProfileId }\n : {}),\n mutableSurfaces: options.mutableSurfaces ?? productBenchmarkMutableSurfaces,\n ...(options.classifySplit !== undefined ? { classifySplit: options.classifySplit } : {}),\n ...(options.toolCallFallback !== undefined\n ? { toolCallFallback: options.toolCallFallback }\n : {}),\n backendVersion: options.backendVersion ?? packageVersion('@tangle-network/sandbox'),\n }\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { ValidationError } from '../errors'\nimport { FAILURE_CLASSES, type FailureClass } from '../trace/schema'\n\nexport const productBenchmarkSplits = ['practice', 'dev', 'holdout', 'safety', 'sentinel'] as const\n\nexport type ProductBenchmarkSplit = (typeof productBenchmarkSplits)[number]\n\nexport interface ProductBenchmarkRepoRef {\n readonly url: string\n readonly commit: string\n readonly branch: string\n}\n\nexport interface ProductBenchmarkSubstrateVersions {\n readonly agentEval: string\n readonly agentRuntime: string\n readonly agentInterface: string\n readonly sandbox: string\n readonly agentBench?: string\n}\n\nexport interface ProductBenchmarkProfileRef {\n readonly id: string\n readonly profileHash: string\n readonly agentProfilePath: string\n}\n\nexport interface ProductBenchmarkArm {\n readonly id: string\n readonly profileId: string\n readonly mutableSurfaces: readonly string[]\n readonly policyAxes: Record<string, unknown>\n}\n\nexport interface ProductBenchmarkScenario {\n readonly id: string\n readonly split: ProductBenchmarkSplit\n readonly tags: readonly string[]\n readonly sourceAllowedForSynthesis: boolean\n}\n\nexport interface ProductBenchmarkBudgets {\n readonly maxUsd: number\n readonly maxCells: number\n readonly maxWallMs: number\n}\n\nexport interface ProductBenchmarkManifest {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly repo: ProductBenchmarkRepoRef\n readonly substrate: ProductBenchmarkSubstrateVersions\n readonly profiles: readonly ProductBenchmarkProfileRef[]\n readonly arms: readonly ProductBenchmarkArm[]\n readonly scenarios: readonly ProductBenchmarkScenario[]\n readonly budgets: ProductBenchmarkBudgets\n readonly expectedArtifactDir: string\n}\n\nexport interface AgentProfileRuntimeReceipt {\n readonly model: string\n readonly harness: string\n readonly backend: string\n readonly reasoningEffort?: string\n}\n\nexport type RuntimeResolution = AgentProfileRuntimeReceipt\n\nexport interface ProductBenchmarkRecord {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly runId: string\n readonly scenarioId: string\n readonly split: ProductBenchmarkSplit\n readonly armId: string\n readonly rep: number\n readonly agentProfile: {\n readonly id: string\n readonly hash: string\n readonly path: string\n readonly declared: RuntimeResolution\n readonly resolved: RuntimeResolution\n }\n readonly model: {\n readonly provider: string\n readonly id: string\n }\n readonly backend: {\n readonly kind: string\n readonly version: string\n }\n readonly outcome: {\n readonly pass: boolean\n readonly score: number\n readonly dimensions: Record<string, number>\n readonly failureClass: Exclude<FailureClass, 'success'> | null\n readonly failureDetail: string | null\n }\n readonly usage: {\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly toolCalls: number\n }\n readonly integrity: {\n readonly realBackend: boolean\n readonly rawCapture: boolean\n readonly traceCapture: boolean\n readonly noStubRows: boolean\n readonly priced: boolean\n readonly profileMaterialized: boolean\n }\n readonly artifacts: {\n readonly records: string\n readonly traces: string\n readonly raws: string\n readonly scores: string\n readonly workspace: string\n }\n}\n\nexport interface ProductBenchmarkRunInput {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly artifactRoot?: string\n readonly checkArtifacts?: boolean\n}\n\nexport interface ProductBenchmarkValidationReport {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly records: number\n /** Manifest repo fields that are empty or the `'unknown'` export sentinel. */\n readonly repoFailures: readonly string[]\n /** Manifest substrate versions that are empty or the `'unknown'` export\n * sentinel — a bundle without substrate identity is not reproducible. */\n readonly substrateFailures: readonly string[]\n readonly projects: readonly string[]\n readonly benchmarks: readonly string[]\n readonly arms: readonly string[]\n readonly scenarios: readonly string[]\n readonly passed: number\n readonly failed: number\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly integrityFailures: readonly string[]\n readonly missingArtifacts: readonly string[]\n}\n\nexport interface ProductBenchmarkArtifactPaths {\n readonly manifestPath: string\n readonly recordsPath: string\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction fail(path: string, message: string): never {\n throw new ValidationError(`${path}: ${message}`)\n}\n\nfunction wrapValidationError(path: string, err: unknown): never {\n if (err instanceof ValidationError) {\n throw new ValidationError(`${path}: ${err.message}`, { cause: err })\n }\n throw new ValidationError(`${path}: ${err instanceof Error ? err.message : String(err)}`, {\n cause: err,\n })\n}\n\nfunction expectObject(value: unknown, path: string): Record<string, unknown> {\n if (!isObject(value)) fail(path, 'must be an object')\n return value\n}\n\nfunction expectString(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.trim().length === 0)\n fail(path, 'must be a non-empty string')\n return value\n}\n\nfunction expectFailureClass(value: unknown, path: string): Exclude<FailureClass, 'success'> {\n const parsed = expectString(value, path)\n if (parsed === 'success' || !FAILURE_CLASSES.includes(parsed as FailureClass)) {\n fail(path, `expected a non-success FailureClass, received ${JSON.stringify(parsed)}`)\n }\n return parsed as Exclude<FailureClass, 'success'>\n}\n\nfunction expectBoolean(value: unknown, path: string): boolean {\n if (typeof value !== 'boolean') fail(path, 'must be a boolean')\n return value\n}\n\nfunction expectNumber(\n value: unknown,\n path: string,\n opts: { readonly min?: number; readonly max?: number; readonly integer?: boolean } = {},\n): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) fail(path, 'must be a finite number')\n if (opts.integer && !Number.isInteger(value)) fail(path, 'must be an integer')\n if (opts.min !== undefined && value < opts.min) fail(path, `must be >= ${opts.min}`)\n if (opts.max !== undefined && value > opts.max) fail(path, `must be <= ${opts.max}`)\n return value\n}\n\nfunction expectStringArray(value: unknown, path: string): string[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectString(entry, `${path}[${index}]`))\n}\n\nfunction expectObjectArray(value: unknown, path: string): Record<string, unknown>[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectObject(entry, `${path}[${index}]`))\n}\n\nfunction expectSplit(value: unknown, path: string): ProductBenchmarkSplit {\n const split = expectString(value, path)\n if (!productBenchmarkSplits.includes(split as ProductBenchmarkSplit)) {\n fail(path, `must be one of ${productBenchmarkSplits.join(', ')}`)\n }\n return split as ProductBenchmarkSplit\n}\n\nfunction optionalString(value: unknown, path: string): string | undefined {\n if (value === undefined) return undefined\n return expectString(value, path)\n}\n\nfunction expectDimensions(value: unknown, path: string): Record<string, number> {\n const obj = expectObject(value, path)\n const out: Record<string, number> = {}\n for (const [key, raw] of Object.entries(obj)) out[key] = expectNumber(raw, `${path}.${key}`)\n return out\n}\n\nfunction expectRuntimeResolution(value: unknown, path: string): RuntimeResolution {\n const obj = expectObject(value, path)\n return {\n model: expectString(obj.model, `${path}.model`),\n harness: expectString(obj.harness, `${path}.harness`),\n backend: expectString(obj.backend, `${path}.backend`),\n ...(obj.reasoningEffort !== undefined\n ? { reasoningEffort: optionalString(obj.reasoningEffort, `${path}.reasoningEffort`) }\n : {}),\n }\n}\n\nexport function validateProductBenchmarkManifest(value: unknown): ProductBenchmarkManifest {\n const obj = expectObject(value, 'manifest')\n if (obj.schemaVersion !== 1) fail('manifest.schemaVersion', 'must be 1')\n const repo = expectObject(obj.repo, 'manifest.repo')\n const substrate = expectObject(obj.substrate, 'manifest.substrate')\n const profiles = expectObjectArray(obj.profiles, 'manifest.profiles').map((profile, index) => ({\n id: expectString(profile.id, `manifest.profiles[${index}].id`),\n profileHash: expectString(profile.profileHash, `manifest.profiles[${index}].profileHash`),\n agentProfilePath: expectString(\n profile.agentProfilePath,\n `manifest.profiles[${index}].agentProfilePath`,\n ),\n }))\n const arms = expectObjectArray(obj.arms, 'manifest.arms').map((arm, index) => ({\n id: expectString(arm.id, `manifest.arms[${index}].id`),\n profileId: expectString(arm.profileId, `manifest.arms[${index}].profileId`),\n mutableSurfaces: expectStringArray(\n arm.mutableSurfaces,\n `manifest.arms[${index}].mutableSurfaces`,\n ),\n policyAxes: expectObject(arm.policyAxes, `manifest.arms[${index}].policyAxes`),\n }))\n const scenarios = expectObjectArray(obj.scenarios, 'manifest.scenarios').map(\n (scenario, index) => ({\n id: expectString(scenario.id, `manifest.scenarios[${index}].id`),\n split: expectSplit(scenario.split, `manifest.scenarios[${index}].split`),\n tags: expectStringArray(scenario.tags, `manifest.scenarios[${index}].tags`),\n sourceAllowedForSynthesis: expectBoolean(\n scenario.sourceAllowedForSynthesis,\n `manifest.scenarios[${index}].sourceAllowedForSynthesis`,\n ),\n }),\n )\n const budgets = expectObject(obj.budgets, 'manifest.budgets')\n if (profiles.length === 0) fail('manifest.profiles', 'must contain at least one profile')\n if (arms.length === 0) fail('manifest.arms', 'must contain at least one arm')\n if (scenarios.length === 0) fail('manifest.scenarios', 'must contain at least one scenario')\n assertUnique(\n profiles.map((profile) => profile.id),\n 'manifest.profiles.id',\n )\n assertUnique(\n arms.map((arm) => arm.id),\n 'manifest.arms.id',\n )\n assertUnique(\n scenarios.map((scenario) => scenario.id),\n 'manifest.scenarios.id',\n )\n const profileIds = new Set(profiles.map((profile) => profile.id))\n for (const arm of arms) {\n if (!profileIds.has(arm.profileId))\n fail(`manifest.arms.${arm.id}.profileId`, `unknown profile ${arm.profileId}`)\n }\n return {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'manifest.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'manifest.benchmarkId'),\n repo: {\n url: expectString(repo.url, 'manifest.repo.url'),\n commit: expectString(repo.commit, 'manifest.repo.commit'),\n branch: expectString(repo.branch, 'manifest.repo.branch'),\n },\n substrate: {\n agentEval: expectString(substrate.agentEval, 'manifest.substrate.agentEval'),\n agentRuntime: expectString(substrate.agentRuntime, 'manifest.substrate.agentRuntime'),\n agentInterface: expectString(substrate.agentInterface, 'manifest.substrate.agentInterface'),\n sandbox: expectString(substrate.sandbox, 'manifest.substrate.sandbox'),\n ...(substrate.agentBench !== undefined\n ? { agentBench: expectString(substrate.agentBench, 'manifest.substrate.agentBench') }\n : {}),\n },\n profiles,\n arms,\n scenarios,\n budgets: {\n maxUsd: expectNumber(budgets.maxUsd, 'manifest.budgets.maxUsd', { min: 0 }),\n maxCells: expectNumber(budgets.maxCells, 'manifest.budgets.maxCells', {\n min: 0,\n integer: true,\n }),\n maxWallMs: expectNumber(budgets.maxWallMs, 'manifest.budgets.maxWallMs', {\n min: 0,\n integer: true,\n }),\n },\n expectedArtifactDir: expectString(obj.expectedArtifactDir, 'manifest.expectedArtifactDir'),\n }\n}\n\nexport function validateProductBenchmarkRecord(value: unknown): ProductBenchmarkRecord {\n const obj = expectObject(value, 'record')\n if (obj.schemaVersion !== 1) fail('record.schemaVersion', 'must be 1')\n const agentProfile = expectObject(obj.agentProfile, 'record.agentProfile')\n const model = expectObject(obj.model, 'record.model')\n const backend = expectObject(obj.backend, 'record.backend')\n const outcome = expectObject(obj.outcome, 'record.outcome')\n const usage = expectObject(obj.usage, 'record.usage')\n const integrity = expectObject(obj.integrity, 'record.integrity')\n const artifacts = expectObject(obj.artifacts, 'record.artifacts')\n const outcomePass = expectBoolean(outcome.pass, 'record.outcome.pass')\n const failureClass =\n outcome.failureClass === null\n ? null\n : expectFailureClass(outcome.failureClass, 'record.outcome.failureClass')\n const failureDetail =\n outcome.failureDetail === null\n ? null\n : expectString(outcome.failureDetail, 'record.outcome.failureDetail')\n if (outcomePass && (failureClass !== null || failureDetail !== null)) {\n fail('record.outcome', 'a passing row cannot carry failure evidence')\n }\n if (!outcomePass && failureClass === null) {\n fail('record.outcome.failureClass', 'a failed row requires a failure class')\n }\n if (failureClass === null && failureDetail !== null) {\n fail('record.outcome.failureDetail', 'failure detail requires a failure class')\n }\n const record: ProductBenchmarkRecord = {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'record.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'record.benchmarkId'),\n runId: expectString(obj.runId, 'record.runId'),\n scenarioId: expectString(obj.scenarioId, 'record.scenarioId'),\n split: expectSplit(obj.split, 'record.split'),\n armId: expectString(obj.armId, 'record.armId'),\n rep: expectNumber(obj.rep, 'record.rep', { min: 1, integer: true }),\n agentProfile: {\n id: expectString(agentProfile.id, 'record.agentProfile.id'),\n hash: expectString(agentProfile.hash, 'record.agentProfile.hash'),\n path: expectString(agentProfile.path, 'record.agentProfile.path'),\n declared: expectRuntimeResolution(agentProfile.declared, 'record.agentProfile.declared'),\n resolved: expectRuntimeResolution(agentProfile.resolved, 'record.agentProfile.resolved'),\n },\n model: {\n provider: expectString(model.provider, 'record.model.provider'),\n id: expectString(model.id, 'record.model.id'),\n },\n backend: {\n kind: expectString(backend.kind, 'record.backend.kind'),\n version: expectString(backend.version, 'record.backend.version'),\n },\n outcome: {\n pass: outcomePass,\n score: expectNumber(outcome.score, 'record.outcome.score', { min: 0, max: 1 }),\n dimensions: expectDimensions(outcome.dimensions, 'record.outcome.dimensions'),\n failureClass,\n failureDetail,\n },\n usage: {\n inputTokens: expectNumber(usage.inputTokens, 'record.usage.inputTokens', {\n min: 0,\n integer: true,\n }),\n outputTokens: expectNumber(usage.outputTokens, 'record.usage.outputTokens', {\n min: 0,\n integer: true,\n }),\n costUsd: expectNumber(usage.costUsd, 'record.usage.costUsd', { min: 0 }),\n wallMs: expectNumber(usage.wallMs, 'record.usage.wallMs', { min: 0, integer: true }),\n toolCalls: expectNumber(usage.toolCalls, 'record.usage.toolCalls', { min: 0, integer: true }),\n },\n integrity: {\n realBackend: expectBoolean(integrity.realBackend, 'record.integrity.realBackend'),\n rawCapture: expectBoolean(integrity.rawCapture, 'record.integrity.rawCapture'),\n traceCapture: expectBoolean(integrity.traceCapture, 'record.integrity.traceCapture'),\n noStubRows: expectBoolean(integrity.noStubRows, 'record.integrity.noStubRows'),\n priced: expectBoolean(integrity.priced, 'record.integrity.priced'),\n profileMaterialized: expectBoolean(\n integrity.profileMaterialized,\n 'record.integrity.profileMaterialized',\n ),\n },\n artifacts: {\n records: expectString(artifacts.records, 'record.artifacts.records'),\n traces: expectString(artifacts.traces, 'record.artifacts.traces'),\n raws: expectString(artifacts.raws, 'record.artifacts.raws'),\n scores: expectString(artifacts.scores, 'record.artifacts.scores'),\n workspace: expectString(artifacts.workspace, 'record.artifacts.workspace'),\n },\n }\n if (record.integrity.realBackend && record.usage.inputTokens + record.usage.outputTokens === 0) {\n fail('record.usage', 'realBackend rows must carry non-zero token usage')\n }\n return record\n}\n\nexport function productBenchmarkIntegrityFailures(record: ProductBenchmarkRecord): string[] {\n const failures: string[] = []\n for (const [key, value] of Object.entries(record.integrity)) {\n if (!value) failures.push(`${record.runId}:${key}=false`)\n }\n return failures\n}\n\nexport function readProductBenchmarkRecords(path: string): ProductBenchmarkRecord[] {\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n const records: ProductBenchmarkRecord[] = []\n for (const [index, line] of lines.entries()) {\n try {\n records.push(validateProductBenchmarkRecord(JSON.parse(line)))\n } catch (err) {\n wrapValidationError(`${path}:${index + 1}`, err)\n }\n }\n return records\n}\n\nexport function readProductBenchmarkManifest(path: string): ProductBenchmarkManifest {\n try {\n return validateProductBenchmarkManifest(JSON.parse(readFileSync(path, 'utf8')))\n } catch (err) {\n wrapValidationError(path, err)\n }\n}\n\nexport function validateProductBenchmarkRun(\n input: ProductBenchmarkRunInput,\n): ProductBenchmarkValidationReport {\n const manifest = readProductBenchmarkManifest(input.manifestPath)\n const records = readProductBenchmarkRecords(input.recordsPath)\n const manifestProjectBench = `${manifest.projectId}/${manifest.benchmarkId}`\n const integrityFailures = records.flatMap(productBenchmarkIntegrityFailures)\n const missingArtifacts =\n input.checkArtifacts === false\n ? []\n : records.flatMap((record) =>\n missingArtifactsForRecord(record, input.artifactRoot ?? dirname(input.recordsPath)),\n )\n for (const [index, record] of records.entries()) {\n const recordProjectBench = `${record.projectId}/${record.benchmarkId}`\n if (recordProjectBench !== manifestProjectBench) {\n fail(\n `records[${index}]`,\n `project/benchmark ${recordProjectBench} does not match manifest ${manifestProjectBench}`,\n )\n }\n if (!manifest.arms.some((arm) => arm.id === record.armId))\n fail(`records[${index}].armId`, `unknown arm ${record.armId}`)\n if (!manifest.scenarios.some((scenario) => scenario.id === record.scenarioId)) {\n fail(`records[${index}].scenarioId`, `unknown scenario ${record.scenarioId}`)\n }\n }\n const repoFailures = (['url', 'commit', 'branch'] as const)\n .filter((key) => manifest.repo[key].trim().length === 0 || manifest.repo[key] === 'unknown')\n .map((key) => `manifest.repo.${key}`)\n const substrateFailures = (['agentEval', 'agentRuntime', 'agentInterface', 'sandbox'] as const)\n .filter(\n (key) => manifest.substrate[key].trim().length === 0 || manifest.substrate[key] === 'unknown',\n )\n .map((key) => `manifest.substrate.${key}`)\n return {\n manifestPath: input.manifestPath,\n recordsPath: input.recordsPath,\n records: records.length,\n repoFailures,\n substrateFailures,\n projects: sortedUnique(records.map((record) => record.projectId)),\n benchmarks: sortedUnique(records.map((record) => record.benchmarkId)),\n arms: sortedUnique(records.map((record) => record.armId)),\n scenarios: sortedUnique(records.map((record) => record.scenarioId)),\n passed: records.filter((record) => record.outcome.pass).length,\n failed: records.filter((record) => !record.outcome.pass).length,\n inputTokens: sum(records, (record) => record.usage.inputTokens),\n outputTokens: sum(records, (record) => record.usage.outputTokens),\n costUsd: sum(records, (record) => record.usage.costUsd),\n wallMs: sum(records, (record) => record.usage.wallMs),\n integrityFailures,\n missingArtifacts,\n }\n}\n\nfunction missingArtifactsForRecord(record: ProductBenchmarkRecord, artifactRoot: string): string[] {\n const missing: string[] = []\n for (const [key, value] of Object.entries(record.artifacts)) {\n const path = resolveArtifactPath(value, artifactRoot)\n if (!existsSync(path)) missing.push(`${record.runId}:${key}:${value}`)\n }\n return missing\n}\n\nfunction resolveArtifactPath(value: string, artifactRoot: string): string {\n return value.startsWith('/') ? value : join(artifactRoot, value)\n}\n\nfunction assertUnique(values: readonly string[], path: string): void {\n const seen = new Set<string>()\n for (const value of values) {\n if (seen.has(value)) fail(path, `duplicate ${value}`)\n seen.add(value)\n }\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort()\n}\n\nfunction sum<T>(items: readonly T[], fn: (item: T) => number): number {\n return items.reduce((total, item) => total + fn(item), 0)\n}\n\nexport function findProductBenchmarkArtifacts(\n runDir: string,\n): ProductBenchmarkArtifactPaths | null {\n const manifestPath = join(runDir, 'product-benchmark-manifest.json')\n const recordsPath = join(runDir, 'product-benchmark-records.jsonl')\n if (\n existsSync(manifestPath) &&\n statSync(manifestPath).isFile() &&\n existsSync(recordsPath) &&\n statSync(recordsPath).isFile()\n ) {\n return { manifestPath, recordsPath }\n }\n return null\n}\n\n/**\n * Fail-loud gate over a bundle directory: locates the manifest + records,\n * runs `validateProductBenchmarkRun`, and throws with every repo,\n * integrity, and artifact failure listed. Returns the report when clean.\n */\nexport function assertProductBenchmarkRun(runDir: string): ProductBenchmarkValidationReport {\n const artifacts = findProductBenchmarkArtifacts(runDir)\n if (!artifacts) {\n fail(runDir, 'missing product-benchmark-manifest.json or product-benchmark-records.jsonl')\n }\n const report = validateProductBenchmarkRun({ ...artifacts, artifactRoot: runDir })\n const failures = [\n ...report.repoFailures,\n ...report.substrateFailures,\n ...report.integrityFailures,\n ...report.missingArtifacts,\n ]\n if (failures.length > 0) {\n fail(runDir, `product benchmark validation failed:\\n${failures.join('\\n')}`)\n }\n return report\n}\n\nexport type {\n ProductBenchmarkExportOptions,\n ProductBenchmarkExportResult,\n ProductBenchmarkSingleRunExportOptions,\n} from './export'\nexport {\n buildProductBenchmarkManifest,\n exportProductBenchmark,\n exportProductBenchmarkRuns,\n productBenchmarkMutableSurfaces,\n productBenchmarkRepoIdentity,\n runRecordToProductBenchmarkRecord,\n} from './export'\n","import type { RunSplitTag } from './run-record'\n\nexport interface RuntimeTrajectoryHookEvent {\n id: string\n runId: string\n scenarioId?: string\n target: string\n phase: string\n timestamp: number\n stepIndex?: number\n parentId?: string\n payload?: unknown\n metadata?: Record<string, unknown>\n}\n\nexport interface RuntimeTrajectoryRecord {\n id?: string\n scenarioId?: string\n splitTag?: RunSplitTag\n runtimeEvents?: unknown\n [key: string]: unknown\n}\n\nexport interface RuntimeTrajectoryRunRecord {\n runId: string\n scenarioId?: string\n splitTag: RunSplitTag\n}\n\nexport interface RuntimeTrajectoryEvidenceSummary {\n recordCount: number\n recordWithRuntimeEventsCount: number\n runtimeRunCount: number\n lifecycleEventCount: number\n defaultedSplitCount: number\n}\n\nexport interface RuntimeTrajectoryEvidenceProjection {\n runs: RuntimeTrajectoryRunRecord[]\n events: RuntimeTrajectoryHookEvent[]\n summary: RuntimeTrajectoryEvidenceSummary\n diagnostics: string[]\n}\n\nexport interface ProjectRuntimeTrajectoryEvidenceOptions<\n TRecord extends RuntimeTrajectoryRecord = RuntimeTrajectoryRecord,\n> {\n records: TRecord[]\n defaultSplitTag?: RunSplitTag\n recordIdOf?: (record: TRecord, index: number) => string | undefined\n scenarioIdOf?: (record: TRecord, index: number) => string | undefined\n}\n\nconst DEFAULT_SPLIT_TAG: RunSplitTag = 'search'\n\nexport function projectRuntimeTrajectoryEvidence<TRecord extends RuntimeTrajectoryRecord>(\n options: ProjectRuntimeTrajectoryEvidenceOptions<TRecord>,\n): RuntimeTrajectoryEvidenceProjection {\n const diagnostics: string[] = []\n const runsById = new Map<string, RuntimeTrajectoryRunRecord>()\n const events: RuntimeTrajectoryHookEvent[] = []\n let recordWithRuntimeEventsCount = 0\n let defaultedSplitCount = 0\n\n for (let recordIndex = 0; recordIndex < options.records.length; recordIndex += 1) {\n const record = options.records[recordIndex]!\n const key = runtimeTrajectoryRecordKey(record, recordIndex, options.recordIdOf)\n const splitTag = record.splitTag ?? options.defaultSplitTag ?? DEFAULT_SPLIT_TAG\n if (record.splitTag === undefined) defaultedSplitCount += 1\n\n const rawEvents = record.runtimeEvents\n if (!Array.isArray(rawEvents)) {\n diagnostics.push(\n `${key}: runtimeEvents is not an array; no runtime run join can be extracted`,\n )\n continue\n }\n if (rawEvents.length === 0) {\n diagnostics.push(`${key}: no runtimeEvents; no runtime run join can be extracted`)\n continue\n }\n recordWithRuntimeEventsCount += 1\n\n for (let index = 0; index < rawEvents.length; index += 1) {\n const event = parseRuntimeTrajectoryHookEvent(rawEvents[index])\n if (!event) {\n diagnostics.push(`${key}: runtimeEvents[${index}] is not a RuntimeHookEvent`)\n continue\n }\n events.push(event)\n\n const scenarioId =\n event.scenarioId ??\n stringOrUndefined(options.scenarioIdOf?.(record, recordIndex)) ??\n stringOrUndefined(record.scenarioId)\n const prior = runsById.get(event.runId)\n if (!prior) {\n runsById.set(event.runId, { runId: event.runId, scenarioId, splitTag })\n continue\n }\n if (prior.scenarioId !== scenarioId || prior.splitTag !== splitTag) {\n diagnostics.push(`${key}: runId ${event.runId} has conflicting scenario/split metadata`)\n }\n }\n }\n\n const runs = [...runsById.values()]\n return {\n runs,\n events,\n summary: {\n recordCount: options.records.length,\n recordWithRuntimeEventsCount,\n runtimeRunCount: runs.length,\n lifecycleEventCount: events.length,\n defaultedSplitCount,\n },\n diagnostics,\n }\n}\n\nfunction parseRuntimeTrajectoryHookEvent(input: unknown): RuntimeTrajectoryHookEvent | null {\n if (!isRecord(input)) return null\n if (typeof input.id !== 'string' || input.id.length === 0) return null\n if (typeof input.runId !== 'string' || input.runId.length === 0) return null\n if (typeof input.target !== 'string' || input.target.length === 0) return null\n if (typeof input.phase !== 'string' || input.phase.length === 0) return null\n if (typeof input.timestamp !== 'number' || !Number.isFinite(input.timestamp)) return null\n\n return {\n id: input.id,\n runId: input.runId,\n scenarioId: stringOrUndefined(input.scenarioId),\n target: input.target,\n phase: input.phase,\n timestamp: input.timestamp,\n stepIndex: finiteNumberOrUndefined(input.stepIndex),\n parentId: stringOrUndefined(input.parentId),\n payload: input.payload,\n metadata: isRecord(input.metadata) ? { ...input.metadata } : undefined,\n }\n}\n\nfunction runtimeTrajectoryRecordKey<TRecord extends RuntimeTrajectoryRecord>(\n record: TRecord,\n index: number,\n recordIdOf?: (record: TRecord, index: number) => string | undefined,\n): string {\n return (\n stringOrUndefined(recordIdOf?.(record, index)) ??\n stringOrUndefined(record.id) ??\n `record[${index}]`\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction stringOrUndefined(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction finiteNumberOrUndefined(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n","import type { FeedbackLabel, ProposedSideEffect } from './feedback-trajectory'\n\nexport interface ActionExecutionPolicy {\n allowedTypes?: string[]\n blockedTypes?: string[]\n alwaysRequireApprovalTypes?: string[]\n autoApproveTypes?: string[]\n requireApprovalForExternalSideEffects?: boolean\n requireApprovalAboveCostUsd?: number\n maxActionCostUsd?: number\n remainingBudgetUsd?: number\n expectedOutcomeRequired?: boolean\n killCriteriaRequired?: boolean\n}\n\nexport interface ActionPolicyDecision {\n allowed: boolean\n blocked: boolean\n requiresApproval: boolean\n reasons: string[]\n label?: FeedbackLabel\n}\n\nexport function evaluateActionPolicy(\n action: ProposedSideEffect,\n policy: ActionExecutionPolicy = {},\n options: { createdAt?: string } = {},\n): ActionPolicyDecision {\n const reasons: string[] = []\n let blocked = false\n let requiresApproval = Boolean(action.requiresApproval)\n\n if (policy.allowedTypes?.length && !policy.allowedTypes.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is not allowed`)\n }\n if (policy.blockedTypes?.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is blocked`)\n }\n if (policy.alwaysRequireApprovalTypes?.includes(action.type)) {\n requiresApproval = true\n reasons.push(`action type \"${action.type}\" requires approval`)\n }\n if (policy.requireApprovalForExternalSideEffects && action.externalSideEffect) {\n requiresApproval = true\n reasons.push('external side effect requires approval')\n }\n if (\n policy.requireApprovalAboveCostUsd !== undefined &&\n (action.costUsd ?? 0) > policy.requireApprovalAboveCostUsd\n ) {\n requiresApproval = true\n reasons.push(\n `cost ${action.costUsd} exceeds approval threshold ${policy.requireApprovalAboveCostUsd}`,\n )\n }\n if (policy.maxActionCostUsd !== undefined && (action.costUsd ?? 0) > policy.maxActionCostUsd) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds max action cost ${policy.maxActionCostUsd}`)\n }\n if (\n policy.remainingBudgetUsd !== undefined &&\n (action.costUsd ?? 0) > policy.remainingBudgetUsd\n ) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds remaining budget ${policy.remainingBudgetUsd}`)\n }\n if (policy.expectedOutcomeRequired && !action.metadata?.expectedOutcome) {\n blocked = true\n reasons.push('expected outcome is required')\n }\n if (policy.killCriteriaRequired && !action.metadata?.killCriteria) {\n blocked = true\n reasons.push('kill criteria are required')\n }\n if (policy.autoApproveTypes?.includes(action.type) && requiresApproval) {\n reasons.push(\n `action type \"${action.type}\" is auto-approved only when no approval policy applies`,\n )\n }\n\n if (!reasons.length) reasons.push(requiresApproval ? 'approval required' : 'action allowed')\n\n const label =\n blocked || requiresApproval\n ? {\n source: 'policy' as const,\n kind: blocked ? ('policy_block' as const) : ('comment' as const),\n value: { actionType: action.type, blocked, requiresApproval },\n reason: reasons.join('; '),\n severity: blocked ? ('critical' as const) : ('warning' as const),\n createdAt: options.createdAt ?? new Date().toISOString(),\n metadata: { action, policy },\n }\n : undefined\n\n return {\n allowed: !blocked,\n blocked,\n requiresApproval: !blocked && requiresApproval,\n reasons,\n label,\n }\n}\n","/**\n * Deploy gate layer — would the agent's build actually publish?\n *\n * The product Blueprint Agent fronts promises \"go from idea to live URL.\"\n * Pre-Gen-48 the eval stopped at install/typecheck/build/serve — every\n * one of which can pass while `vite build` (or `next build`, etc) fails\n * on a production-only constraint (env-var requirement, dynamic import\n * not statically resolvable, missing public asset).\n *\n * Deploy gate runs the production build via the supplied {@link DeployRunner}\n * and asserts:\n * - command exited 0\n * - artifact dir contains an entry point (index.html for static SPAs,\n * equivalent per framework family)\n *\n * Ships with a canonical `vite` runner. Additional runners\n * (wrangler-deploy --dry-run, next-build, etc.) plug in as factories.\n */\n\nimport type { Layer, LayerResult } from './multi-layer-verifier'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport type DeployFamily = 'frontend-static' | 'nextjs' | 'remix' | 'fullstack-ts'\n\nexport interface DeployRunResult {\n ok: boolean\n /** Stdout/stderr tail surfaced as evidence. Bounded in caller. */\n output?: string\n /** Wall-clock duration of the build command. */\n durationMs?: number\n /** Path to artifact directory the runner expects (dist/, .next/, build/, etc). */\n artifactDir?: string\n /** True iff artifactDir contains the family's expected entry point. */\n artifactValid?: boolean\n}\n\nexport interface DeployRunner {\n /** Run the production build. The runner owns command + cwd. */\n run(): Promise<DeployRunResult>\n}\n\nexport interface DeployGateLayerInput {\n /** Build the runner per call. */\n runner: () => DeployRunner | Promise<DeployRunner>\n /** Family hint — for logging, surfaced in diagnostics. */\n family?: DeployFamily\n /** Layer name. Default `deploy`. */\n name?: string\n /** Layer dependencies — default `['build']`. */\n dependsOn?: string[]\n /** Weight in blendedScore. Default 1. */\n weight?: number\n /** Cap (ms). Default 120s — prod builds are slower than dev. */\n capMs?: number\n /** When true, treat artifactValid=false as a fail (default true). */\n requireArtifact?: boolean\n}\n\n// ─── Layer factory ──────────────────────────────────────────────────────\n\n/**\n * Build a deploy gate layer that runs the production build and verifies\n * the artifact. Pass: ok && artifactValid. Score: 1.0 (pass) or 0 (fail).\n *\n * For families where artifact-validation isn't applicable (e.g. a\n * server-rendered build that prints a manifest), set `requireArtifact:\n * false` and rely on the runner's own ok signal.\n */\nexport function deployGateLayer<Env = unknown>(input: DeployGateLayerInput): Layer<Env> {\n const requireArtifact = input.requireArtifact ?? true\n return {\n name: input.name ?? 'deploy',\n dependsOn: input.dependsOn ?? ['build'],\n weight: input.weight ?? 1,\n capMs: input.capMs ?? 120_000,\n run: async (ctx) => {\n const start = Date.now()\n let runner: DeployRunner\n try {\n runner = await input.runner()\n } catch (err) {\n return {\n layer: input.name ?? 'deploy',\n status: 'error',\n durationMs: Date.now() - start,\n findings: [\n {\n severity: 'major',\n message: `deploy runner failed to start: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n reason: 'runner-init-failed',\n }\n }\n let result: DeployRunResult\n try {\n result = await runner.run()\n } catch (err) {\n return {\n layer: input.name ?? 'deploy',\n status: 'error',\n durationMs: Date.now() - start,\n findings: [\n {\n severity: 'major',\n message: `deploy command threw: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n reason: 'runner-throw',\n }\n }\n if (ctx.signal.aborted) {\n return {\n layer: input.name ?? 'deploy',\n status: 'timeout',\n durationMs: Date.now() - start,\n findings: [],\n reason: 'aborted by overall cap',\n }\n }\n\n const artifactOk = !requireArtifact || result.artifactValid === true\n const pass = result.ok && artifactOk\n const findings: LayerResult['findings'] = []\n if (!result.ok) {\n findings.push({\n severity: 'critical',\n message: 'deploy build exited non-zero',\n evidence: (result.output ?? '').slice(-1200),\n })\n }\n if (result.ok && requireArtifact && !result.artifactValid) {\n findings.push({\n severity: 'major',\n message: `deploy build succeeded but artifact ${result.artifactDir ?? '(unknown)'} is invalid or empty`,\n })\n }\n return {\n layer: input.name ?? 'deploy',\n status: pass ? 'pass' : 'fail',\n score: pass ? 1 : 0,\n durationMs: Date.now() - start,\n findings,\n reason: pass\n ? `deploy build OK${input.family ? ` (${input.family})` : ''}${result.artifactDir ? ` → ${result.artifactDir}` : ''}`\n : !result.ok\n ? 'build command failed'\n : 'artifact missing or invalid',\n diagnostics: {\n deployBuildOk: result.ok ? 1 : 0,\n deployArtifactOk: result.artifactValid === true ? 1 : 0,\n deployBuildMs: result.durationMs ?? null,\n },\n }\n },\n }\n}\n\n// ─── Canonical vite runner ──────────────────────────────────────────────\n\nexport interface ViteDeployRunnerInput {\n /** Workdir to build. The runner cd's here. */\n workdir: string\n /**\n * Function to run a shell command in `workdir`. Same shape as\n * agent-eval's CommandRunner.run for compositional reuse.\n */\n exec: (\n cmd: string,\n opts?: { cwd?: string; timeoutMs?: number },\n ) => Promise<{ stdout: string; stderr: string; exitCode: number }>\n /**\n * Function to test whether a path exists in the workdir. Inject\n * `(p) => existsSync(join(workdir, p))` for host runs.\n */\n exists: (relativePath: string) => boolean | Promise<boolean>\n /** Build command. Default `npm run build`. */\n buildCommand?: string\n /** Artifact directory to validate. Default `dist`. */\n artifactDir?: string\n /** Entry-point file under artifactDir. Default `index.html`. */\n artifactEntry?: string\n /** Per-build cap (ms). Default 90s. */\n timeoutMs?: number\n}\n\n/**\n * Canonical runner for `frontend-static` family — runs the build script,\n * validates `<artifactDir>/<artifactEntry>` exists. Use as the `runner:`\n * factory for {@link deployGateLayer}.\n */\nexport function viteDeployRunner(input: ViteDeployRunnerInput): DeployRunner {\n return {\n run: async () => {\n const start = Date.now()\n const cmd = input.buildCommand ?? 'npm run build'\n const artifactDir = input.artifactDir ?? 'dist'\n const artifactEntry = input.artifactEntry ?? 'index.html'\n const timeoutMs = input.timeoutMs ?? 90_000\n const result = await input.exec(cmd, { cwd: input.workdir, timeoutMs })\n const ok = result.exitCode === 0\n let artifactValid = false\n try {\n const entryExists = await input.exists(`${artifactDir}/${artifactEntry}`)\n artifactValid = ok && Boolean(entryExists)\n } catch {\n artifactValid = false\n }\n const tail = ((result.stderr || result.stdout) ?? '').slice(-1500)\n return {\n ok,\n output: tail,\n durationMs: Date.now() - start,\n artifactDir,\n artifactValid,\n }\n },\n }\n}\n\n// ─── Canonical wrangler runner ──────────────────────────────────────────\n\nexport interface WranglerDeployRunnerInput {\n workdir: string\n exec: (\n cmd: string,\n opts?: { cwd?: string; timeoutMs?: number },\n ) => Promise<{ stdout: string; stderr: string; exitCode: number }>\n exists: (relativePath: string) => boolean | Promise<boolean>\n /** Build command. Default `npm run build`. */\n buildCommand?: string\n /** Wrangler dry-run command. Default `npx wrangler deploy --dry-run --outdir dist`. */\n dryRunCommand?: string\n /** Per-step cap (ms). Default 120s. */\n timeoutMs?: number\n}\n\n/**\n * Canonical runner for the `fullstack-ts` family on Cloudflare Workers\n * (Remix / React Router v7 / Hono on Workers). Detects wrangler.toml or\n * wrangler.jsonc in the workdir, builds, then `wrangler deploy --dry-run`\n * to catch missing bindings, syntax errors in wrangler config, and\n * import-time crashes that don't surface in `tsc`.\n *\n * No wrangler config = skip with \"no wrangler\" evidence (not a failure\n * — the gate caller decides whether to require deploy validation).\n */\nexport function wranglerDeployRunner(input: WranglerDeployRunnerInput): DeployRunner {\n return {\n run: async () => {\n const start = Date.now()\n const buildCmd = input.buildCommand ?? 'npm run build'\n const dryCmd = input.dryRunCommand ?? 'npx wrangler deploy --dry-run --outdir dist'\n const timeoutMs = input.timeoutMs ?? 120_000\n\n const hasToml = await input.exists('wrangler.toml')\n const hasJsonc = hasToml ? false : await input.exists('wrangler.jsonc')\n if (!hasToml && !hasJsonc) {\n return {\n ok: false,\n output: 'no wrangler config found (wrangler.toml / wrangler.jsonc absent)',\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const build = await input.exec(buildCmd, { cwd: input.workdir, timeoutMs })\n if (build.exitCode !== 0) {\n const tail = ((build.stderr || build.stdout) ?? '').slice(-1500)\n return {\n ok: false,\n output: `build failed: ${tail}`,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const dry = await input.exec(dryCmd, { cwd: input.workdir, timeoutMs })\n if (dry.exitCode !== 0) {\n const tail = ((dry.stderr || dry.stdout) ?? '').slice(-1500)\n return {\n ok: false,\n output: `wrangler dry-run failed: ${tail}`,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const tail = ((dry.stdout || dry.stderr) ?? '').slice(-1500)\n return {\n ok: true,\n output: tail,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: true,\n }\n },\n }\n}\n","/**\n * HeldOutGate — first-class held-out paired-delta promotion gate.\n *\n * Encodes the \"honesty override\" pattern that lived inline in\n * `~/webb/redteam/scripts/agent-eval-autoresearch.ts:138–171`.\n * The optimizer's best-guess is one thing; what we should actually\n * ship is another. The gate is the line between them.\n *\n * A candidate is promoted iff ALL FOUR pass:\n *\n * 0. **Coverage**: on BOTH splits, the fraction of DEALT work items that\n * carry a real score on BOTH arms is at least `minCoverage`\n * (default 1 — all of them). See \"Missing scores are missing data\".\n * 1. **Productive runs**: the candidate has at least\n * `minProductiveRuns` paired observations on items where BOTH\n * candidate and baseline produced a real (non-silent) score.\n * 2. **Paired delta**: the lower bound of the CI on the per-item\n * holdout delta (candidate − baseline) is strictly greater than\n * `pairedDeltaThreshold`. WHICH paired statistic carries that CI\n * depends on the outcome's shape — see \"Choosing the statistic\".\n * 3. **Overfit gap**: the candidate's gap between search-split\n * score and holdout-split score is no worse (more positive)\n * than the baseline's gap by more than `overfitGapThreshold`.\n * \"Better on search, worse on holdout\" is the canonical\n * overfit pattern; this catches it.\n *\n * ## Missing scores are missing data\n *\n * Gates 1-3 all read numbers off the items where BOTH arms produced a finite\n * score. Without gate 0 that set is a SILENT FILTER: an item the candidate\n * crashed on, timed out on, or never wrote a row for simply left the\n * comparison, and the verdict was computed over whatever survived. Measured on\n * the pre-0.134 gate: 26 held-out items, a candidate that produced no score at\n * all on 20 of them, promoted at every threshold from −0.05 to +0.30 on the 6\n * it answered (`unpairedBaselineRuns: 20` sat in the evidence, read by\n * nothing); the control — the same 20 failures scored as the 0 they earned —\n * was correctly refused at a mean paired delta of −0.3808. An agent that fails\n * 77% of its tasks was promoted, and every guarantee gates 1-3 provide sat\n * behind that filter.\n *\n * The gate does NOT impute a value for those items. It cannot: it does not know\n * the failure value of the caller's metric (0 on [0,1]? 0 on 0-100? a\n * lower-is-better latency?), and guessing one is exactly the silent assumption\n * this gate exists to remove. A caller who DOES know it writes it onto the\n * record before calling — that is the caller's decision to make and to be\n * accountable for, and it then travels in the run corpus where an auditor can\n * see it. What the gate does instead is REFUSE, and report the full coverage\n * accounting (`GateEvidence.holdoutCoverage` / `searchCoverage`) so the caller\n * can see exactly which items went dark and on which arm.\n *\n * The denominator is MEASURED, never assumed: it is the set of work items the\n * comparison was DEALT, which is what `pairRunRecords` reports when it is given\n * every row of a split rather than only the scored ones. There is no list of\n * \"expected\" scenarios to keep in sync and nothing to trust — an item counts as\n * dealt because a row for it exists on at least one arm.\n *\n * ## Choosing the statistic\n *\n * The median paired delta is the robust default, but it goes BLIND wherever\n * ties dominate: with more than half the pairs tied its sample value is exactly\n * 0 whatever the shift on the rest, and the whole bootstrap CI collapses to\n * [0, 0]. `low > threshold` is then \"no\" forever at a non-negative threshold\n * and \"yes\" forever at a negative one — the gate refuses real gains AND\n * promotes real regressions. Measured: 76 held-out items with 15 candidate\n * wins, 5 candidate losses and 56 ties is a real +13.2pp lift whose median\n * paired delta is 0; the median-CI gate refused it at every non-negative\n * threshold while PROMOTING the mirror-image −13.2pp regression at any\n * negative one.\n *\n * So the statistic is picked by the shape of the data, in three cases:\n *\n * 1. **Two-point (pass/fail) outcomes on ANY encoding** — every value on both\n * arms is either 0 or one common positive level, so {0,1} and {0,100} and\n * {0,5} all qualify (see `pairedBinaryScale`). The estimand is the change in\n * success rate, rescaled into the caller's native units. Two statistics\n * answer about it and BOTH must agree before anything is promoted:\n * `pairedRiskDifferenceScore` (Tango's score interval) supplies the\n * interval, and McNemar's exact test — carried on\n * `pairedRiskDifferenceExact` — holds a veto at any non-negative threshold.\n * The score interval is the one that decides because it is valid at a\n * NONZERO margin, which is the only thing a noninferiority threshold asks\n * about; the exact test's own Clopper-Pearson interval is conditional on the\n * discordant count and is therefore a valid interval only at margin 0.\n * McNemar's b/c/p ship as evidence.\n * 2. **Everything else** — the bootstrap CI of the MEAN paired delta. The mean\n * is the estimator that answers the gate's own question (\"by how much did\n * the score move\") in the caller's units, and it is well defined on every\n * shape the median loses: tie-dominated vectors, low-cardinality lattices\n * (block scores in {⅔, 1} from averaging pass/fail leaves; integer 0-100\n * judge dimensions), and mixed arms. Measured: 26 blocks of 3 pass/fail\n * leaves carrying a real +12.8pp lift, only 23% of pairs tied, give a\n * median CI of [0, 0.333] — a lower bound of exactly 0 refuses a real lift\n * at threshold 0, which is the original bug one lattice over. There is\n * therefore no tie-fraction cutoff: any cutoff leaves the lattice case open\n * on the far side of it. `heldoutSignificance` has defaulted to the mean\n * since #316 for the same reason.\n *\n * Set `deltaStatistic: 'median'` to force the median on every input — the\n * pre-0.134 behaviour, kept for callers who want outlier robustness and accept\n * the blindness that comes with it.\n *\n * ## Fail closed\n *\n * A ZERO-WIDTH CI carries no information about how far the estimate could be\n * wrong, wherever it sits. At [0, 0] it cannot tell a gain from a regression\n * and it clears every negative threshold. Away from zero it fails the opposite\n * way: n identical positive deltas give [g, g], which clears threshold 0 on no\n * spread at all. Both are an absence of evidence, so the gate refuses with\n * `indeterminate_delta` rather than answering \"promote\".\n *\n * The decision carries a machine-readable `rejectionCode` plus an\n * `evidence` block with every number the gate looked at, so the\n * downstream researcher / paper / dashboard can re-derive the\n * verdict without re-running.\n *\n * See also:\n * - `src/statistics.ts` for `pairedBootstrap` + `wilcoxonSignedRank`, and\n * `pairedRiskDifferenceScore` / `pairedRiskDifferenceExact` (+\n * `pairedBinaryScale`) for the binary path\n * - `src/run-record.ts` for the input row schema\n * - `src/reference-replay.ts` for the older, reference-replay-\n * specific promotion path (still useful for replay-style evals).\n */\n\nimport { pairRunRecords } from './paired-arms'\nimport { minimumPairsForPairedDeltaTest } from './paired-delta-test'\nimport {\n decidePairedPromotion,\n type PairedDecisionShape,\n type PairedDecisionStatistic,\n pairedDecisionShape,\n} from './paired-promotion-decision'\nimport { isRealnessGated, observedSplitScore, type ScorePreference } from './rollout/reward'\nimport type { RunRecord } from './run-record'\nimport { wilcoxonSignedRank } from './statistics'\n\nexport type HeldOutGateRejectionCode =\n | 'few_runs'\n | 'incomplete_coverage'\n | 'missing_split_scores'\n | 'missing_cost'\n | 'negative_delta'\n | 'indeterminate_delta'\n | 'overfit_gap'\n | 'cost_ceiling'\n\n/**\n * How much of one split's DEALT work the comparison actually measured.\n *\n * `answered + unscoredPairs + candidateOnly + baselineOnly === dealt` — a\n * complete, mutually exclusive partition of the item slots the split was dealt,\n * so nothing can leave the comparison without appearing in exactly one bucket.\n */\nexport interface SplitCoverage {\n /** Work items the split was dealt: every item with a row on either arm. */\n dealt: number\n /** Dealt items carrying a finite score on BOTH arms — the only ones any\n * paired statistic can read. */\n answered: number\n /** Dealt items with a row on both arms where at least one row carried no\n * finite score: a run happened and produced nothing (crash, timeout, judge\n * failure). Measured absence, not an absent item. */\n unscoredPairs: number\n /** Dealt items only the candidate produced a row for. */\n candidateOnly: number\n /** Dealt items only the baseline produced a row for. */\n baselineOnly: number\n /** `answered / dealt`, or 0 when nothing was dealt. 1 means every dealt item\n * was scored on both arms. */\n coverage: number\n}\n\nexport interface HeldOutGateConfig {\n /** Minimum number of paired (candidate, baseline) holdout observations\n * required before promotion. The exact small-sample test may require more\n * observations at the selected confidence. */\n minProductiveRuns?: number\n /** The CI lower bound on the paired holdout delta must exceed this to\n * promote. Read in the same units as the holdout scores: with binary\n * (0/1) outcomes that is a change in success RATE (0.05 = +5pp).\n * Default 0. */\n pairedDeltaThreshold?: number\n /**\n * Which paired statistic carries the promotion CI.\n *\n * `'auto'` (default) picks by outcome shape — two-point outcomes on the exact\n * paired risk difference, everything else on the mean bootstrap (see the\n * module header). `'median'` forces the median bootstrap on every input,\n * including shapes where it is structurally blind and will refuse a real lift\n * and accept a real regression. Set it for outlier robustness on genuinely\n * continuous outcomes, or to reproduce a pre-0.134 verdict.\n */\n deltaStatistic?: 'auto' | 'median'\n /** Maximum allowed worsening of (search − holdout) gap relative to\n * baseline. Default 0.15 (i.e. candidate may overfit by up to 15\n * absolute score points more than baseline before rejection). */\n overfitGapThreshold?: number\n /** Stable label of the baseline candidate. Required — paper-grade\n * evaluation never compares two unlabelled candidates. */\n baselineKey: string\n /** Confidence level for the bootstrap CI. Default 0.95. */\n confidence?: number\n /** Bootstrap resamples. Default 2000. */\n bootstrapResamples?: number\n /** Optional deterministic seed for the bootstrap. Absent, `pairedBootstrap`\n * derives the seed from the paired observations, so the same holdout\n * reproduces the same interval. */\n seed?: number\n /**\n * Smallest acceptable `answered / dealt` fraction, required on BOTH splits.\n * Default 1: every work item the comparison was dealt must carry a real score\n * on both arms before the gate will decide anything.\n *\n * The default is 1 because a missing score is missing data, and a promotion\n * computed over \"the items that happened to answer\" is a promotion computed\n * over a set the candidate selected by failing (see the module header). One\n * split below `minCoverage` rejects with `incomplete_coverage`.\n *\n * Lowering it is a real, defensible choice for a caller who accepts a known\n * flake rate — but it must be DECLARED, not inherited: the shrunken\n * denominator then still ships in `GateEvidence.holdoutCoverage` /\n * `searchCoverage`, so the verdict can never be read without it. Must be in\n * [0, 1]; anything else throws rather than clamping.\n */\n minCoverage?: number\n /**\n * Hard ceiling on the candidate's median per-task USD cost. When the\n * candidate clears the quality gates (paired-delta + overfit-gap) but\n * its median cost exceeds this number, the gate rejects with\n * `cost_ceiling`. Default `undefined` = no cost ceiling, behaving\n * exactly like the pre-cost gate.\n *\n * This exists because \"we ship the better prompt\" is only an honest\n * pitch when the better prompt also fits a customer-stated budget.\n * Cost is read from `RunRecord.costUsd`; a null amount rejects a\n * configured cost check because the limit cannot be proven.\n */\n costPerTaskCeiling?: number\n}\n\n/** Which paired statistic a `HeldOutGate` verdict was decided on. One\n * definition, shared with every other gate that decides a paired interval. */\nexport type DeltaStatistic = PairedDecisionStatistic\n\nexport interface GateEvidence {\n /** Number of paired (candidate, baseline) holdout observations used. */\n productiveRuns: number\n /** Candidate holdout rows with no baseline row at the same work identity. */\n unpairedCandidateRuns: number\n /** Baseline holdout rows with no candidate row at the same work identity. */\n unpairedBaselineRuns: number\n /**\n * How much of the dealt HOLDOUT work carried a score on both arms — the\n * denominator behind `productiveRuns`, `medianPairedDelta`, `pairedCI` and\n * `holdoutScore`. A `coverage` below 1 means those numbers describe a\n * SUBSET of the items the comparison was dealt, and which items are in that\n * subset was decided by whichever arm went dark.\n */\n holdoutCoverage: SplitCoverage\n /**\n * The same accounting for the SEARCH split — the denominator behind\n * `searchScore`, and therefore behind both overfit gaps.\n */\n searchCoverage: SplitCoverage\n /** Median of paired holdout deltas, or null when there are no pairs.\n * ALWAYS the literal median — a diagnostic, not necessarily the statistic\n * the verdict keyed on (see `deltaStatistic` / `decidingDelta`). On binary\n * outcomes this is normally 0 by construction. */\n medianPairedDelta: number | null\n /** Which paired statistic the promotion CI was computed on, and therefore\n * what `decidingDelta` / `pairedCI` mean. `'median_bootstrap'` = bootstrap\n * CI on the median paired delta (continuous outcomes).\n * `'mean_bootstrap'` = bootstrap CI on the mean paired delta, used when ties\n * dominate and pin the median at 0. `'paired_risk_difference'` = change in\n * success rate on a two-point (pass/fail) outcome, on an EXACT conditional\n * interval dual to McNemar's exact test, rescaled to the outcome's native\n * units (so a 0-100 dimension reports points, not a rate). */\n deltaStatistic: DeltaStatistic\n /** Point estimate of `deltaStatistic` — the number the `pairedDeltaThreshold`\n * check is about. Null when no CI was computed. */\n decidingDelta: number | null\n /** CI on `deltaStatistic`, if computed. The gate promotes iff\n * `pairedCI.low > pairedDeltaThreshold`. */\n pairedCI: { low: number; high: number } | null\n /** Wilcoxon signed-rank p-value, if computed. Always the Wilcoxon, on both\n * paths, so this field never changes meaning. */\n pairedPValue: number | null\n /** McNemar's exact paired-binary test on the holdout pairs, or null when the\n * outcomes were not two-point (or no CI was computed). `b` = candidate-only\n * wins, `c` = baseline-only wins; only these discordant pairs carry signal.\n * When present it is not merely reported: the promotion interval is dual to\n * this p-value, so a promotion at a non-negative threshold implies\n * `pValue < 1 − confidence`. */\n mcnemar: { b: number; c: number; nDiscordant: number; pValue: number } | null\n /** The common positive level of a two-point outcome — 1 for {0,1}, 100 for a\n * 0-100 pass/fail dimension — or null when the outcome is not two-point.\n * Non-null is exactly the condition for the `paired_risk_difference` path,\n * and it is the factor `decidingDelta` / `pairedCI` were rescaled by. */\n binaryScale: number | null\n /** Fraction of paired holdout deltas that are exact ties, or null when there\n * are no pairs. At or above 0.5 the median paired delta is pinned at 0 by\n * construction; this is the diagnostic for why a median-decided verdict\n * (`deltaStatistic: 'median'`) saw nothing. */\n tieFraction: number | null\n /** Mean candidate score on the search split, or null when absent. */\n searchScore: number | null\n /** Mean candidate score on the holdout split, or null when absent. */\n holdoutScore: number | null\n /** Candidate (search − holdout) gap, or null when either side is absent. */\n overfitGap: number | null\n /** Baseline (search − holdout) gap, or null when either side is absent. */\n baselineOverfitGap: number | null\n /** Median per-task USD cost across the candidate's runs. Recorded\n * even when no `costPerTaskCeiling` is configured so downstream\n * dashboards (intelligence.tangle.tools) can render \\$/task per\n * generation regardless of gating policy. */\n medianCandidateCost: number | null\n /** Median per-task USD cost across the baseline runs, for\n * symmetric reporting. */\n medianBaselineCost: number | null\n /**\n * Runs (candidate + baseline) dropped before pairing because the\n * authenticity gate flagged them as gamed. Surfaced rather than silent: a\n * promotion decision computed over a shrunken pool has to say by how much,\n * and a nonzero count here is itself the finding.\n */\n realnessGatedRuns: number\n}\n\nexport interface GateDecision {\n /** Final promote/no-promote verdict. */\n promote: boolean\n /** The candidate that was evaluated. */\n candidateId: string\n /** The baseline it was compared against. */\n baselineId: string\n /** Every number the gate looked at, for audit + paper export. */\n evidence: GateEvidence\n /** Human-readable reason. */\n reason: string\n /** Machine-readable rejection code, or null on promote. */\n rejectionCode: HeldOutGateRejectionCode | null\n}\n\n/**\n * Held-out paired-delta promotion gate. Construct once with config,\n * call `evaluate(candidateRuns, baselineRuns)` per (candidate,\n * baseline) pair. Stateless across calls.\n */\nexport class HeldOutGate {\n private readonly minProductiveRuns: number\n private readonly pairedDeltaThreshold: number\n private readonly overfitGapThreshold: number\n private readonly baselineKey: string\n private readonly confidence: number\n private readonly resamples: number\n private readonly seed?: number\n private readonly costPerTaskCeiling?: number\n private readonly minCoverage: number\n private readonly deltaStatistic: 'auto' | 'median'\n\n constructor(config: HeldOutGateConfig) {\n if (!config.baselineKey) {\n throw new Error('HeldOutGate: baselineKey is required')\n }\n if (\n config.minCoverage !== undefined &&\n !(Number.isFinite(config.minCoverage) && config.minCoverage >= 0 && config.minCoverage <= 1)\n ) {\n throw new Error(\n `HeldOutGate: minCoverage must be a finite fraction in [0, 1], got ${config.minCoverage}`,\n )\n }\n this.minCoverage = config.minCoverage ?? 1\n this.confidence = config.confidence ?? 0.95\n this.minProductiveRuns = Math.max(\n config.minProductiveRuns ?? 3,\n minimumPairsForPairedDeltaTest(this.confidence),\n )\n this.pairedDeltaThreshold = config.pairedDeltaThreshold ?? 0\n this.overfitGapThreshold = config.overfitGapThreshold ?? 0.15\n this.baselineKey = config.baselineKey\n this.resamples = config.bootstrapResamples ?? 2000\n this.seed = config.seed\n this.deltaStatistic = config.deltaStatistic ?? 'auto'\n if (\n config.costPerTaskCeiling !== undefined &&\n !(Number.isFinite(config.costPerTaskCeiling) && config.costPerTaskCeiling > 0)\n ) {\n throw new Error('HeldOutGate: costPerTaskCeiling must be a positive finite number')\n }\n this.costPerTaskCeiling = config.costPerTaskCeiling\n }\n\n /** Decide whether `candidate` should replace `baseline`.\n * Pairing is by `(experimentId, scenarioId, seed)`.\n * Missing or duplicate identities throw instead of comparing by position. */\n evaluate(candidate: RunRecord[], baseline: RunRecord[]): GateDecision {\n const candidateId = inferCandidateId(candidate, this.baselineKey)\n const baselineId = this.baselineKey\n assertScenarioIdentities([...candidate, ...baseline])\n\n // Runs flagged as gamed are dropped from BOTH sides before anything is\n // paired. This is a promotion decision, and the whole point of the\n // authenticity gate is that a faked success must not buy a promotion; the\n // count ships in the evidence so the shrunken pool is never invisible.\n const realnessGatedRuns = [...candidate, ...baseline].filter(isRealnessGated).length\n const honestCandidate = candidate.filter((run) => !isRealnessGated(run))\n const honestBaseline = baseline.filter((run) => !isRealnessGated(run))\n\n const candidateSearch = scoredRuns(honestCandidate, 'search')\n const baselineSearch = scoredRuns(honestBaseline, 'search')\n const candidateHoldout = scoredRuns(honestCandidate, 'holdout')\n const baselineHoldout = scoredRuns(honestBaseline, 'holdout')\n const searchPairing = pairRunRecords(baselineSearch, candidateSearch)\n const holdoutPairing = pairRunRecords(baselineHoldout, candidateHoldout)\n // The DEALT denominators, measured over every row of each split — scored or\n // not — so an item that produced no number is still counted as work the\n // comparison was given. `splitCoverage` re-pairs the unfiltered rows with\n // the same primitive the decision pairs with, which is the only way the\n // \"dealt\" set can be derived rather than assumed.\n const searchCoverage = splitCoverage(honestBaseline, honestCandidate, 'search')\n const holdoutCoverage = splitCoverage(honestBaseline, honestCandidate, 'holdout')\n // `scoredRuns` admits only rows whose split score is a finite number, so\n // the non-null assertion below cannot fire on data the pairing saw.\n const splitScoreOf = (run: RunRecord, split: ScorePreference): number =>\n observedSplitScore(run, split) as number\n const beforeSearch = searchPairing.pairs.map((pair) => splitScoreOf(pair.baseline, 'search'))\n const afterSearch = searchPairing.pairs.map((pair) => splitScoreOf(pair.treatment, 'search'))\n const beforeHoldout = holdoutPairing.pairs.map((pair) => splitScoreOf(pair.baseline, 'holdout'))\n const afterHoldout = holdoutPairing.pairs.map((pair) => splitScoreOf(pair.treatment, 'holdout'))\n\n const productiveRuns = beforeHoldout.length\n\n const candidateSearchMean = meanOrNull(afterSearch)\n const candidateHoldoutMean = meanOrNull(afterHoldout)\n const baselineSearchMean = meanOrNull(beforeSearch)\n const baselineHoldoutMean = meanOrNull(beforeHoldout)\n\n const overfitGap = diffOrNull(candidateSearchMean, candidateHoldoutMean)\n const baselineOverfitGap = diffOrNull(baselineSearchMean, baselineHoldoutMean)\n\n // Cost summary — surfaced in evidence regardless of gating policy so\n // downstream dashboards always know what the candidate cost.\n //\n // The population is the rows that DECIDED this verdict: the matched pairs\n // on both splits, and nothing else. Taking the median over every row the\n // caller happened to pass is a denominator nobody measured, and it is\n // trivially movable — 48 rows tagged `dev` at $0.0001, which the gate never\n // scores and the coverage check never counts, drag a real $5.00/task\n // candidate to a reported $0.0001 and clear a $1.00 ceiling. Deriving the\n // population from the pairing rather than from a list of split tags means\n // there is no tag to sit outside the rule: a row either decided the verdict\n // or it does not describe its cost.\n const medianCandidateCost = completeCostMedian([\n ...searchPairing.pairs.map((pair) => pair.treatment),\n ...holdoutPairing.pairs.map((pair) => pair.treatment),\n ])\n const medianBaselineCost = completeCostMedian([\n ...searchPairing.pairs.map((pair) => pair.baseline),\n ...holdoutPairing.pairs.map((pair) => pair.baseline),\n ])\n const commonEvidence = {\n productiveRuns,\n unpairedCandidateRuns: holdoutPairing.unpairedTreatment.length,\n unpairedBaselineRuns: holdoutPairing.unpairedBaseline.length,\n searchScore: candidateSearchMean,\n holdoutScore: candidateHoldoutMean,\n overfitGap,\n baselineOverfitGap,\n medianCandidateCost,\n medianBaselineCost,\n realnessGatedRuns,\n searchCoverage,\n holdoutCoverage,\n }\n /** Evidence for the early exits, where no CI was computed at all. The\n * statistic that WOULD have decided is still reported so a caller can see\n * which branch their data lands in without producing a verdict. */\n const earlyShape = this.chooseShape(beforeHoldout, afterHoldout)\n const noCiEvidence = {\n ...commonEvidence,\n medianPairedDelta: productiveRuns > 0 ? medianDelta(beforeHoldout, afterHoldout) : null,\n deltaStatistic: earlyShape.statistic,\n decidingDelta: null,\n pairedCI: null,\n pairedPValue: null,\n mcnemar: null,\n binaryScale: earlyShape.binaryScale,\n tieFraction: earlyShape.tieFraction,\n }\n\n const missingSplitScores = [\n candidateSearch.length === 0 ? 'candidate search' : null,\n candidateHoldout.length === 0 ? 'candidate holdout' : null,\n baselineSearch.length === 0 ? 'baseline search' : null,\n baselineHoldout.length === 0 ? 'baseline holdout' : null,\n ].filter((label): label is string => label !== null)\n if (missingSplitScores.length > 0) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason: `missing_split_scores: ${missingSplitScores.join(', ')} score evidence is absent`,\n rejectionCode: 'missing_split_scores',\n }\n }\n\n // COVERAGE — before every statistic, because every statistic below reads\n // only the items that answered. A candidate that went dark on most of its\n // work does not get judged on the remainder; missing scores are missing\n // data, and the gate refuses rather than shrinking the denominator to the\n // subset that happened to answer. Checked ahead of `few_runs` because \"6 of\n // 26 items produced no score\" is the finding, and \"6 paired observations\"\n // is only its shadow.\n const shortfalls = (\n [\n ['holdout', holdoutCoverage],\n ['search', searchCoverage],\n ] as const\n ).filter(([, cov]) => cov.coverage < this.minCoverage)\n if (shortfalls.length > 0) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason:\n `incomplete_coverage: ${shortfalls.map(([split, cov]) => describeCoverage(split, cov)).join('; ')}` +\n ` — required ${fmt(this.minCoverage)} of every dealt item scored on both arms.` +\n ' A missing score is missing data, not an absent item: the gate will not decide on the subset that answered',\n rejectionCode: 'incomplete_coverage',\n }\n }\n\n if (productiveRuns < this.minProductiveRuns) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason: `few_runs: ${productiveRuns} paired holdout observation(s) < min ${this.minProductiveRuns}`,\n rejectionCode: 'few_runs',\n }\n }\n if (overfitGap === null || baselineOverfitGap === null) {\n throw new Error('HeldOutGate: complete split scores did not produce overfit gaps')\n }\n\n // The paired holdout delta, decided by the one shared rule (see\n // `paired-promotion-decision.ts`): the estimator comes from the outcome's\n // shape, McNemar vetoes at a non-negative threshold, and a zero-width\n // interval is refused. `medianPairedDelta` stays the literal median on\n // EVERY path so the number that made the old gate blind remains visible.\n const decision = decidePairedPromotion(beforeHoldout, afterHoldout, {\n threshold: this.pairedDeltaThreshold,\n confidence: this.confidence,\n resamples: this.resamples,\n seed: this.seed,\n minPairs: this.minProductiveRuns,\n statistic: this.deltaStatistic === 'median' ? 'median' : 'mean',\n })\n const literalMedian = medianDelta(beforeHoldout, afterHoldout)\n const wilcoxon = wilcoxonSignedRank(beforeHoldout, afterHoldout)\n const { delta: decidingDelta, low, high, label: deltaLabel } = decision\n\n const evidence: GateEvidence = {\n ...commonEvidence,\n medianPairedDelta: literalMedian,\n deltaStatistic: decision.statistic,\n decidingDelta,\n pairedCI: { low, high },\n pairedPValue: wilcoxon.p,\n mcnemar: decision.mcnemar,\n binaryScale: decision.binaryScale,\n tieFraction: decision.tieFraction,\n }\n\n // FAIL CLOSED on a ZERO-WIDTH interval, wherever it sits. [0, 0] cannot\n // tell a gain from a regression and clears every negative threshold, which\n // is exactly how a tie-pinned median laundered a −13.2pp regression into a\n // promotion. But the same emptiness away from zero is just as false a\n // certainty and it fails the other way: n identical positive deltas give\n // [g, g], which clears threshold 0 with no spread to support it. Under a\n // bounded asymmetric null whose true mean paired delta is exactly 0 — 2 %\n // of pairs dropping by 1.0, the rest gaining 0.0204 — every sample that\n // misses the drop is exactly that shape, and a `low === 0 && high === 0`\n // test promotes 65.65 % of them at n = 20 against a nominal 5 %.\n if (decision.indeterminate) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `indeterminate_delta: ${decision.indeterminateCause}, so the paired holdout CI is ` +\n `[${fmt(low)}, ${fmt(high)}] and carries no direction — ` +\n `it cannot clear threshold ${fmt(this.pairedDeltaThreshold)} on evidence`,\n rejectionCode: 'indeterminate_delta',\n }\n }\n\n // The exact test is a VETO on the two-point path. Redundant by construction\n // — `pairedRiskDifferenceExact`'s interval is dual to this p-value, so\n // `low > 0` already implies `pValue < 1 − confidence` (verified over 8108\n // (b, c, ties, confidence) shapes) — and kept anyway so that swapping the\n // estimator for one without that duality (the Wald interval, which\n // undercovers on a handful of discordant pairs) cannot silently reintroduce\n // \"promotes what the exact test refuses\". Only applies at a non-negative\n // threshold: a negative threshold is a non-inferiority question, which\n // McNemar's test of \"no difference\" is not the right test for.\n const exactTestVetoes = decision.exactTestVetoes\n\n // Negative-delta gate (the paired-delta evidence must clear the threshold).\n if (!decision.clearsThreshold || exactTestVetoes) {\n const detail = exactTestVetoes\n ? ` McNemar exact p=${decision.mcnemar?.pValue.toExponential(2)} does not reject at α=${fmt(1 - this.confidence)}.`\n : decision.methodDetail\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `negative_delta: paired holdout ${deltaLabel} Δ=${fmt(decidingDelta)} ` +\n `CI=[${fmt(low)}, ${fmt(high)}] does not clear threshold ${fmt(this.pairedDeltaThreshold)}.${detail}`,\n rejectionCode: 'negative_delta',\n }\n }\n\n // Overfit-gap gate. We allow some absolute slack —\n // candidate.gap ≤ baseline.gap + overfitGapThreshold.\n if (overfitGap > baselineOverfitGap + this.overfitGapThreshold) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `overfit_gap: candidate gap=${fmt(overfitGap)} exceeds baseline gap=${fmt(baselineOverfitGap)} ` +\n `by more than ${fmt(this.overfitGapThreshold)}`,\n rejectionCode: 'overfit_gap',\n }\n }\n\n // Cost-ceiling gate. Runs after quality gates so a cost-driven\n // rejection always carries a \"you cleared quality but blew budget\"\n // story rather than masking a quality failure.\n if (this.costPerTaskCeiling !== undefined && medianCandidateCost === null) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason: 'missing_cost: candidate cost evidence is incomplete',\n rejectionCode: 'missing_cost',\n }\n }\n if (\n this.costPerTaskCeiling !== undefined &&\n medianCandidateCost !== null &&\n medianCandidateCost > this.costPerTaskCeiling\n ) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `cost_ceiling: candidate median cost $${fmt(medianCandidateCost)} ` +\n `exceeds ceiling $${fmt(this.costPerTaskCeiling)} (baseline $${fmt(medianBaselineCost)})`,\n rejectionCode: 'cost_ceiling',\n }\n }\n\n return {\n promote: true,\n candidateId,\n baselineId,\n evidence,\n reason:\n `promote: paired holdout ${deltaLabel} Δ=${fmt(decidingDelta)} ` +\n `CI=[${fmt(low)}, ${fmt(high)}] over ${productiveRuns} pairs; ` +\n `overfit gap candidate=${fmt(overfitGap)} vs baseline=${fmt(baselineOverfitGap)}; ` +\n `median cost candidate=$${fmt(medianCandidateCost)} vs baseline=$${fmt(medianBaselineCost)}`,\n rejectionCode: null,\n }\n }\n\n /**\n * Which paired statistic decides this data, and the shape facts behind it —\n * for the early exits, where no interval is computed. Delegates to\n * {@link pairedDecisionShape} so the reported shape can never disagree with\n * the shape the decision actually routes on.\n */\n private chooseShape(before: number[], after: number[]): PairedDecisionShape {\n return pairedDecisionShape(before, after, this.deltaStatistic === 'median' ? 'median' : 'mean')\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction inferCandidateId(candidate: RunRecord[], baselineKey: string): string {\n for (const run of candidate) {\n if (run.candidateId && run.candidateId !== baselineKey) return run.candidateId\n }\n // All candidate rows match the baseline key — caller mistake, but\n // surface the symptom rather than throwing inside the gate.\n return candidate[0]?.candidateId ?? '(unknown candidate)'\n}\n\nfunction assertScenarioIdentities(runs: RunRecord[]): void {\n for (const run of runs) {\n if (typeof run.scenarioId !== 'string' || run.scenarioId.trim() === '') {\n throw new Error(`HeldOutGate: run ${run.runId} is missing scenarioId`)\n }\n }\n}\n\n/**\n * Rows carrying a finite score on one split. RAW (`observedSplitScore`) by\n * choice: the gated runs are already removed by the caller, so applying the\n * gate again here would only zero runs that are no longer in the set, and the\n * reported means must describe the runs that actually decided the promotion.\n */\nfunction scoredRuns(runs: RunRecord[], split: ScorePreference): RunRecord[] {\n return runs.filter((run) => {\n if (run.splitTag !== split) return false\n const v = observedSplitScore(run, split)\n return typeof v === 'number' && Number.isFinite(v)\n })\n}\n\n/** Every row tagged to one split, scored or not — the work the split was\n * DEALT, as opposed to the work it managed to measure. */\nfunction dealtRuns(runs: RunRecord[], split: ScorePreference): RunRecord[] {\n return runs.filter((run) => run.splitTag === split)\n}\n\nfunction hasFiniteScore(run: RunRecord, split: ScorePreference): boolean {\n const v = observedSplitScore(run, split)\n return typeof v === 'number' && Number.isFinite(v)\n}\n\n/**\n * Partition one split's dealt work into answered / unscored / one-armed.\n *\n * Pairs the UNFILTERED rows with the same `pairRunRecords` the decision uses,\n * so the denominator comes out of the same identity rules as the numerator and\n * cannot drift from it. Deliberately a SECOND pairing rather than a widening of\n * the decision's own: the decision keeps pairing exactly the rows it always\n * paired, so this check can only ever add a refusal, never move a verdict that\n * was already being made on a complete set.\n */\nfunction splitCoverage(\n baseline: RunRecord[],\n candidate: RunRecord[],\n split: ScorePreference,\n): SplitCoverage {\n const pairing = pairRunRecords(dealtRuns(baseline, split), dealtRuns(candidate, split))\n let answered = 0\n for (const pair of pairing.pairs) {\n if (hasFiniteScore(pair.baseline, split) && hasFiniteScore(pair.treatment, split)) answered += 1\n }\n const unscoredPairs = pairing.pairs.length - answered\n const candidateOnly = pairing.unpairedTreatment.length\n const baselineOnly = pairing.unpairedBaseline.length\n const dealt = pairing.pairs.length + candidateOnly + baselineOnly\n return {\n dealt,\n answered,\n unscoredPairs,\n candidateOnly,\n baselineOnly,\n coverage: dealt === 0 ? 0 : answered / dealt,\n }\n}\n\nfunction describeCoverage(split: string, cov: SplitCoverage): string {\n const dark = [\n cov.unscoredPairs > 0 ? `${cov.unscoredPairs} ran on both arms but produced no score` : null,\n cov.baselineOnly > 0 ? `${cov.baselineOnly} only the baseline produced a row for` : null,\n cov.candidateOnly > 0 ? `${cov.candidateOnly} only the candidate produced a row for` : null,\n ].filter((part): part is string => part !== null)\n return (\n `${split} scored ${cov.answered} of ${cov.dealt} dealt items (coverage ${fmt(cov.coverage)})` +\n (dark.length > 0 ? ` — ${dark.join(', ')}` : '')\n )\n}\n\nfunction meanOrNull(xs: number[]): number | null {\n if (xs.length === 0) return null\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction diffOrNull(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null\n return a - b\n}\n\nfunction medianDelta(before: number[], after: number[]): number {\n const ds = before.map((b, i) => after[i]! - b).sort((x, y) => x - y)\n if (ds.length === 0) throw new Error('HeldOutGate: median delta requires at least one pair')\n const mid = Math.floor(ds.length / 2)\n return ds.length % 2 === 0 ? (ds[mid - 1]! + ds[mid]!) / 2 : ds[mid]!\n}\n\nfunction medianFinite(xs: number[]): number | null {\n const ys = xs.filter((x) => Number.isFinite(x)).sort((x, y) => x - y)\n if (ys.length === 0) return null\n const mid = Math.floor(ys.length / 2)\n return ys.length % 2 === 0 ? (ys[mid - 1]! + ys[mid]!) / 2 : ys[mid]!\n}\n\nfunction completeCostMedian(runs: RunRecord[]): number | null {\n if (runs.length === 0) return null\n const costs: number[] = []\n for (const run of runs) {\n const provenance = run.costProvenance\n if (provenance.kind === 'uncaptured') return null\n costs.push(provenance.usd)\n }\n return medianFinite(costs)\n}\n\nfunction fmt(x: number | null): string {\n if (x === null) return 'n/a'\n return x.toFixed(4)\n}\n","/**\n * Hidden-criteria grading firewall — grade an agent on criteria it never saw.\n *\n * A trustworthy benchmark splits every scenario's data by WHERE each field is\n * allowed to flow, then proves the held-out / judge-only fields never reach the\n * agent during the run. The coding bench expresses this with four destinations\n * (prompt / develop-against / held-out suite / rubric); this module lifts the\n * domain-FREE core out of it so research, legal, tax, content — any domain —\n * can declare the same routing and get the same firewall enforcement and the\n * same held-out-weighted composite, plugging in its OWN grader.\n *\n * Two reusable pieces, both domain-agnostic:\n *\n * 1. FIELD ROUTING BY DESTINATION. A scenario declares each field's\n * `FieldDestination`; `assertNoHiddenLeak` is a pure checker that throws if\n * a grading-only or judge-only field's value appears in what reaches the\n * agent. The domain decides which fields exist and where they go — the\n * substrate only enforces \"hidden stays hidden\".\n *\n * 2. HIDDEN-CRITERIA GRADING. The domain supplies its own grader\n * `(artifact, hiddenCriteria) => { passRate, total }` — the coding\n * node-test executor is ONE such grader a consumer plugs in; the substrate\n * bakes in NO node/test/TS/exec/regex. `gradeOnHidden` runs that grader\n * behind the firewall and `blendHeldout` composes its pass rate with a\n * judge score into the final number the leaderboard ranks on.\n *\n * Shape mirrors `treatment-gate`/`authenticity`: pure predicates and pure\n * composition over already-computed values, fail-loud, with the\n * \"which field / which weight / which grader\" decisions left as parameters and\n * no domain literal anywhere in the module.\n *\n * Lives next to `test-graded-scenario` and `partition-held-out` — it is a\n * scorecard/grading concept that makes sense without a running agent loop.\n */\n\nimport type { JudgeScore } from './campaign/types'\nimport { ValidationError } from './errors'\n\n// ── 1. field routing by destination ──────────────────────────────────────────\n\n/**\n * Where one scenario field is allowed to flow. The firewall guarantee is keyed\n * on this tag, not on a field name — a domain can have any number of fields per\n * destination.\n *\n * - `agent-visible` reaches the agent's context during the run (the prompt,\n * the task statement — what the agent reads to act).\n * - `develop-against` seeded into the agent's environment during the run so it\n * can iterate (a visible example/test/reference). The\n * agent MAY read it — that is intentional (real TDD). Not\n * a leak: it is example-grade, not the grading criteria.\n * - `grading-only` the hidden criteria. Used ONLY at grading, after the run\n * — the held-out suite / answer key / hidden requirements.\n * Must NEVER reach the agent context. This is what makes a\n * good score un-memorizable.\n * - `judge-only` grading context for the judge only (rubric anchors,\n * design intent). Lives with the judge, never in the agent\n * context.\n */\nexport type FieldDestination = 'agent-visible' | 'develop-against' | 'grading-only' | 'judge-only'\n\n/** The destinations a value must be kept OUT of the agent context for. */\nconst hiddenDestinations: ReadonlySet<FieldDestination> = new Set<FieldDestination>([\n 'grading-only',\n 'judge-only',\n])\n\n/** True for the destinations whose values must never reach the agent context. */\nexport function isHiddenDestination(destination: FieldDestination): boolean {\n return hiddenDestinations.has(destination)\n}\n\n/**\n * A scenario's fields routed by destination. The domain owns the field set\n * (`TFields` — a record of its named fields to their string-renderable values)\n * and declares one `FieldDestination` per field. `routeFields` builds this from\n * a domain's `(value, destination)` map; the firewall reads it.\n */\nexport interface RoutedField {\n /** The field's name — for diagnostics only. */\n name: string\n /** The field's value as it would be rendered into text. The firewall compares\n * this against the agent context, so a domain that ships structured data\n * passes a stable string projection (e.g. JSON) of the hidden value. */\n value: string\n destination: FieldDestination\n}\n\n/**\n * Route a domain's named fields by destination into the firewall's input shape.\n * The `routing` declares each field's destination; the `values` carry each\n * field's renderable string. A field present in `routing` but missing from\n * `values` is an authoring error (fail loud) — every routed field must have a\n * value the firewall can check.\n */\nexport function routeFields<TName extends string>(\n routing: Readonly<Record<TName, FieldDestination>>,\n values: Readonly<Record<TName, string>>,\n): RoutedField[] {\n const out: RoutedField[] = []\n for (const name of Object.keys(routing) as TName[]) {\n const value = values[name]\n if (value === undefined) {\n throw new ValidationError(\n `routed field \"${name}\" has a destination but no value — every routed field must carry its value`,\n )\n }\n out.push({ name, value, destination: routing[name] })\n }\n return out\n}\n\n/** A single detected leak: a hidden field whose value appears in the agent context. */\nexport interface HiddenLeak {\n field: string\n destination: FieldDestination\n}\n\nexport interface NoLeakOptions {\n /** Minimum hidden-value length to check. A hidden value shorter than this is\n * skipped — a one-word or empty hidden field would substring-match innocuous\n * prose and is not meaningful evidence of a leak. Default 12. */\n minMatchLength?: number\n}\n\n/**\n * The FIREWALL. Throws `ValidationError` if any `grading-only`/`judge-only`\n * field's value is found inside `agentContext` — the exact text that reaches the\n * agent during the run (its prompt, its seeded files concatenated, whatever the\n * caller assembled). `agent-visible` and `develop-against` fields are never\n * checked: they are meant to be there.\n *\n * Substring containment is the check: it is domain-free and catches the failure\n * that matters — a hidden answer key, held-out case, or rubric anchor pasted\n * into the prompt. Returns the routed fields on success so a caller can chain.\n */\nexport function assertNoHiddenLeak(\n fields: readonly RoutedField[],\n agentContext: string,\n opts: NoLeakOptions = {},\n): readonly RoutedField[] {\n const minLen = opts.minMatchLength ?? 12\n const leaks: HiddenLeak[] = []\n for (const field of fields) {\n if (!isHiddenDestination(field.destination)) continue\n const needle = field.value.trim()\n if (needle.length < minLen) continue\n if (agentContext.includes(needle)) {\n leaks.push({ field: field.name, destination: field.destination })\n }\n }\n if (leaks.length > 0) {\n const detail = leaks.map((l) => `\"${l.field}\" (${l.destination})`).join(', ')\n throw new ValidationError(\n `hidden-criteria firewall breached: ${leaks.length} hidden field(s) reached the agent context: ${detail}`,\n )\n }\n return fields\n}\n\n/** Collect the values a domain may safely render into the agent context — the\n * `agent-visible` (and, by intent, `develop-against`) fields — so a caller can\n * ASSEMBLE the context from the routing rather than hand-picking fields and\n * risking a slip. `develop-against` is included because it is seeded into the\n * agent's environment during the run on purpose. */\nexport function agentVisibleFields(fields: readonly RoutedField[]): RoutedField[] {\n return fields.filter((f) => !isHiddenDestination(f.destination))\n}\n\n// ── 2. hidden-criteria grading ────────────────────────────────────────────────\n\n/** What a hidden-criteria grader reports. `passRate = passed / total` over the\n * hidden checks; `total === 0` means the criteria never ran (e.g. the artifact\n * did not even load) — an honest zero, never a spurious pass. */\nexport interface HiddenGradeResult {\n /** Hidden checks that passed. */\n passed: number\n /** Total hidden checks attempted. 0 when the criteria could not run at all. */\n total: number\n /** `passed / total`, or 0 when `total === 0`. The PRIMARY correctness score. */\n passRate: number\n /** Free-form provenance the caller may record (runner output, reason for 0). */\n notes?: string\n}\n\n/**\n * The domain's grader: given the agent's artifact and the HIDDEN criteria,\n * return a pass rate. This is the ONE seam a non-coding domain implements — the\n * coding node-test executor is a single implementation of it; a legal grader\n * checks the brief against hidden required holdings, a research grader checks an\n * answer against held-out facts, a tax grader runs hidden return assertions.\n * The substrate calls it ONLY at grading time, behind the firewall.\n *\n * `THidden` is the domain's hidden-criteria payload (the held-out suite, the\n * answer key, the hidden requirements) — opaque to the substrate.\n */\nexport type HiddenCriteriaGrader<TArtifact, THidden> = (\n artifact: TArtifact,\n hiddenCriteria: THidden,\n signal?: AbortSignal,\n) => Promise<HiddenGradeResult> | HiddenGradeResult\n\n/** Normalize a grader's raw `{passed, total}` into a `HiddenGradeResult` with a\n * consistent, fail-loud `passRate` — the canonical \"honest zero on no-run\"\n * rule, single-sourced so every domain grader gets it. */\nexport function hiddenGrade(passed: number, total: number, notes?: string): HiddenGradeResult {\n const p = Number.isFinite(passed) && passed > 0 ? Math.floor(passed) : 0\n const t = Number.isFinite(total) && total > 0 ? Math.floor(total) : 0\n const passRate = t > 0 ? Math.min(1, p / t) : 0\n return { passed: Math.min(p, t > 0 ? t : p), total: t, passRate, notes }\n}\n\n/**\n * Run a domain's hidden-criteria grader behind the firewall. Before grading, it\n * re-asserts the firewall against the agent context the run actually used —\n * proving (at grading time, on real data) that the hidden criteria never\n * reached the agent — then invokes the grader and returns its pass rate. A\n * domain that wants the firewall and the grader wired together in one call uses\n * this; a domain that already asserted the firewall at dispatch time can call\n * its grader directly and feed the result to `blendHeldout`.\n */\nexport async function gradeOnHidden<TArtifact, THidden>(args: {\n artifact: TArtifact\n hiddenCriteria: THidden\n grader: HiddenCriteriaGrader<TArtifact, THidden>\n /** The routed fields + the exact agent context, re-checked before grading. */\n firewall: { fields: readonly RoutedField[]; agentContext: string; options?: NoLeakOptions }\n signal?: AbortSignal\n}): Promise<HiddenGradeResult> {\n assertNoHiddenLeak(args.firewall.fields, args.firewall.agentContext, args.firewall.options)\n const result = await args.grader(args.artifact, args.hiddenCriteria, args.signal)\n return hiddenGrade(result.passed, result.total, result.notes)\n}\n\n// ── the composite: hidden correctness (PRIMARY) + judge quality (secondary) ────\n\n/** Weights for the held-out / judge blend. Must be finite and non-negative;\n * they are renormalized to sum to 1 so a caller can pass any positive ratio. */\nexport interface BlendWeights {\n /** Weight on the hidden-criteria pass rate (the primary, ungameable score). */\n heldout: number\n /** Weight on the judge's quality composite (the secondary style/quality score). */\n judge: number\n}\n\n/** Default blend: 0.7 hidden correctness, 0.3 judge quality. The coding bench's\n * long-standing split — execution truth dominates, style refines. */\nexport const defaultBlendWeights: BlendWeights = { heldout: 0.7, judge: 0.3 }\n\n/** The input shape a judge's `score` receives — exactly `JudgeConfig.score`'s\n * argument: the artifact, plus any scenario/signal fields the judge carries.\n * `withHeldoutBlend` only reads `artifact`; the rest rides through. */\nexport interface JudgeScoreInput<TArtifact> {\n artifact: TArtifact\n /** Pass-through for the judge's extra input fields (scenario, signal). */\n [key: string]: unknown\n}\n\nfunction normalizeWeights(weights: BlendWeights): { heldout: number; judge: number } {\n const h = Number.isFinite(weights.heldout) && weights.heldout >= 0 ? weights.heldout : 0\n const j = Number.isFinite(weights.judge) && weights.judge >= 0 ? weights.judge : 0\n const sum = h + j\n if (sum <= 0) {\n throw new ValidationError(\n 'blend weights must have a positive sum (got heldout+judge <= 0) — cannot weight a composite by zero',\n )\n }\n return { heldout: h / sum, judge: j / sum }\n}\n\n/**\n * Compose the PRIMARY hidden-criteria pass rate with the SECONDARY judge\n * composite into the single score the leaderboard ranks on. Weights are\n * renormalized, so a solution that fails the hidden criteria is capped low no\n * matter how the judge felt about its style, while a stylistically-mediocre but\n * CORRECT solution still earns the bulk of the points. Both inputs are clamped\n * to [0,1] — a judge on a non-unit scale must be normalized by the caller first.\n */\nexport function blendHeldout(\n heldoutPassRate: number,\n judgeScore: number,\n weights: BlendWeights = defaultBlendWeights,\n): number {\n const w = normalizeWeights(weights)\n const heldout = clampUnit(heldoutPassRate)\n const judge = clampUnit(judgeScore)\n return w.heldout * heldout + w.judge * judge\n}\n\n/**\n * Wrap a judge's `score` so the `composite` it REPORTS is the held-out-weighted\n * blend. The judge still scores its quality dimensions (recorded, secondary),\n * but the composite that downstream selection/scorecard reads becomes\n * `blendHeldout(heldoutPassRate(artifact), judgeComposite, weights)`. The held-\n * out pass rate is read off the artifact via `heldoutPassRate` — already\n * computed before the judge runs — so no second grading pass is needed.\n *\n * Generic over the artifact type, inferred from `heldoutPassRate`, so it\n * composes with both a `campaign` `JudgeConfig.score` and a bare scoring\n * function. The input is the judge's `{ artifact, ... }` — any extra fields\n * (`scenario`, `signal`) ride through untouched via the index signature.\n */\nexport function withHeldoutBlend<TArtifact>(\n score: (input: JudgeScoreInput<TArtifact>) => JudgeScore | Promise<JudgeScore>,\n heldoutPassRate: (artifact: TArtifact) => number,\n weights: BlendWeights = defaultBlendWeights,\n): (input: JudgeScoreInput<TArtifact>) => Promise<JudgeScore> {\n return async (input: JudgeScoreInput<TArtifact>): Promise<JudgeScore> => {\n const base = await score(input)\n if (base.failed) return base\n const rate = clampUnit(heldoutPassRate(input.artifact))\n const composite = blendHeldout(rate, base.composite, weights)\n const w = normalizeWeights(weights)\n return {\n ...base,\n composite,\n notes:\n `composite=${composite.toFixed(3)} ` +\n `(held-out ${(rate * 100).toFixed(0)}% × ${w.heldout.toFixed(2)} + ` +\n `quality ${base.composite.toFixed(3)} × ${w.judge.toFixed(2)})` +\n (base.notes ? ` — ${base.notes}` : ''),\n }\n }\n}\n\nfunction clampUnit(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n","/**\n * Single-backend guard: assert the agent and the rubric judge run through the\n * SAME backend config, so the judge can't silently re-route through a\n * different (often paid) backend than the agent.\n *\n * The bug class: a consumer rewires the agent onto one backend but leaves the\n * judge bound to another. Cost is billed against the second backend, the eval\n * reports the first backend's model, and the data is unusable.\n * Four consumers hand-roll this comparison (legal at `canonical.ts:702-795`);\n * this is the one substrate copy.\n *\n * Complements `assertRealBackend` (records → stub vs real) and\n * `assertCrossFamily` (judge-ensemble family diversity): this one compares two\n * backend *configs* before the run.\n */\n\nimport { AgentEvalError } from '../errors'\n\n/**\n * Minimal backend-config shape the assertion reads. Consumers may pass richer\n * types — only these five fields are inspected.\n */\nexport interface BackendDescriptor {\n /** Backend route — e.g. `'tcloud' | 'cli-bridge' | 'sandbox' | 'direct-provider'`;\n * free-form for consumer extensibility. */\n kind: string\n /** Resolved base URL. Compared lexically (trailing slash stripped). */\n baseUrl: string\n /** Model id (with snapshot suffix). Compared lexically. */\n model: string\n /** Optional provider override. Compared when both set; flagged when only\n * one side sets it. */\n provider?: string\n /** Bearer token. Values are NEVER compared (security) — only that EITHER\n * both are set OR both are empty. Mismatched presence is a divergence. */\n apiKey?: string\n}\n\nexport interface AssertSingleBackendOptions {\n /** When true, ANY field divergence fails. When false (default), only\n * `kind` / `baseUrl` / `provider` / `apiKeyPresence` divergence throws —\n * a different judge `model` on the same route is allowed (the legal\n * pattern: a cheaper judge model). */\n strict?: boolean\n agentLabel?: string\n judgeLabel?: string\n}\n\nexport type SingleBackendField = 'kind' | 'baseUrl' | 'model' | 'provider' | 'apiKeyPresence'\n\nexport interface SingleBackendDivergence {\n field: SingleBackendField\n agent: string | undefined\n judge: string | undefined\n}\n\nexport interface SingleBackendReport {\n /** True when agent + judge agree per the configured strictness. */\n ok: boolean\n /** Every divergence detected (includes `model` even when non-blocking). */\n divergences: ReadonlyArray<SingleBackendDivergence>\n}\n\nexport class SingleBackendError extends AgentEvalError {\n constructor(\n message: string,\n public readonly report: SingleBackendReport,\n ) {\n super('backend_integrity', message)\n this.name = 'SingleBackendError'\n }\n}\n\nfunction stripSlash(url: string): string {\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Throw `SingleBackendError` when the agent and judge backends diverge in a\n * way that would re-route the judge through a different backend than the\n * agent. Returns the report so callers can log it in either case.\n */\nexport function assertSingleBackend(\n agent: BackendDescriptor,\n judge: BackendDescriptor,\n opts: AssertSingleBackendOptions = {},\n): SingleBackendReport {\n const divergences: SingleBackendDivergence[] = []\n\n if (agent.kind !== judge.kind) {\n divergences.push({ field: 'kind', agent: agent.kind, judge: judge.kind })\n }\n if (stripSlash(agent.baseUrl) !== stripSlash(judge.baseUrl)) {\n divergences.push({ field: 'baseUrl', agent: agent.baseUrl, judge: judge.baseUrl })\n }\n if (agent.model !== judge.model) {\n divergences.push({ field: 'model', agent: agent.model, judge: judge.model })\n }\n // provider: compare when both set; flag when exactly one is set.\n if (agent.provider !== judge.provider) {\n divergences.push({ field: 'provider', agent: agent.provider, judge: judge.provider })\n }\n // apiKey: presence only, never the value.\n const agentHasKey = Boolean(agent.apiKey)\n const judgeHasKey = Boolean(judge.apiKey)\n if (agentHasKey !== judgeHasKey) {\n divergences.push({\n field: 'apiKeyPresence',\n agent: agentHasKey ? 'set' : 'empty',\n judge: judgeHasKey ? 'set' : 'empty',\n })\n }\n\n const blocking = opts.strict ? divergences : divergences.filter((d) => d.field !== 'model')\n const ok = blocking.length === 0\n const report: SingleBackendReport = { ok, divergences }\n\n if (!ok) {\n const agentLabel = opts.agentLabel ?? 'agent'\n const judgeLabel = opts.judgeLabel ?? 'judge'\n const detail = blocking\n .map((d) => `${d.field}: ${agentLabel}=${d.agent ?? '∅'} vs ${judgeLabel}=${d.judge ?? '∅'}`)\n .join('; ')\n throw new SingleBackendError(\n `single-backend: ${agentLabel} and ${judgeLabel} backends diverge — the judge would ` +\n `re-route through a different backend than the agent (${detail})`,\n report,\n )\n }\n\n return report\n}\n","/**\n * Intent-match judge — \"did the agent build the right APP, ignoring\n * whether every feature is wired up?\"\n *\n * Distinct from {@link runSemanticConceptJudge} which scores per-concept\n * presence. The semantic judge can return 0/4 concepts present even\n * when the agent built a thoughtful, polished, on-brief app that just\n * lacks one or two features. The semantic judge can also return 4/4\n * present even when the agent shipped the wrong project (keyword-rich\n * stub).\n *\n * Intent-match asks ONE question:\n * \"Looking at the agent's work as a whole — independent of feature\n * coverage — is this an honest attempt at the user's request?\"\n *\n * Returns a 0–1 score and a 1-sentence evidence string. Use as a sanity\n * check on `completenessScore`-style metrics: if intent-match is high\n * and concept count is low, the agent built the right thing but is\n * missing features (ship and iterate). If intent-match is low, the\n * agent built the wrong thing (reject regardless of concept count).\n *\n * Soft-fails on LLM/JSON error (`available: false`) so callers can\n * treat failure as \"judge skipped.\"\n */\n\nimport type { ChatClient } from './analyst/chat-client'\nimport { paidJsonChat } from './chat-json-call'\nimport {\n CostLedger,\n type CostLedgerHandle,\n type CostReceipt,\n type CustomTokenPricing,\n} from './cost-ledger'\nimport type { LlmCallRequest } from './llm-client'\n\nexport const INTENT_MATCH_JUDGE_VERSION = 'intent-match-judge-v1-2026-04-24'\n\nexport interface IntentMatchInput {\n /** The full natural-language prompt the agent was handed. */\n userRequest: string\n /** Top-level source files from the agent's workdir. */\n sourceFiles: Array<{ path: string; content: string }>\n /** Rendered HTML the preview returned, when available. */\n servedHtml?: string\n /** Optional metadata to inject (id, vertical, difficulty). */\n artifactLabel?: string\n artifactDescription?: string\n}\n\nexport interface IntentMatchResult {\n kind: 'intent-match'\n version: string\n /** 0..1 — 1 = unmistakably the right app, 0 = unrelated to the brief. */\n score: number\n /** One-sentence rationale citing concrete evidence (file or HTML). */\n evidence: string\n durationMs: number\n costUsd: number | null\n available: boolean\n error?: string\n}\n\nexport interface IntentMatchOptions {\n /** Caller-owned transport. Required: agent-eval executes no paid model. */\n chat: ChatClient\n model?: string\n timeoutMs?: number\n maxTokens?: number\n maxSourceChars?: number\n maxPerFileChars?: number\n maxHtmlChars?: number\n /** Endpoint rates used when the transport reports no billed amount. */\n pricing?: CustomTokenPricing\n costLedger?: CostLedgerHandle\n costPhase?: string\n costTags?: Record<string, string>\n signal?: AbortSignal\n}\n\nconst DEFAULT_MODEL = 'claude-sonnet-4-6'\nconst DEFAULT_TIMEOUT = 300_000\nconst DEFAULT_MAX_TOKENS = 800\nconst DEFAULT_MAX_SOURCE = 25_000\nconst DEFAULT_MAX_PER_FILE = 12_000\nconst DEFAULT_MAX_HTML = 20_000\n\nconst INTENT_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n required: ['score', 'evidence'],\n properties: {\n score: { type: 'number', minimum: 0, maximum: 1 },\n evidence: { type: 'string', minLength: 10, maxLength: 400 },\n },\n}\n\nfunction truncate(body: string, cap: number, label: string): string {\n if (body.length <= cap) return body\n return `${body.slice(0, cap)}\\n… [truncated ${body.length - cap} chars of ${label}]`\n}\n\nfunction buildPrompt(\n input: IntentMatchInput,\n opts: { maxPerFileChars: number; maxSourceChars: number; maxHtmlChars: number },\n): string {\n const sourceBlob = input.sourceFiles\n .filter((f) => f.content.length <= opts.maxPerFileChars)\n .map((f) => `--- FILE: ${f.path} ---\\n${f.content}`)\n .join('\\n\\n')\n const html = input.servedHtml ?? ''\n\n return `You are evaluating whether an agent built THE RIGHT APP for a user request.\n\nYou are NOT scoring feature coverage. You are NOT scoring code quality.\nYou are answering ONE question: when a person looks at this work, do they\nsee an honest attempt at the user's request — or do they see the wrong\nproject entirely?\n\nUSER REQUEST:\n${input.userRequest}\n\n${input.artifactLabel ? `ARTIFACT METADATA:\\n name: ${input.artifactLabel}\\n description: ${input.artifactDescription ?? ''}\\n\\n` : ''}${html ? `SERVED HTML (what the preview returns):\\n${truncate(html, opts.maxHtmlChars, 'HTML')}\\n\\n` : ''}SOURCE FILES (the agent's workdir):\n${truncate(sourceBlob, opts.maxSourceChars, 'source')}\n\nScore 0–1:\n 1.0 — unmistakably the right app. Even with bugs, gaps, or missing\n features, a reviewer would say \"yes, this is what was asked for.\"\n 0.7 — recognizable. Domain matches; some required surface areas exist.\n A reviewer would say \"right direction, lots of work needed.\"\n 0.4 — partially related. Wrong framing or wrong product entirely but\n with some shared keywords or a tangential overlap.\n 0.0 — wrong project. The agent shipped something unrelated to the\n request (e.g. asked for an NFT mint page, shipped a generic\n landing page with zero NFT-related code).\n\nEvidence: one sentence citing the strongest concrete signal — a file\nname, a route, a rendered headline, a missing core surface. Don't\nrestate the request.\n\nExamples:\n - \"src/App.tsx renders <MintWidget /> with mint-1/mint-5 buttons and\n wagmi imports — clearly the requested NFT mint page.\" → 0.95\n - \"src/App.tsx is the default Vite React template; no\n mint/wallet/contract code in any file under src/.\" → 0.05\n\nReturn STRICT JSON. No prose outside.`\n}\n\n/**\n * Run the intent-match judge. Soft-fails to available=false on error.\n */\nexport async function runIntentMatchJudge(\n input: IntentMatchInput,\n options: IntentMatchOptions,\n): Promise<IntentMatchResult> {\n const start = Date.now()\n const opts = {\n chat: options.chat,\n model: options.model ?? options.chat.defaultModel ?? DEFAULT_MODEL,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT,\n maxTokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,\n maxSourceChars: options.maxSourceChars ?? DEFAULT_MAX_SOURCE,\n maxPerFileChars: options.maxPerFileChars ?? DEFAULT_MAX_PER_FILE,\n maxHtmlChars: options.maxHtmlChars ?? DEFAULT_MAX_HTML,\n ...(options.pricing ? { pricing: options.pricing } : {}),\n costLedger: options.costLedger ?? new CostLedger(),\n costPhase: options.costPhase ?? 'judge.intent-match',\n costTags: options.costTags ?? {},\n signal: options.signal ?? new AbortController().signal,\n }\n\n if (input.sourceFiles.length === 0 && !input.servedHtml) {\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: 0,\n evidence: 'no source files and no served HTML — nothing to evaluate',\n durationMs: 0,\n costUsd: null,\n available: false,\n error: 'no input artifact',\n }\n }\n\n let receipt: CostReceipt | undefined\n try {\n const request = {\n model: opts.model,\n messages: [\n {\n role: 'system' as const,\n content:\n 'You are a holistic code reviewer answering one question: did the agent build the right app for the user. Return strict JSON. No prose outside.',\n },\n { role: 'user' as const, content: buildPrompt(input, opts) },\n ],\n jsonSchema: { name: 'intent_match_judge', schema: INTENT_SCHEMA },\n temperature: 0,\n maxTokens: opts.maxTokens,\n timeoutMs: opts.timeoutMs,\n } satisfies LlmCallRequest\n const paid = await paidJsonChat<{ score: number; evidence: string }>({\n chat: opts.chat,\n request,\n ledger: opts.costLedger,\n channel: 'judge',\n phase: opts.costPhase,\n actor: 'intent-match',\n tags: opts.costTags,\n signal: opts.signal,\n ...(opts.pricing ? { pricing: opts.pricing } : {}),\n })\n receipt = paid.receipt\n if (!paid.succeeded) throw paid.error\n const { value } = paid\n\n const score = Math.max(0, Math.min(1, Number(value?.score ?? 0)))\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: Number(score.toFixed(3)),\n evidence: String(value?.evidence ?? '').slice(0, 400),\n durationMs: Date.now() - start,\n costUsd: paid.receipt.costUnknown ? null : paid.receipt.costUsd,\n available: true,\n }\n } catch (err) {\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: 0,\n evidence: '',\n durationMs: Date.now() - start,\n costUsd: receipt && !receipt.costUnknown ? receipt.costUsd : null,\n available: false,\n error: err instanceof Error ? err.message : String(err),\n }\n }\n}\n\n/**\n * Factory: pin the transport and options once, return a closure.\n */\nexport function createIntentMatchJudge(\n options: IntentMatchOptions,\n): (input: IntentMatchInput) => Promise<IntentMatchResult> {\n return (input) => runIntentMatchJudge(input, options)\n}\n","/**\n * Judge-ensemble reducer — folds N independent judge verdicts on the same\n * artifact into one aggregate score.\n *\n * The pattern every multi-model judge re-implements: run K uncorrelated judges\n * (different model families remove within-family bias), then reduce their\n * per-dimension verdicts to a single composite + an inter-rater disagreement\n * signal. This is the pure reduction — no LLM, no I/O — so a lift it produces\n * is attributable to the scores, not to where they came from.\n *\n * Fail-loud: a judge that errored or returned malformed output is recorded in\n * `failedJudges` with `perDimension: null`, never folded into a zero. If EVERY\n * judge failed the reducer throws — a silent zero here would corrupt the result.\n */\n\nimport type { LlmUsage } from './llm-client'\nimport { clamp01 } from './run-score'\nimport { weightedComposite } from './statistics'\n\n/** One judge's verdict. `perDimension: null` ⇒ that judge call failed (threw or\n * returned malformed output) — recorded, never folded into a zero. */\nexport interface JudgeVerdict<D extends string = string> {\n /** Judge identity (typically the model id) — the `perJudge` / `failedJudges` key. */\n model: string\n /** Per-dimension scores, or `null` when the judge failed. */\n perDimension: Record<D, number> | null\n /** Optional one-line rationale; the first non-empty one becomes the aggregate's. */\n rationale?: string\n /** Optional reported cost, committed by the caller's CostLedger. */\n costUsd?: number\n /** Optional provider usage, committed by the caller's CostLedger. */\n usage?: LlmUsage\n /** Optional per-dimension reasoning/evidence. Carried through to\n * `EnsembleAggregate.verdicts` verbatim — never folded into the math. */\n detail?: Partial<Record<D, { reasoning?: string; evidence?: string }>>\n}\n\n/** The aggregated ensemble result. */\nexport interface EnsembleAggregate<D extends string = string> {\n /** Mean over SURVIVING judges, per dimension (absent-everywhere ⇒ 0). */\n perDimension: Record<D, number>\n /** Weighted mean of `perDimension` (uniform unless `weights` given). */\n composite: number\n /** Each surviving judge's clamped per-dimension scores, for trace drill-down. */\n perJudge: Record<string, Record<D, number>>\n /** Max over dimensions of (max − min) across survivors — the inter-rater signal. */\n maxDisagreement: number\n /** Models whose verdict was null (failed). */\n failedJudges: string[]\n /** First non-empty survivor rationale, or `'llm-judge'`. */\n rationale: string\n /** The input verdicts, verbatim — drill-down to raw scores, `detail`\n * reasoning/evidence, and per-verdict cost without re-running judges. */\n verdicts: JudgeVerdict<D>[]\n}\n\n/**\n * Reduce per-judge verdicts to one aggregate. Generic over the rubric: pass the\n * stable-ordered `dimensionKeys` the judges scored.\n *\n * - Per-dimension score = mean over surviving judges (out-of-range clamped to [0,1]).\n * - `composite` = `weightedComposite` of `perDimension`. No `weights` ⇒ uniform\n * over every dimension. A partial `weights` map selects AND weights exactly the\n * named dimensions (others excluded from the composite) — the substrate's\n * sum-normalized weighting, not re-implemented here.\n * - Throws if `verdicts` or `dimensionKeys` is empty, or if every judge failed.\n */\nexport function aggregateJudgeVerdicts<D extends string>(\n verdicts: readonly JudgeVerdict<D>[],\n dimensionKeys: readonly D[],\n weights?: Partial<Record<D, number>>,\n): EnsembleAggregate<D> {\n if (verdicts.length === 0) {\n throw new Error('aggregateJudgeVerdicts: no verdicts to aggregate')\n }\n if (dimensionKeys.length === 0) {\n throw new Error('aggregateJudgeVerdicts: dimensionKeys is empty')\n }\n\n const perJudge: Record<string, Record<D, number>> = {}\n const failedJudges: string[] = []\n const dimAcc = {} as Record<D, number[]>\n for (const d of dimensionKeys) dimAcc[d] = []\n let rationale = ''\n\n // Same model sampled k times (best-of-N judging) gets keys 'm', 'm#2',\n // 'm#3'… so repeat votes land as distinct perJudge/failedJudges entries\n // instead of overwriting each other.\n const seenCount = new Map<string, number>()\n const keyFor = (model: string): string => {\n const n = (seenCount.get(model) ?? 0) + 1\n seenCount.set(model, n)\n return n === 1 ? model : `${model}#${n}`\n }\n\n for (const v of verdicts) {\n const key = keyFor(v.model)\n if (!v.perDimension) {\n failedJudges.push(key)\n continue\n }\n const dims = {} as Record<D, number>\n for (const d of dimensionKeys) dims[d] = clamp01(Number(v.perDimension[d]))\n perJudge[key] = dims\n for (const d of dimensionKeys) dimAcc[d].push(dims[d])\n if (!rationale && typeof v.rationale === 'string' && v.rationale) rationale = v.rationale\n }\n\n if (failedJudges.length === verdicts.length) {\n throw new Error(`aggregateJudgeVerdicts: all ${verdicts.length} judges failed`)\n }\n\n const perDimension = {} as Record<D, number>\n for (const d of dimensionKeys) {\n const vals = dimAcc[d]\n perDimension[d] = vals.length === 0 ? 0 : vals.reduce((s, x) => s + x, 0) / vals.length\n }\n\n let maxDisagreement = 0\n for (const d of dimensionKeys) {\n const vals = dimAcc[d]\n if (vals.length < 2) continue\n const spread = Math.max(...vals) - Math.min(...vals)\n if (spread > maxDisagreement) maxDisagreement = spread\n }\n\n const w: Record<string, number> = {}\n if (weights) {\n for (const [d, weight] of Object.entries(weights)) {\n if (weight !== undefined) w[d] = weight as number\n }\n } else {\n for (const d of dimensionKeys) w[d] = 1 / dimensionKeys.length\n }\n const composite = weightedComposite({ dims: perDimension, weights: w }).composite\n\n return {\n perDimension,\n composite,\n perJudge,\n maxDisagreement,\n failedJudges,\n rationale: rationale || 'llm-judge',\n verdicts: [...verdicts],\n }\n}\n","/**\n * Wrap a single judge LLM call with retry, optional fallback-model\n * rotation, exponential backoff, and a typed `JudgeRetryOutcome`. Callers\n * MUST inspect `succeeded` before using `value`; on failure the library\n * returns `value: null` rather than substituting a default, so a judge\n * abort cannot silently corrupt a downstream composite.\n *\n * Reporting contract: callers ship `TrialResult.judgeSucceeded = succeeded`\n * and `TrialResult.judgeAttempts = attempts` so `aggregateTrialsByMode`\n * with `mode: 'exclude-failed'` drops the trial.\n */\n\nimport { backoffMs, isTransientLlmError } from './llm-client'\n\n/** Retry policy for judge LLM calls. */\nexport interface JudgeRetryPolicy {\n /** Max attempts per model. Default 3 (one initial + two retries). */\n maxAttempts?: number\n /** Per-attempt timeout in ms. Default 300_000. */\n timeoutMs?: number\n /**\n * Models to try, in order. The first model is the primary; subsequent\n * models are fallbacks invoked only when ALL retries on the previous\n * model have been exhausted. Example: `['claude-code/sonnet', 'kimi-code/k2p6']`\n * runs claude-code up to maxAttempts times, then falls back to kimi.\n * If omitted, the caller's judge function controls model selection and\n * the retries apply to that single model.\n */\n models?: readonly string[]\n /** Exponential backoff function, default `attempt → min(500 * 2^attempt, 16_000)`. */\n backoffMs?: (attempt: number) => number\n /**\n * Predicate deciding whether an error should trigger a retry. Defaults to\n * `isTransientLlmError` — the package-wide classifier shared with\n * `callLlm` — which retries aborts/timeouts, network faults, HTTP/2\n * transport faults, and any `LlmCallError` with status in {429,502,503,504}.\n * JSON-parse and schema-rejection errors are NOT retriable (the model\n * needs prompt adjustment, not another shot).\n */\n isRetryable?: (err: unknown) => boolean\n}\n\n/** Outcome of a wrapped judge invocation. */\nexport interface JudgeRetryOutcome<T> {\n /** The judge's returned value when `succeeded === true`. */\n value: T | null\n /** True iff one of the attempts completed without throwing. */\n succeeded: boolean\n /** Total attempts made across all models. */\n attempts: number\n /** Which model the successful attempt used (when succeeded). */\n modelUsed?: string\n /** Last error captured when `succeeded === false`. */\n error?: Error\n /** Per-attempt error log for forensics. */\n attemptErrors: Array<{ attempt: number; model: string; error: string }>\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 3\nconst DEFAULT_TIMEOUT_MS = 300_000\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Wrap a judge call with retry + fallback-model + typed outcome semantics.\n *\n * The `judgeFn` signature is `(model: string, signal: AbortSignal) => Promise<T>`.\n * The signal will be aborted at `timeoutMs`. Callers should pass the signal\n * to their underlying fetch/SDK call so the abort actually fires.\n *\n * Returns a typed outcome — callers MUST inspect `succeeded` before using\n * `value`. The library refuses to default to a silent zero score because a\n * synthetic zero is indistinguishable from a real low score downstream.\n */\nexport async function withJudgeRetry<T>(\n judgeFn: (model: string, signal: AbortSignal) => Promise<T>,\n policy: JudgeRetryPolicy = {},\n): Promise<JudgeRetryOutcome<T>> {\n const maxAttempts = policy.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n const timeoutMs = policy.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const backoff = policy.backoffMs ?? backoffMs\n const isRetryable = policy.isRetryable ?? isTransientLlmError\n const models =\n policy.models && policy.models.length > 0 ? policy.models : [undefined as unknown as string]\n\n let totalAttempts = 0\n const attemptErrors: JudgeRetryOutcome<T>['attemptErrors'] = []\n let lastError: Error | undefined\n\n for (const model of models) {\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n totalAttempts += 1\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(new Error('TimeoutError')), timeoutMs)\n try {\n const value = await judgeFn(model as string, controller.signal)\n clearTimeout(timer)\n return {\n value,\n succeeded: true,\n attempts: totalAttempts,\n modelUsed: model,\n attemptErrors,\n }\n } catch (err) {\n clearTimeout(timer)\n const errObj = err instanceof Error ? err : new Error(String(err))\n lastError = errObj\n attemptErrors.push({\n attempt: totalAttempts,\n model: model ?? '(default)',\n error: errObj.message,\n })\n if (!isRetryable(errObj)) {\n // Non-retriable (e.g., JSON parse, schema rejection): break out of\n // attempts on this model AND skip the fallback rotation — a\n // permanent error here will be permanent on the fallback too.\n return {\n value: null,\n succeeded: false,\n attempts: totalAttempts,\n error: errObj,\n attemptErrors,\n }\n }\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt))\n }\n }\n }\n // Exhausted attempts on this model — fall through to next model in the\n // rotation (if any). The backoff between MODEL rotations is the same\n // as the last per-attempt backoff (already slept above).\n }\n\n return {\n value: null,\n succeeded: false,\n attempts: totalAttempts,\n error: lastError,\n attemptErrors,\n }\n}\n","/**\n * Multi-model judge panel — `ensembleJudge` builds a campaign `JudgeConfig`\n * that fans one artifact out to K judge models and reduces their verdicts\n * through `aggregateJudgeVerdicts` (src/judge-ensemble.ts).\n *\n * The panel is the fail-loud composition of the substrate's existing judge\n * primitives:\n * - `assertCrossFamily` (construction-time) — a single-family panel is\n * correlated bias, not independent signal.\n * - `withJudgeRetry` (per model, opt-in) — transient-fault retry with a\n * typed outcome; a judge that exhausts retries is recorded as failed,\n * never folded into a zero.\n * - `aggregateJudgeVerdicts` — the pure reducer; throws when EVERY judge\n * failed so a silent zero can't reach the gate.\n *\n * The returned `JudgeScore` is on the campaign [0,1] scale and carries the\n * ensemble extras (`maxDisagreement`, `failedJudges`, `perJudge`) declared\n * on the canonical `JudgeScore` in src/campaign/types.ts.\n */\n\nimport type { JudgeConfig, JudgeScore } from './campaign/types'\nimport {\n CostLedger,\n type CostLedgerHandle,\n type CostReceiptInput,\n type MaximumCharge,\n} from './cost-ledger'\nimport { aggregateJudgeVerdicts, type JudgeVerdict } from './judge-ensemble'\nimport { assertCrossFamily } from './judge-families'\nimport { type JudgeRetryPolicy, withJudgeRetry } from './judge-retry'\nimport { contentHash } from './verdict-cache'\n\nexport interface EnsembleJudgeOptions<D extends string> {\n /** Judge name — becomes the returned `JudgeConfig.name`. */\n name: string\n /** Rubric dimensions every model scores. Keys of the verdict's `perDimension`. */\n dimensions: D[]\n /** Judge model ids — one `scoreWith` call per entry. List a model twice to\n * sample it twice (votes are suffix-keyed `model#2` so none overwrite). */\n models: string[]\n /** Explicit scoring revision for closure state not visible in the static panel config. */\n judgeVersion?: string\n /**\n * Score the artifact with one model. Throw (or reject) on failure — the\n * panel records that model as a failed judge; it is never folded into a\n * zero. Verdict scores are clamped to [0,1] by the reducer.\n */\n scoreWith: (\n model: string,\n input: { artifact: unknown; scenario?: unknown; signal: AbortSignal },\n ) => Promise<JudgeVerdict<D>>\n /** Recover usage from a failed provider response when its error retains one. */\n receiptFromError?: (error: Error, model: string) => CostReceiptInput | undefined\n /** Used by direct score calls; campaigns supply their run ledger in score(). */\n costLedger?: CostLedgerHandle\n /** Required per model when the shared ledger has a dollar cap. */\n maximumCharge?: MaximumCharge | ((model: string) => MaximumCharge)\n /**\n * Per-model retry policy, applied via `withJudgeRetry`. The panel's\n * `models` list drives the fan-out, so `retry.models` (the fallback\n * rotation) is overridden to each panel model in turn.\n */\n retry?: JudgeRetryPolicy\n /** Enforce `assertCrossFamily` over `models` at construction. Default true.\n * Opt out only for deliberate single-family panels (e.g. self-consistency\n * sampling of one model).\n *\n * Construction-time only, over the REQUESTED ids: it cannot see a gateway\n * that answers several ids from one provider. `scoreWith` owns the served\n * side — check the id the provider echoed with `assertServedModel`\n * (./integrity/served-model) inside your judge call. */\n crossFamily?: boolean\n /** Composite weights forwarded to `aggregateJudgeVerdicts`: a partial map\n * selects AND weights exactly the named dimensions. Omit for uniform. */\n weights?: Partial<Record<D, number>>\n}\n\n/**\n * Build a campaign-shaped `JudgeConfig` whose `score()` runs every panel\n * model in parallel and reduces the surviving verdicts to one canonical\n * `JudgeScore` in [0,1].\n *\n * Failure semantics: a model whose `scoreWith` throws (or exhausts `retry`)\n * lands in `failedJudges` and is excluded from the means. When EVERY model\n * fails, `aggregateJudgeVerdicts` throws — the campaign engine records a\n * failed cell instead of averaging a fabricated zero.\n */\nexport function ensembleJudge<D extends string>(\n opts: EnsembleJudgeOptions<D>,\n): JudgeConfig<unknown> {\n if (opts.models.length === 0) {\n throw new Error(`ensembleJudge '${opts.name}': models is empty — nothing to score with`)\n }\n if (opts.dimensions.length === 0) {\n throw new Error(`ensembleJudge '${opts.name}': dimensions is empty — nothing to score`)\n }\n if (opts.crossFamily !== false) {\n assertCrossFamily(opts.models)\n }\n const declaredJudgeVersion = opts.judgeVersion?.trim()\n if (opts.judgeVersion !== undefined && !declaredJudgeVersion) {\n throw new Error(`ensembleJudge '${opts.name}': judgeVersion must be non-empty when provided`)\n }\n const judgeVersion =\n declaredJudgeVersion ??\n contentHash({\n kind: 'ensembleJudge',\n models: opts.models,\n dimensions: opts.dimensions,\n weights: opts.weights ?? null,\n crossFamily: opts.crossFamily ?? true,\n maximumCharge:\n typeof opts.maximumCharge === 'function'\n ? opts.maximumCharge.toString()\n : (opts.maximumCharge ?? null),\n retry: opts.retry\n ? {\n maxAttempts: opts.retry.maxAttempts ?? null,\n timeoutMs: opts.retry.timeoutMs ?? null,\n models: opts.retry.models ?? null,\n backoffMs: opts.retry.backoffMs?.toString() ?? null,\n isRetryable: opts.retry.isRetryable?.toString() ?? null,\n }\n : null,\n scoreWith: opts.scoreWith.toString(),\n })\n const directCostLedger = opts.costLedger ?? new CostLedger()\n\n const scoreOne = async (args: {\n model: string\n artifact: unknown\n scenario?: unknown\n signal: AbortSignal\n costLedger: CostLedgerHandle\n costPhase: string\n costTags?: Record<string, string>\n }): Promise<JudgeVerdict<D>> => {\n const outcome = await withJudgeRetry(\n async (model, retrySignal) => {\n const paid = await args.costLedger.runPaidCall({\n channel: 'judge',\n phase: args.costPhase,\n actor: `${opts.name}.${model}`,\n model,\n maximumCharge:\n typeof opts.maximumCharge === 'function'\n ? opts.maximumCharge(model)\n : opts.maximumCharge,\n tags: args.costTags,\n signal: AbortSignal.any([args.signal, retrySignal]),\n execute: (signal) =>\n opts.scoreWith(model, { artifact: args.artifact, scenario: args.scenario, signal }),\n receipt: (verdict) => {\n const cachedTokens = verdict.usage?.cachedPromptTokens ?? 0\n const usageUnknown = !verdict.usage || verdict.usage.captured === false\n return {\n model: verdict.model,\n inputTokens: Math.max(0, (verdict.usage?.promptTokens ?? 0) - cachedTokens),\n outputTokens: verdict.usage?.completionTokens ?? 0,\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\n usageUnknown,\n ...(verdict.costUsd === undefined ? {} : { actualCostUsd: verdict.costUsd }),\n }\n },\n receiptFromError: (error) => opts.receiptFromError?.(error, model),\n })\n if (!paid.succeeded) throw paid.error\n return paid.value\n },\n opts.retry\n ? { ...opts.retry, models: [args.model] }\n : { maxAttempts: 1, models: [args.model], isRetryable: () => false },\n )\n if (!outcome.succeeded || outcome.value === null) {\n return {\n model: args.model,\n perDimension: null,\n rationale: outcome.error?.message ?? 'judge failed',\n }\n }\n return outcome.value\n }\n\n return {\n name: opts.name,\n dimensions: opts.dimensions.map((d) => ({ key: d, description: d })),\n judgeVersion,\n async score({\n artifact,\n scenario,\n signal,\n costLedger,\n costPhase,\n costTags,\n }): Promise<JudgeScore> {\n const verdicts = await Promise.all(\n opts.models.map((model) =>\n scoreOne({\n model,\n artifact,\n scenario,\n signal,\n costLedger: costLedger ?? directCostLedger,\n costPhase: costPhase ?? 'judge',\n costTags,\n }),\n ),\n )\n // All-failed throws here — propagate so the engine records a failed cell.\n const agg = aggregateJudgeVerdicts(verdicts, opts.dimensions, opts.weights)\n const score: JudgeScore = {\n dimensions: agg.perDimension,\n composite: agg.composite,\n notes: agg.rationale,\n maxDisagreement: agg.maxDisagreement,\n perJudge: agg.perJudge,\n }\n if (agg.failedJudges.length > 0) score.failedJudges = agg.failedJudges\n return score\n },\n }\n}\n","/**\n * Keyword-coverage judge — baseline complement to the semantic concept\n * judge.\n *\n * Where {@link runSemanticConceptJudge} uses an LLM to read source code\n * and decide whether a concept is REALLY implemented (not just\n * keyword-mentioned), this judge does the cheap, deterministic version:\n * fetch the served preview, concatenate every linked CSS/JS asset, and\n * substring-match each expected concept's keywords against the\n * concatenated haystack. Optional `requiredElement` selector adds a\n * structural gate so \"supply counter\" can require an actual `<input>` or\n * `<table>`, not just a comment containing the word.\n *\n * Use both judges. Keyword coverage is a fast 0-cost gate — a stub page\n * with the right keywords passes here, fails the semantic judge. Score\n * divergence between the two is itself a signal: high keyword coverage\n * + low semantic = \"the agent slapped the right words on the right\n * scaffold but didn't wire any of it up.\"\n *\n * Pure functions, soft-fail on fetch error, no LLM dependency.\n */\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface KeywordConceptSpec {\n name: string\n keywords: string[]\n /**\n * Optional CSS selector that must match in the HTML for the concept\n * to count as present. Tiny subset:\n * - `tag` (e.g. `form`)\n * - `tag[attr=\"value\"]` (e.g. `input[type=\"number\"]`)\n * - `tag[attr]` (presence only)\n * Anything more complex is rejected with `null` (treated as\n * \"unenforced\", not \"failed\").\n */\n requiredElement?: string\n}\n\nexport interface KeywordCoverageFinding {\n concept: string\n found: boolean\n matchedKeywords: string[]\n /** True iff the optional requiredElement selector matched; null when no selector. */\n requiredElementPresent: boolean | null\n}\n\nexport interface KeywordCoverageResult {\n /** 0..1 share of concepts satisfied. */\n score: number\n presentCount: number\n totalCount: number\n findings: KeywordCoverageFinding[]\n durationMs: number\n /** Total bytes assembled across html + linked assets. */\n totalAssembledBytes: number\n /** Soft-failure reason if the audit couldn't run. */\n error?: string\n}\n\nexport interface KeywordCoverageOptions {\n /** Override fetch implementation — for tests. */\n fetch?: typeof fetch\n /** Per-asset fetch timeout (default 3s). */\n assetTimeoutMs?: number\n /** Initial-HTML fetch timeout (default 5s). */\n htmlTimeoutMs?: number\n}\n\n// ─── Selector matcher ──────────────────────────────────────────────────\n\n/**\n * Element-presence check using a tiny CSS-selector subset. Returns\n * null when the selector isn't supported — caller treats that as\n * \"unenforced\" rather than \"failed.\"\n */\nexport function htmlContainsElement(html: string, selector: string): boolean | null {\n const tagOnly = /^([a-zA-Z][\\w-]*)$/.exec(selector)\n if (tagOnly) {\n const re = new RegExp(`<${tagOnly[1]}\\\\b`, 'i')\n return re.test(html)\n }\n const tagAttrEq = /^([a-zA-Z][\\w-]*)\\[([\\w-]+)\\s*=\\s*[\"']?([^\"'\\]]+)[\"']?\\]$/.exec(selector)\n if (tagAttrEq) {\n const [, tag, attr, value] = tagAttrEq\n const re = new RegExp(\n `<${tag}\\\\b[^>]*\\\\b${attr}\\\\s*=\\\\s*[\"']${value!.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\"']`,\n 'i',\n )\n return re.test(html)\n }\n const tagAttrPresence = /^([a-zA-Z][\\w-]*)\\[([\\w-]+)\\]$/.exec(selector)\n if (tagAttrPresence) {\n const [, tag, attr] = tagAttrPresence\n const re = new RegExp(`<${tag}\\\\b[^>]*\\\\b${attr}\\\\b`, 'i')\n return re.test(html)\n }\n return null\n}\n\n// ─── Asset extraction ─────────────────────────────────────────────────\n\n/**\n * Pull every `<link rel=stylesheet href>` and `<script src>` from a\n * raw HTML body. Returns absolute URLs resolved against `baseUrl`.\n * Permissive regex — agent-authored markup doesn't always quote\n * attributes the same way.\n */\nexport function extractAssetUrls(html: string, baseUrl: string): string[] {\n const urls = new Set<string>()\n const linkRe = /<link\\b[^>]*\\bhref\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi\n const scriptRe = /<script\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi\n for (const re of [linkRe, scriptRe]) {\n let match: RegExpExecArray | null = re.exec(html)\n while (match !== null) {\n const raw = match[1]!\n try {\n urls.add(new URL(raw, baseUrl).toString())\n } catch {\n // unresolvable refs (e.g. data: URLs) — skip\n }\n match = re.exec(html)\n }\n }\n return Array.from(urls)\n}\n\n// ─── Coverage scorer ──────────────────────────────────────────────────\n\n/**\n * Score expected concepts against an already-fetched HTML payload + any\n * pre-fetched CSS/JS assets. Use when the runner has the bytes in hand\n * and doesn't want a fresh HTTP round-trip — e.g. sandbox runtime where\n * the preview content was fetched via curl from inside the container.\n */\nexport function runKeywordCoverageJudge(\n html: string,\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n assets: ReadonlyArray<string> = [],\n): KeywordCoverageResult {\n const start = Date.now()\n if (expectedConcepts.length === 0) {\n return {\n score: 0,\n presentCount: 0,\n totalCount: 0,\n findings: [],\n durationMs: 0,\n totalAssembledBytes: 0,\n }\n }\n const haystack = `${html}\\n${assets.join('\\n')}`.toLowerCase()\n const findings: KeywordCoverageFinding[] = expectedConcepts.map((concept) => {\n const matchedKeywords: string[] = []\n for (const kw of concept.keywords) {\n if (haystack.includes(kw.toLowerCase())) matchedKeywords.push(kw)\n }\n const requiredElementPresent = concept.requiredElement\n ? htmlContainsElement(html, concept.requiredElement)\n : null\n const passesElementGate = requiredElementPresent === null || requiredElementPresent === true\n const found = matchedKeywords.length > 0 && passesElementGate\n return { concept: concept.name, found, matchedKeywords, requiredElementPresent }\n })\n const presentCount = findings.filter((f) => f.found).length\n return {\n score: presentCount / expectedConcepts.length,\n presentCount,\n totalCount: expectedConcepts.length,\n findings,\n durationMs: Date.now() - start,\n totalAssembledBytes: haystack.length,\n }\n}\n\n/**\n * URL-fetch flavor — GET the preview, parallel-fetch every linked\n * stylesheet + script (with bounded timeouts, soft-fail individually),\n * then score via {@link runKeywordCoverageJudge}.\n */\nexport async function runKeywordCoverageJudgeUrl(\n previewUrl: string,\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n options: KeywordCoverageOptions = {},\n): Promise<KeywordCoverageResult> {\n const start = Date.now()\n const fetchFn = options.fetch ?? globalThis.fetch\n const htmlTimeout = options.htmlTimeoutMs ?? 5_000\n const assetTimeout = options.assetTimeoutMs ?? 3_000\n\n if (expectedConcepts.length === 0) {\n return {\n score: 0,\n presentCount: 0,\n totalCount: 0,\n findings: [],\n durationMs: 0,\n totalAssembledBytes: 0,\n }\n }\n\n let html = ''\n try {\n const resp = await fetchFn(previewUrl, {\n redirect: 'follow',\n signal: AbortSignal.timeout(htmlTimeout),\n })\n if (!resp.ok) {\n return softFail(expectedConcepts, start, `preview HTTP ${resp.status}`)\n }\n html = await resp.text()\n } catch (err) {\n return softFail(expectedConcepts, start, err instanceof Error ? err.message : String(err))\n }\n\n const assetUrls = extractAssetUrls(html, previewUrl)\n const assetBodies = await Promise.all(\n assetUrls.map(async (u) => {\n try {\n const r = await fetchFn(u, {\n redirect: 'follow',\n signal: AbortSignal.timeout(assetTimeout),\n })\n if (!r.ok) return ''\n return await r.text()\n } catch {\n return ''\n }\n }),\n )\n\n return runKeywordCoverageJudge(html, expectedConcepts, assetBodies)\n}\n\nfunction softFail(\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n start: number,\n error: string,\n): KeywordCoverageResult {\n return {\n score: 0,\n presentCount: 0,\n totalCount: expectedConcepts.length,\n findings: expectedConcepts.map((c) => ({\n concept: c.name,\n found: false,\n matchedKeywords: [],\n requiredElementPresent: null,\n })),\n durationMs: Date.now() - start,\n totalAssembledBytes: 0,\n error,\n }\n}\n","/**\n * Multi-layer verifier — ordered pipeline of verification layers.\n *\n * A DAG of layers (install → typecheck → build → lint → serve → semantic → …)\n * with dependency-based skip, per-layer findings, soft-fail semantics, and an\n * aggregated `blendedScore` across all passed layers.\n *\n * Use when you want:\n * - ordered stages where a failing upstream stage skips downstream ones\n * - each stage produces rich `findings` (severity + message + evidence)\n * - a single composite score across stages with per-stage weights\n * - soft-fail stages whose failure doesn't abort the pipeline\n *\n * A layer body is an arbitrary async function, so independent checks that need\n * no ordering run as one layer that resolves them in parallel.\n */\n\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport type LayerStatus = 'pass' | 'fail' | 'skipped' | 'error' | 'timeout'\n\nexport type Severity = 'critical' | 'major' | 'minor' | 'info'\n\nexport interface Finding {\n severity: Severity\n message: string\n evidence?: string\n /** Optional layer name the finding belongs to (set by the verifier if omitted). */\n layer?: string\n /**\n * Free-form structured payload — a layer attaches its toolchain\n * (`{ adapter: 'pnpm' }`), a judge attaches evidence pointers, etc.\n * Renderers MAY interrogate; agent-eval primitives never assume shape.\n */\n detail?: Record<string, unknown>\n}\n\nexport interface LayerResult {\n layer: string\n status: LayerStatus\n /** Origin of an `error` or `timeout`. Defaults to `execution`. */\n errorSource?: 'execution' | 'judge'\n /** 0..1 score, optional — layers that don't produce a numeric score omit. */\n score?: number\n durationMs: number\n findings: Finding[]\n /** Short human-readable summary (one line). */\n reason?: string\n /**\n * Numeric layer-level diagnostics: error counts, warning counts,\n * cyclomatic complexity, total adapter wall-time, etc. Keyed by\n * diagnostic name; null = \"diagnostic not applicable / not measured.\"\n * Renderers that know the keys can display them; ones that don't,\n * ignore. Free-form on purpose — consumers type the value shape in\n * their own namespace.\n */\n diagnostics?: Record<string, number | null>\n /** Any rich per-layer detail — rendered as-is by consumers that know the layer. */\n detail?: Record<string, unknown>\n}\n\nexport interface VerifyContext<Env = unknown> {\n /** Per-run opaque context the caller provides. Layers destructure what they need. */\n env: Env\n /** Previously-computed results from layers that already ran. */\n prior: Record<string, LayerResult>\n /** Signal — if aborted, layers MUST bail within reasonable wall. */\n signal: AbortSignal\n}\n\nexport interface Layer<Env = unknown> {\n name: string\n /** Origin assigned when this layer errors or times out. Defaults to `execution`. */\n errorSource?: 'execution' | 'judge'\n /** Stages that must have `status: 'pass'` before this layer runs. */\n dependsOn?: string[]\n /**\n * Weight in the composite `blendedScore`. Default 1.0. Layers with weight 0\n * contribute findings but not score.\n */\n weight?: number\n /**\n * If true, a `fail` status contributes to `blendedScore` (as 0) instead of\n * being dropped — use for layers whose failure is a real signal. Default:\n * fail drops from numerator + denominator, matching VB's existing semantics.\n */\n failContributesToScore?: boolean\n /** Optional per-layer wall-cap in ms. Honored by the verifier (AbortSignal). */\n capMs?: number\n run: (ctx: VerifyContext<Env>) => Promise<LayerResult> | LayerResult\n}\n\nexport interface VerifyOptions<Env = unknown> {\n env: Env\n /**\n * Overall wall cap. Default: sum of layer capMs, or Infinity if any layer\n * omits a cap. The verifier short-circuits remaining layers on overall cap.\n */\n overallCapMs?: number\n /** Called with each layer result as it completes. */\n onLayer?: (result: LayerResult) => void\n}\n\n/** Extends the substrate verdict spine: `valid` = `allPass`; `score` is the\n * complete task score or 0 when the configured scoring panel was incomplete. */\nexport interface VerificationReport extends DefaultVerdict {\n layers: LayerResult[]\n passCount: number\n failCount: number\n skippedCount: number\n errorCount: number\n /** True iff the configured scoring panel completed and every layer passed. */\n allPass: boolean\n /**\n * Diagnostic weighted mean across contributing layers. This may represent a\n * partial panel. It is 0 when no layer contributed.\n */\n blendedScore: number\n /**\n * Complete task-quality measurement.\n * Present when at least one layer produced a valid score, every other layer\n * completed successfully or contributed an explicit scored failure, and no\n * result is missing because of a failure, skip, error, or timeout.\n * Use this field, not `blendedScore`, when creating task labels.\n */\n taskScore?: number\n durationMs: number\n startedAt: string\n finishedAt: string\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────\n\n/**\n * Grade a semantic-concept-style judge result into a single layer status.\n *\n * Pass when overall score >= threshold AND no critical-severity concept gap.\n * Fail otherwise. Use inside a `Layer.run` when wrapping a concept judge.\n *\n * Generalized from VerticalBench H3 fix: `failingConcepts.length === 0` was\n * too strict — a single concept at 6/10 failed the entire layer despite\n * overall score being >= 0.7. Now we trust the judge's own `severity` field:\n * `critical` findings veto; `major`/`minor` reduce the score but don't veto.\n */\nexport function gradeSemanticStatus(input: {\n score: number\n findings: Array<{ severity: Severity; present?: boolean; score?: number }>\n available: boolean\n threshold?: number\n}): LayerStatus {\n if (!input.available) return 'error'\n const threshold = input.threshold ?? 0.7\n const criticalGaps = input.findings.filter(\n (f) => f.severity === 'critical' && (f.present === false || (f.score ?? 0) < 7),\n )\n return input.score >= threshold && criticalGaps.length === 0 ? 'pass' : 'fail'\n}\n\n// ─── Verifier ───────────────────────────────────────────────────────────\n\n/**\n * Ordered DAG of verification layers with dependency-based skipping, per-layer findings, soft-fail semantics, and a blended composite score across all passed layers.\n */\nexport class MultiLayerVerifier<Env = unknown> {\n constructor(private readonly layers: Layer<Env>[]) {\n const seen = new Set<string>()\n for (const l of layers) {\n if (seen.has(l.name)) throw new Error(`MultiLayerVerifier: duplicate layer name \"${l.name}\"`)\n seen.add(l.name)\n }\n for (const l of layers) {\n for (const dep of l.dependsOn ?? []) {\n if (!seen.has(dep)) {\n throw new Error(\n `MultiLayerVerifier: layer \"${l.name}\" depends on \"${dep}\" which is not registered`,\n )\n }\n }\n }\n }\n\n async run(opts: VerifyOptions<Env>): Promise<VerificationReport> {\n const startedAtMs = Date.now()\n const startedAt = new Date(startedAtMs).toISOString()\n const controller = new AbortController()\n const overallCap = opts.overallCapMs\n const overallTimer =\n overallCap != null\n ? setTimeout(() => controller.abort(new Error('overall cap exceeded')), overallCap)\n : null\n\n const results: LayerResult[] = []\n const byName: Record<string, LayerResult> = {}\n\n try {\n for (const layer of this.layers) {\n // Skip if any dependency didn't pass.\n const unmet = (layer.dependsOn ?? []).filter((d) => byName[d]?.status !== 'pass')\n if (unmet.length > 0) {\n const skipped: LayerResult = {\n layer: layer.name,\n status: 'skipped',\n durationMs: 0,\n findings: [],\n reason: `skipped — upstream not passing: ${unmet.join(', ')}`,\n }\n results.push(skipped)\n byName[layer.name] = skipped\n opts.onLayer?.(skipped)\n continue\n }\n\n // Per-layer cap — compose with overall signal.\n const perLayerController = new AbortController()\n const mergedSignal = mergeSignals(controller.signal, perLayerController.signal)\n const layerTimer =\n layer.capMs != null\n ? setTimeout(\n () => perLayerController.abort(new Error(`layer ${layer.name} cap`)),\n layer.capMs,\n )\n : null\n\n const layerStart = Date.now()\n let result: LayerResult\n let rejectOnAbort: (() => void) | undefined\n const abortPromise = new Promise<never>((_resolve, reject) => {\n const rejectWithReason = (): void => {\n const reason = mergedSignal.reason\n reject(reason instanceof Error ? reason : new Error(String(reason ?? 'aborted')))\n }\n if (mergedSignal.aborted) {\n rejectWithReason()\n return\n }\n mergedSignal.addEventListener('abort', rejectWithReason, { once: true })\n rejectOnAbort = () => mergedSignal.removeEventListener('abort', rejectWithReason)\n })\n try {\n result = await Promise.race([\n Promise.resolve(\n layer.run({ env: opts.env, prior: { ...byName }, signal: mergedSignal }),\n ),\n abortPromise,\n ])\n } catch (err) {\n const aborted = mergedSignal.aborted\n result = {\n layer: layer.name,\n status: aborted ? 'timeout' : 'error',\n errorSource: layer.errorSource ?? 'execution',\n durationMs: Date.now() - layerStart,\n findings: [\n {\n severity: 'major',\n message: err instanceof Error ? err.message : String(err),\n layer: layer.name,\n },\n ],\n reason: err instanceof Error ? err.message : String(err),\n }\n } finally {\n rejectOnAbort?.()\n if (layerTimer) clearTimeout(layerTimer)\n }\n\n if (result.status === 'error' || result.status === 'timeout') {\n result.errorSource ??= layer.errorSource ?? 'execution'\n }\n\n // Normalize findings to attach layer name if omitted.\n result.findings = result.findings.map((f) => ({ ...f, layer: f.layer ?? layer.name }))\n results.push(result)\n byName[layer.name] = result\n opts.onLayer?.(result)\n\n if (controller.signal.aborted) break\n }\n\n const report = aggregate(this.layers, results, startedAt, startedAtMs)\n return report\n } finally {\n if (overallTimer) clearTimeout(overallTimer)\n }\n }\n}\n\nfunction aggregate<Env>(\n layers: Layer<Env>[],\n results: LayerResult[],\n startedAt: string,\n startedAtMs: number,\n): VerificationReport {\n const weightByName = new Map<string, number>()\n const failContribByName = new Map<string, boolean>()\n for (const l of layers) {\n weightByName.set(l.name, l.weight ?? 1)\n failContribByName.set(l.name, l.failContributesToScore ?? false)\n }\n\n let passCount = 0\n let failCount = 0\n let skippedCount = 0\n let errorCount = 0\n let scoredWeightSum = 0\n let scoredWeightedTotal = 0\n\n for (const r of results) {\n const weight = weightByName.get(r.layer) ?? 1\n const failContrib = failContribByName.get(r.layer) ?? false\n if (r.status === 'pass') passCount++\n else if (r.status === 'fail') failCount++\n else if (r.status === 'skipped') skippedCount++\n else errorCount++\n\n if (isValidTaskMeasurement(r) && weight > 0) {\n if (r.status === 'pass') {\n scoredWeightSum += weight\n scoredWeightedTotal += weight * r.score\n } else if (r.status === 'fail') {\n if (failContrib) {\n scoredWeightSum += weight\n scoredWeightedTotal += weight * r.score\n }\n }\n // skipped / error / timeout layers don't contribute\n }\n }\n\n const finishedAtMs = Date.now()\n const blendedScore = scoredWeightSum > 0 ? scoredWeightedTotal / scoredWeightSum : 0\n const resultByName = new Map(results.map((result) => [result.layer, result]))\n const completeTaskMeasurement =\n scoredWeightSum > 0 &&\n results.length === layers.length &&\n layers.every((layer) => {\n const result = resultByName.get(layer.name)\n if (!result) return false\n if ((layer.weight ?? 1) <= 0) return true\n if (result.status === 'pass') {\n return result.score === undefined || isValidTaskMeasurement(result)\n }\n return (\n result.status === 'fail' &&\n layer.failContributesToScore === true &&\n isValidTaskMeasurement(result)\n )\n })\n const taskScore =\n completeTaskMeasurement && scoredWeightSum > 0 && Number.isFinite(blendedScore)\n ? blendedScore\n : undefined\n const allPass =\n taskScore !== undefined &&\n results.length === layers.length &&\n failCount === 0 &&\n skippedCount === 0 &&\n errorCount === 0\n // Layers that produced no measurement are the steps this composite\n // certificate rests on without verifying — named per layer, never folded\n // into the blend silently.\n const assumptions = results\n .filter((r) => r.status === 'skipped' || r.status === 'error' || r.status === 'timeout')\n .map((r) => `layer '${r.layer}' ${r.status} — its obligations are unverified`)\n return {\n layers: results,\n passCount,\n failCount,\n skippedCount,\n errorCount,\n allPass,\n blendedScore,\n ...(taskScore === undefined ? {} : { taskScore }),\n valid: allPass,\n score: taskScore ?? 0,\n certification: {\n strategy: 'composite',\n checker: { name: 'agent-eval:multi-layer-verifier', version: packageVersion() },\n assumptions,\n evidenceDigest: certificationEvidenceDigest(results),\n },\n durationMs: finishedAtMs - startedAtMs,\n startedAt,\n finishedAt: new Date(finishedAtMs).toISOString(),\n }\n}\n\nfunction isValidTaskMeasurement(\n result: LayerResult,\n): result is LayerResult & { status: 'pass' | 'fail'; score: number } {\n return (\n (result.status === 'pass' || result.status === 'fail') &&\n typeof result.score === 'number' &&\n Number.isFinite(result.score) &&\n result.score >= 0 &&\n result.score <= 1\n )\n}\n\nfunction mergeSignals(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a\n if (b.aborted) return b\n const c = new AbortController()\n const onAbort = (signal: AbortSignal) => () => c.abort(signal.reason)\n a.addEventListener('abort', onAbort(a), { once: true })\n b.addEventListener('abort', onAbort(b), { once: true })\n return c.signal\n}\n","/**\n * Declarative oracles — ground-truth assertions without an LLM.\n *\n * Lifted from browser-agent-driver's _oracle.mjs. When you know the\n * expected outcome exactly (a URL, a text fragment, a JSON shape), you\n * don't need an LLM judge — you need a regex. These oracles are\n * composable pass/fail checks over an observation bundle.\n *\n * Each oracle returns { pass, detail, evidence? } and has a short `id` for\n * reporting. `evaluateOracles` runs a batch and lands the aggregate in the\n * shared verdict spine (`DefaultVerdict`, docs/verdicts.md) with a\n * `'test'`-strategy certification: an oracle set IS a small answer key,\n * and certifies nothing outside its own coverage.\n */\n\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\nexport interface OracleObservation {\n /** Final observable text output from the agent (response, page snapshot, stdout). */\n text?: string\n /** Final URL — for browser-style scenarios. */\n url?: string\n /** Any structured JSON the agent produced. */\n json?: unknown\n /** Free-form context used by custom oracles. */\n context?: Record<string, unknown>\n}\n\nexport interface OracleResult {\n id: string\n pass: boolean\n detail: string\n evidence?: string\n}\n\nexport interface Oracle {\n id: string\n check(obs: OracleObservation): OracleResult\n}\n\nexport function textInSnapshot(needle: string, opts: { caseSensitive?: boolean } = {}): Oracle {\n const id = `text-in-snapshot(${needle})`\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n const found = opts.caseSensitive\n ? hay.includes(needle)\n : hay.toLowerCase().includes(needle.toLowerCase())\n return {\n id,\n pass: found,\n detail: found ? `\"${needle}\" found` : `\"${needle}\" not present in observation`,\n evidence: found ? excerpt(hay, needle, opts.caseSensitive) : undefined,\n }\n },\n }\n}\n\nexport function urlContains(fragment: string): Oracle {\n const id = `url-contains(${fragment})`\n return {\n id,\n check(obs) {\n const url = obs.url ?? ''\n const pass = url.toLowerCase().includes(fragment.toLowerCase())\n return {\n id,\n pass,\n detail: pass ? `url ok (${url})` : `url \"${url}\" missing \"${fragment}\"`,\n evidence: url,\n }\n },\n }\n}\n\nexport function jsonShape(expected: Record<string, unknown>): Oracle {\n const id = `json-shape(${Object.keys(expected).join(',')})`\n return {\n id,\n check(obs) {\n const json = obs.json\n if (!isObject(json)) {\n return { id, pass: false, detail: 'observation.json missing or not an object' }\n }\n for (const [k, v] of Object.entries(expected)) {\n if (!(k in json)) return { id, pass: false, detail: `key \"${k}\" missing` }\n const actual = (json as Record<string, unknown>)[k]\n if (typeof v === 'string' && v.startsWith('re:')) {\n const re = new RegExp(v.slice(3))\n if (typeof actual !== 'string' || !re.test(actual)) {\n return { id, pass: false, detail: `key \"${k}\" failed regex ${v}` }\n }\n } else if (actual !== v) {\n return {\n id,\n pass: false,\n detail: `key \"${k}\" = ${JSON.stringify(actual)}, expected ${JSON.stringify(v)}`,\n }\n }\n }\n return { id, pass: true, detail: 'all keys match' }\n },\n }\n}\n\nexport function regexMatches(pattern: RegExp): Oracle {\n const id = `regex(${pattern.source})`\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n const m = hay.match(pattern)\n return {\n id,\n pass: m !== null,\n detail: m ? `matched \"${m[0]}\"` : `pattern ${pattern.source} not matched`,\n evidence: m?.[0],\n }\n },\n }\n}\n\n/**\n * Anti-bot detector — distinguishes genuine failures from blocked navigation\n * (cloudflare, recaptcha, etc). Returns an Oracle that PASSES when no block\n * marker is present; on block, detail names the blocker so runners can tag\n * results as \"blocked\" rather than \"failed\". Lifted from browser-agent-driver.\n */\nexport function notBlocked(): Oracle {\n const id = 'not-blocked'\n const markers: Array<{ name: string; re: RegExp }> = [\n { name: 'cloudflare', re: /just a moment|verifying you are human|cf-chl-|cloudflare/i },\n { name: 'recaptcha', re: /recaptcha|i'?m not a robot|challenge.?form/i },\n { name: 'hcaptcha', re: /hcaptcha/i },\n { name: 'akamai', re: /akamai|pragma: no-cache/i },\n { name: 'perimeterx', re: /perimeterx|px-captcha/i },\n { name: 'rate-limit', re: /rate.?limit|429 too many requests/i },\n { name: 'access-denied', re: /access denied|403 forbidden/i },\n ]\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n for (const { name, re } of markers) {\n if (re.test(hay)) {\n return {\n id,\n pass: false,\n detail: `blocked by ${name}`,\n evidence: (hay.match(re) ?? [])[0],\n }\n }\n }\n return { id, pass: true, detail: 'no anti-bot block detected' }\n },\n }\n}\n\n/** Extends the substrate verdict spine: `valid` = every oracle passed (and\n * at least one ran); `score` = ratio of oracles passed; `scores` = per-\n * oracle 0|1 keyed by oracle id. */\nexport interface OracleReport extends DefaultVerdict {\n results: OracleResult[]\n passCount: number\n failCount: number\n}\n\n/** Run all oracles against one observation and aggregate. */\nexport function evaluateOracles(obs: OracleObservation, oracles: Oracle[]): OracleReport {\n const results = oracles.map((o) => o.check(obs))\n const passCount = results.filter((r) => r.pass).length\n const failCount = results.length - passCount\n const scores: Record<string, number> = {}\n for (const r of results) scores[r.id] = r.pass ? 1 : 0\n return {\n results,\n passCount,\n failCount,\n valid: failCount === 0 && results.length > 0,\n score: results.length ? passCount / results.length : 0,\n scores,\n notes: `${passCount}/${results.length} oracles passed`,\n certification: {\n strategy: 'test',\n checker: { name: 'agent-eval:declarative-oracles', version: packageVersion() },\n assumptions: [],\n evidenceDigest: certificationEvidenceDigest(results),\n },\n }\n}\n\nfunction excerpt(hay: string, needle: string, caseSensitive = false): string {\n const haySearch = caseSensitive ? hay : hay.toLowerCase()\n const needleSearch = caseSensitive ? needle : needle.toLowerCase()\n const idx = haySearch.indexOf(needleSearch)\n if (idx === -1) return ''\n const start = Math.max(0, idx - 20)\n const end = Math.min(hay.length, idx + needle.length + 20)\n return (start > 0 ? '…' : '') + hay.slice(start, end) + (end < hay.length ? '…' : '')\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n","/**\n * Treatment-applied gate — \"did the treatment's tool actually fire this run?\"\n *\n * A tool-treatment A/B (mount a search provider, a browser, a code-exec\n * sandbox, a retrieval MCP — anything one arm gets and the other doesn't) only\n * means something on the treatment arm if that arm actually EXERCISED the tool.\n * A treatment run that never called the mounted tool is not a weak data point\n * — it is a NON-data-point: the manipulation never happened, so the run cannot\n * speak to the treatment and must be excluded from the objective, the same way\n * an infra-tainted run is excluded.\n *\n * This is the manipulation/validity precondition that protects the paired A/B\n * tests downstream (`mcnemar`, `pairedRiskDifference`): they must only ever see\n * runs where the treatment was applied, or they measure noise and report it as\n * an effect.\n *\n * Shape mirrors `authenticity`'s `gateRealness`: a pure predicate over already-\n * computed signals, with explicit fail-open/fail-closed discipline. It is not a\n * trace parser — the tool-call telemetry it reads is the deterministic\n * `toolHistogram` that `computeTraceMetrics(spans)` already produces (OTLP\n * tool-name extraction via `TOOL_NAME_ATTR_KEYS`), or the `ToolSpan[]` a\n * `toolSpans(store, runId)` query returns. The gate never re-derives either.\n *\n * General by construction:\n * - The \"which tool counts as the treatment\" decision is a `matches` PARAMETER\n * — a `(toolName: string) => boolean`. There is no `search`/`web`/`fetch`\n * literal anywhere in this module; a search A/B passes its own matcher.\n * - The \"is THIS run a treatment arm (vs a control)\" decision is the caller's\n * policy and stays at the call site. The gate only answers the narrower,\n * domain-free question: \"given this run's telemetry, did a matching tool\n * fire?\" — so it generalizes to any tool-treatment, not search.\n *\n * Fail-open on telemetry absence: when NO tool calls were captured at all\n * (`sum(toolHistogram) === 0`), the gate cannot distinguish \"the agent used no\n * tools\" from \"this harness's tool calls weren't recorded\". Quarantining on a\n * telemetry gap would silently delete real runs, so the default is\n * applied=true / gated=false. Pass `failOpenWhenNoTelemetry: false` to flip to\n * fail-closed for harnesses where tool capture is guaranteed.\n */\n\nimport type { RunRecord } from './run-record'\nimport type { ToolSpan } from './trace/schema'\nimport type { BehavioralMetrics } from './trace-analyst/behavioral-metrics'\nimport { computeTraceMetrics } from './trace-analyst/behavioral-metrics'\nimport type { TraceAnalystSpan } from './trace-analyst/types'\n\n/** A tool-name matcher: does this tool name belong to the treatment under test?\n * The caller supplies it — the substrate ships no `search` (or any) literal. */\nexport type ToolMatcher = (toolName: string) => boolean\n\nexport interface TreatmentGateInput {\n /** Tool-call counts by tool name — exactly `computeTraceMetrics(spans).toolHistogram`.\n * The gate consumes this; it does not parse spans itself. */\n toolHistogram: Readonly<Record<string, number>>\n /** Which tool names count as the treatment firing. A parameter, never baked in. */\n matches: ToolMatcher\n}\n\nexport interface TreatmentGateOptions {\n /** When the histogram is empty (no tool telemetry captured), treat the run as\n * applied rather than quarantining it. Default true — a telemetry gap must\n * never be mistaken for \"treatment not applied\". Set false only when tool\n * capture is guaranteed for this harness. */\n failOpenWhenNoTelemetry?: boolean\n}\n\nexport interface TreatmentGate {\n /** True iff the treatment's tool is considered to have fired this run. False\n * ONLY when telemetry was present and no matching call appears. */\n applied: boolean\n /** Objective-exclusion flag, parallel to `outcome.realness.gated`: a gated run\n * is dropped from the objective denominator and reported as\n * treatment-not-applied (like infra-loss). `gated === !applied`. */\n gated: boolean\n reason?: string\n /** How many recorded tool calls matched the treatment matcher. */\n matchedCalls: number\n /** Total recorded tool calls (`sum(toolHistogram)`) — 0 means no telemetry. */\n observedTools: number\n}\n\n/**\n * Core predicate. Gated (treatment-not-applied) ONLY when telemetry was\n * captured AND zero matching calls appear; an empty histogram fails open.\n */\nexport function gateTreatmentApplied(\n input: TreatmentGateInput,\n opts: TreatmentGateOptions = {},\n): TreatmentGate {\n const failOpen = opts.failOpenWhenNoTelemetry ?? true\n\n let observedTools = 0\n let matchedCalls = 0\n for (const [tool, count] of Object.entries(input.toolHistogram)) {\n const n = Number.isFinite(count) && count > 0 ? count : 0\n observedTools += n\n if (n > 0 && input.matches(tool)) matchedCalls += n\n }\n\n if (observedTools === 0) {\n return failOpen\n ? {\n applied: true,\n gated: false,\n reason: 'no tool telemetry captured — fail-open (not quarantined)',\n matchedCalls: 0,\n observedTools: 0,\n }\n : {\n applied: false,\n gated: true,\n reason: 'no tool telemetry captured — fail-closed',\n matchedCalls: 0,\n observedTools: 0,\n }\n }\n\n if (matchedCalls === 0) {\n return {\n applied: false,\n gated: true,\n reason: `treatment tool never fired (${observedTools} tool calls, 0 matched)`,\n matchedCalls: 0,\n observedTools,\n }\n }\n\n return { applied: true, gated: false, matchedCalls, observedTools }\n}\n\n/**\n * Convenience: gate from an already-computed `BehavioralMetrics` (the common\n * case — analysts already hold `computeTraceMetrics(spans)` for the run). Reads\n * the metrics' `toolHistogram`; does no re-derivation.\n */\nexport function gateTreatmentFromMetrics(\n metrics: Pick<BehavioralMetrics, 'toolHistogram'>,\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n return gateTreatmentApplied({ toolHistogram: metrics.toolHistogram, matches }, opts)\n}\n\n/**\n * Convenience: gate directly from analyst spans, reusing the substrate's\n * deterministic histogram builder. For callers holding the trace store's typed\n * `ToolSpan[]` instead, see {@link gateTreatmentFromToolSpans}.\n */\nexport function gateTreatmentFromSpans(\n spans: readonly TraceAnalystSpan[],\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n return gateTreatmentFromMetrics(computeTraceMetrics(spans), matches, opts)\n}\n\n/**\n * Convenience: gate from the trace store's canonical `ToolSpan[]` (e.g. the\n * result of `toolSpans(store, runId)`). Counts by `toolName` — the typed\n * tool-call field — so it needs no OTLP attribute extraction.\n */\nexport function gateTreatmentFromToolSpans(\n toolSpans: readonly ToolSpan[],\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n const toolHistogram: Record<string, number> = {}\n for (const s of toolSpans) {\n if (s.toolName) toolHistogram[s.toolName] = (toolHistogram[s.toolName] ?? 0) + 1\n }\n return gateTreatmentApplied({ toolHistogram, matches }, opts)\n}\n\n/** Measurable runs count toward the objective; treatment-not-applied runs are\n * excluded (like infra-loss), NOT counted as treatment failures. This is a\n * partition over the existing exclusion-flag pattern — it adds no new\n * classification enum. */\nexport type TreatmentClass = 'measurable' | 'treatment-not-applied'\n\n/**\n * Map a gate verdict onto a single measurable-vs-excluded label keyed on a\n * `RunRecord`, so consumers (paired A/B filters, reporters) read the partition\n * in one place instead of re-implementing the fail-open guard inline. The\n * `RunRecord` is accepted so callers key on the canonical run row, mirroring\n * how `outcome.realness.gated` rides along on the record; the verdict itself is\n * the gate's, not re-derived here.\n */\nexport function classifyTreatment(_record: RunRecord, gate: TreatmentGate): TreatmentClass {\n return gate.gated ? 'treatment-not-applied' : 'measurable'\n}\n","/**\n * Anti-slop quality judge.\n *\n * Deterministic pattern-based quality check — no LLM call. Catches the\n * 80% of AI slop that every production agent leaks:\n * - Banned phrases (voice-specific: \"delve\", \"it's worth noting\", etc.)\n * - N-gram repetition (same phrase over and over)\n * - Hedging overuse (\"I could be wrong, but...\")\n * - Apology padding (\"I'm so sorry for the confusion...\")\n * - Unused opening formulas (\"Great question!\")\n * - Length bounds (too short to be useful, too long to be read)\n *\n * Produces a JudgeScore in the same shape as LLM judges so it composes into\n * any `JudgeFn` array transparently.\n */\n\nimport type { JudgeFn, JudgeInput, JudgeScore } from './types'\n\nexport interface AntiSlopConfig {\n /** Domain label — appears in the JudgeScore output */\n domain?: string\n\n /** Case-insensitive substrings that must not appear. Each occurrence = penalty. */\n bannedPhrases?: string[]\n\n /** Regexes matching opening formulas to penalize (e.g. /^great question/i). */\n bannedOpenings?: RegExp[]\n\n /** Regexes matching hedges (e.g. /i could be wrong/i). Ratio of hedged sentences drives score. */\n hedgingPatterns?: RegExp[]\n\n /** Regexes matching apology padding. */\n apologyPatterns?: RegExp[]\n\n /** Fraction of sentences that can be duplicates before penalty (default 0.15 = 15%). */\n repetitionThreshold?: number\n\n /** Min output length in chars; below this the turn is deemed too terse. */\n minLength?: number\n\n /** Max output length in chars; above this the turn is deemed too verbose. */\n maxLength?: number\n\n /** How heavily each violation class reduces the score (default 1). */\n penaltyWeights?: Partial<Record<SlopCategory, number>>\n}\n\nexport type SlopCategory =\n | 'banned_phrase'\n | 'banned_opening'\n | 'hedging'\n | 'apology'\n | 'repetition'\n | 'length'\n\nconst DEFAULT_HEDGES: RegExp[] = [\n /\\bi\\s+could\\s+be\\s+wrong\\b/i,\n /\\bi\\s+think\\s+maybe\\b/i,\n /\\bit\\s+might\\s+be\\s+that\\b/i,\n /\\bperhaps\\s+(?:you\\s+)?could\\b/i,\n]\n\nconst DEFAULT_APOLOGIES: RegExp[] = [\n /\\bi\\s+(?:apologize|apologise)\\s+(?:for|if)\\b/i,\n /\\bi'?m\\s+(?:so\\s+|really\\s+)?sorry\\s+(?:for|if|about)\\b/i,\n /\\bmy\\s+apologies\\b/i,\n]\n\n/** Create a reusable Judge function from an anti-slop config. */\nexport function createAntiSlopJudge(config: AntiSlopConfig = {}): JudgeFn {\n const conf: Required<Omit<AntiSlopConfig, 'penaltyWeights'>> & {\n penaltyWeights: Record<SlopCategory, number>\n } = {\n domain: config.domain ?? 'general',\n bannedPhrases: config.bannedPhrases ?? [],\n bannedOpenings: config.bannedOpenings ?? [],\n hedgingPatterns: config.hedgingPatterns ?? DEFAULT_HEDGES,\n apologyPatterns: config.apologyPatterns ?? DEFAULT_APOLOGIES,\n repetitionThreshold: config.repetitionThreshold ?? 0.15,\n minLength: config.minLength ?? 20,\n maxLength: config.maxLength ?? 8000,\n penaltyWeights: {\n banned_phrase: 1,\n banned_opening: 1,\n hedging: 0.5,\n apology: 0.5,\n repetition: 0.75,\n length: 0.5,\n ...config.penaltyWeights,\n },\n }\n\n const judge: JudgeFn = async (_tc, input: JudgeInput): Promise<JudgeScore[]> => {\n const outputs = input.turns.map((t) => t.agentResponse ?? '')\n const report = analyzeAntiSlop(outputs, conf)\n return [\n {\n judgeName: `anti-slop(${conf.domain})`,\n dimension: 'anti_slop',\n score: report.score,\n reasoning: report.issues.length\n ? report.issues\n .slice(0, 5)\n .map((i) => `${i.category}: ${i.detail}`)\n .join('; ')\n : 'No slop patterns detected.',\n evidence: report.issues[0]?.example,\n },\n ]\n }\n return judge\n}\n\nexport interface AntiSlopIssue {\n category: SlopCategory\n detail: string\n example?: string\n}\n\nexport interface AntiSlopReport {\n /** 0–10 score; 10 is clean, lower values mean more slop. */\n score: number\n issues: AntiSlopIssue[]\n /** Count of each category for programmatic aggregation. */\n counts: Record<SlopCategory, number>\n}\n\n/**\n * Pure function — analyze one or more outputs against the config. Exposed\n * separately so consumers can build their own reporters on top.\n */\nexport function analyzeAntiSlop(\n outputs: string[],\n config: Omit<Required<AntiSlopConfig>, 'domain'> & {\n penaltyWeights: Record<SlopCategory, number>\n },\n): AntiSlopReport {\n const issues: AntiSlopIssue[] = []\n const counts: Record<SlopCategory, number> = {\n banned_phrase: 0,\n banned_opening: 0,\n hedging: 0,\n apology: 0,\n repetition: 0,\n length: 0,\n }\n\n for (const output of outputs) {\n if (!output) continue\n const lower = output.toLowerCase()\n\n for (const phrase of config.bannedPhrases) {\n const needle = phrase.toLowerCase()\n let idx = lower.indexOf(needle, 0)\n while (idx !== -1) {\n counts.banned_phrase += 1\n if (issues.length < 20) {\n issues.push({\n category: 'banned_phrase',\n detail: `\"${phrase}\"`,\n example: snippet(output, idx, phrase.length),\n })\n }\n idx = lower.indexOf(needle, idx + needle.length)\n }\n }\n\n for (const re of config.bannedOpenings) {\n if (re.test(output)) {\n counts.banned_opening += 1\n issues.push({ category: 'banned_opening', detail: re.source, example: output.slice(0, 80) })\n }\n }\n\n for (const re of config.hedgingPatterns) {\n const matches = output.match(\n new RegExp(re, re.flags.includes('g') ? re.flags : `${re.flags}g`),\n )\n if (matches) {\n counts.hedging += matches.length\n issues.push({\n category: 'hedging',\n detail: `${matches.length}x ${re.source}`,\n example: matches[0],\n })\n }\n }\n\n for (const re of config.apologyPatterns) {\n const matches = output.match(\n new RegExp(re, re.flags.includes('g') ? re.flags : `${re.flags}g`),\n )\n if (matches) {\n counts.apology += matches.length\n issues.push({\n category: 'apology',\n detail: `${matches.length}x ${re.source}`,\n example: matches[0],\n })\n }\n }\n\n // Repetition: compare sentence-level dupes\n const sentences = splitSentences(output)\n if (sentences.length >= 4) {\n const seen = new Map<string, number>()\n for (const s of sentences) {\n const key = normalizeForDupe(s)\n if (!key) continue\n seen.set(key, (seen.get(key) ?? 0) + 1)\n }\n let dupes = 0\n for (const n of seen.values()) if (n > 1) dupes += n - 1\n const ratio = dupes / sentences.length\n if (ratio > config.repetitionThreshold) {\n counts.repetition += 1\n issues.push({\n category: 'repetition',\n detail: `${(ratio * 100).toFixed(0)}% duplicated (threshold ${(config.repetitionThreshold * 100).toFixed(0)}%)`,\n })\n }\n }\n\n // Length\n if (output.length < config.minLength) {\n counts.length += 1\n issues.push({\n category: 'length',\n detail: `too short (${output.length} < ${config.minLength})`,\n })\n } else if (output.length > config.maxLength) {\n counts.length += 1\n issues.push({\n category: 'length',\n detail: `too long (${output.length} > ${config.maxLength})`,\n })\n }\n }\n\n // Score: 10 minus weighted violations, clamped. Each violation of category c\n // subtracts `penaltyWeights[c]` points. Violations beyond 10/weight saturate.\n let penalty = 0\n for (const cat of Object.keys(counts) as SlopCategory[]) {\n penalty += counts[cat] * (config.penaltyWeights[cat] ?? 1)\n }\n const score = Math.max(0, Math.min(10, 10 - penalty))\n\n return { score, issues, counts }\n}\n\nfunction snippet(source: string, at: number, len: number): string {\n const pad = 24\n const start = Math.max(0, at - pad)\n const end = Math.min(source.length, at + len + pad)\n return (start > 0 ? '…' : '') + source.slice(start, end) + (end < source.length ? '…' : '')\n}\n\nfunction splitSentences(text: string): string[] {\n // Simple sentence split — good enough for slop detection; not linguistically perfect.\n return text\n .split(/[.!?\\n]+/)\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n}\n\nfunction normalizeForDupe(s: string): string {\n return s\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .replace(/[^a-z0-9 ]/g, '')\n .trim()\n}\n","/**\n * EvalTraceStore — JSONL save / query / compare over the analysis-time\n * `RunRecord` row.\n *\n * `FileSystemTraceStore` (in `./trace/store`) persists the rich TraceSchema-v1\n * span corpus — runs, spans, events, artifacts — the runtime emits live. That\n * is NOT the thing three consumers hand-roll in `tests/eval/lib/trace-store.ts`.\n * What they hand-roll is the *analysis* layer: append each finished run as one\n * JSONL line keyed by scenario/candidate, then query it (\"every run where score\n * < 50\"), pick the best run for a scenario (few-shot seeding), and compare two\n * candidates on matched scenarios.\n *\n * The substrate already has the canonical analysis-time row — `RunRecord` — so\n * this is that query/compare API expressed over `RunRecord[]`, with a\n * JSONL-backed store. It does NOT fork `FileSystemTraceStore`; it sits beside it\n * for the analysis projection.\n */\n\nimport { ValidationError } from './errors'\nimport { isRealnessGated, trainingScore } from './rollout/reward'\nimport { isRunRecord, type RunRecord, type RunSplitTag, validateRunRecord } from './run-record'\n\n/**\n * The score the query/compare layer ranks on: holdout when present, else\n * search, with the anti-Goodhart gate applied — a run flagged as gamed reads 0\n * however high it claims to have scored.\n *\n * The gate is load-bearing here and this function did not previously apply it,\n * despite saying it did. `getBest` is few-shot exemplar selection: whatever it\n * returns is pasted into the next agent's prompt as an example to imitate.\n * Ranking on the raw number handed the highest-scoring gamed trajectory to\n * every subsequent run — propagation through the context window rather than\n * through a gradient, but propagation all the same.\n *\n * Analysis that needs to SEE the inflated number (reward-hack detection,\n * per-run reporting) reads `observedScore` from `rollout/reward.ts` directly.\n *\n * Returns `undefined` for an execution-only record (neither score present):\n * such rows are valid RunRecords, but cannot participate in score-ranked\n * queries. A gated run still reads 0 — the gate's verdict is a number, never\n * a gap.\n */\nexport function runScore(record: RunRecord): number | undefined {\n return trainingScore(record)\n}\n\nexport interface RunRecordFilter {\n experimentId?: string\n candidateId?: string\n scenarioId?: string\n model?: string\n splitTag?: RunSplitTag\n /** Inclusive lower bound on `runScore`. */\n minScore?: number\n /** Inclusive upper bound on `runScore`. */\n maxScore?: number\n /** Match a single tag in `outcome.raw` by exact numeric value. */\n rawEquals?: { key: string; value: number }\n /** Custom predicate, ANDed with the structured filters. */\n where?: (record: RunRecord) => boolean\n}\n\nfunction matches(record: RunRecord, f: RunRecordFilter): boolean {\n if (f.experimentId && record.experimentId !== f.experimentId) return false\n if (f.candidateId && record.candidateId !== f.candidateId) return false\n if (f.scenarioId && record.scenarioId !== f.scenarioId) return false\n if (f.model && record.model !== f.model) return false\n if (f.splitTag && record.splitTag !== f.splitTag) return false\n if (f.minScore !== undefined || f.maxScore !== undefined) {\n const score = runScore(record)\n if (score === undefined) return false\n if (f.minScore !== undefined && score < f.minScore) return false\n if (f.maxScore !== undefined && score > f.maxScore) return false\n }\n if (f.rawEquals && record.outcome.raw[f.rawEquals.key] !== f.rawEquals.value) return false\n if (f.where && !f.where(record)) return false\n return true\n}\n\nexport interface CandidateComparison {\n a: string\n b: string\n /** Scenario ids present for BOTH candidates — the paired comparison set. */\n pairedScenarioIds: string[]\n /** Mean `runScore` for candidate a over the paired scenarios. */\n meanA: number\n /** Mean `runScore` for candidate b over the paired scenarios. */\n meanB: number\n /** meanB − meanA. Positive ⇒ b scored higher on the matched scenarios. */\n meanDelta: number\n /** Scenarios where b beat a (strictly), tied, and a beat b. */\n bWins: number\n ties: number\n aWins: number\n /**\n * Runs of either candidate excluded from the comparison because the\n * authenticity gate flagged them (`outcome.realness.gated`).\n *\n * Excluded rather than scored 0: `runScore` is gated, so leaving them in\n * would have entered a gamed run as a silent zero, which reads as \"this\n * candidate failed the scenario\" when what happened is \"this candidate's\n * result is not evidence\". A non-zero count here is itself the finding — a\n * comparison drawn over a shrunken scenario set has to say so.\n */\n realnessGatedRuns: number\n}\n\n/**\n * Backing persistence for `EvalTraceStore`. The in-memory store is the default;\n * the JSONL file store appends one validated `RunRecord` per line. Both keep an\n * append order so `getBest` / `compareRuns` are reproducible.\n */\nexport interface RunRecordBackend {\n append(record: RunRecord): Promise<void>\n load(): Promise<RunRecord[]>\n}\n\nexport function inMemoryRunRecordBackend(initial: RunRecord[] = []): RunRecordBackend {\n const rows = initial.map((r) => validateRunRecord(r))\n return {\n async append(record) {\n rows.push(record)\n },\n async load() {\n return [...rows]\n },\n }\n}\n\n/**\n * JSONL-backed store at `path`, one `RunRecord` per line. Malformed lines fail\n * loud on load (a corrupt corpus must not silently shrink the analysis set);\n * pass `skipInvalid` only for forensics on a known-bad file.\n */\nexport function jsonlRunRecordBackend(\n path: string,\n opts: { skipInvalid?: boolean } = {},\n): RunRecordBackend {\n return {\n async append(record) {\n const fs = await import('node:fs/promises')\n const pathMod = await import('node:path')\n await fs.mkdir(pathMod.dirname(path), { recursive: true })\n await fs.appendFile(path, `${JSON.stringify(record)}\\n`, 'utf8')\n },\n async load() {\n const fs = await import('node:fs/promises')\n let raw: string\n try {\n raw = await fs.readFile(path, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw err\n }\n const out: RunRecord[] = []\n let lineNo = 0\n for (const line of raw.split('\\n')) {\n lineNo++\n if (!line.trim()) continue\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch (err) {\n if (opts.skipInvalid) continue\n throw new ValidationError(`EvalTraceStore: ${path}:${lineNo} is not valid JSON`)\n }\n if (opts.skipInvalid) {\n if (isRunRecord(parsed)) out.push(parsed)\n continue\n }\n try {\n out.push(validateRunRecord(parsed))\n } catch (err) {\n throw new ValidationError(\n `EvalTraceStore: ${path}:${lineNo} is not a valid RunRecord — ${(err as Error).message}`,\n )\n }\n }\n return out\n },\n }\n}\n\n/**\n * Query / compare layer over a `RunRecord` corpus. Append finished runs, query\n * with a structured filter, take the best run for a scenario, and compare two\n * candidates on their matched scenarios. Persistence is injected via\n * `RunRecordBackend` (in-memory by default, JSONL file via\n * `jsonlRunRecordBackend`).\n */\nexport class EvalTraceStore {\n private readonly backend: RunRecordBackend\n\n constructor(backend: RunRecordBackend = inMemoryRunRecordBackend()) {\n this.backend = backend\n }\n\n /** Validate and append one run. Throws on an invalid record — the corpus\n * stays paper-grade. */\n async append(record: RunRecord): Promise<void> {\n await this.backend.append(validateRunRecord(record))\n }\n\n async all(): Promise<RunRecord[]> {\n return this.backend.load()\n }\n\n async query(filter: RunRecordFilter = {}): Promise<RunRecord[]> {\n const rows = await this.backend.load()\n return rows.filter((r) => matches(r, filter))\n }\n\n /**\n * Highest-scoring run for a scenario (optionally restricted to a candidate).\n * Returns null when no run matches. Ties resolve to the earliest-appended run\n * so the result is stable.\n *\n * Runs flagged as gamed are DROPPED, not zeroed. The caller's use for this is\n * few-shot seeding — the returned trajectory becomes an example to copy — so\n * the same rule as SFT applies: a faked success must not be in the candidate\n * set at all. When every run for the scenario is gated the honest answer is\n * `null` (no exemplar), never the least-bad fake.\n */\n async getBest(\n scenarioId: string,\n opts: { candidateId?: string; splitTag?: RunSplitTag } = {},\n ): Promise<RunRecord | null> {\n const rows = (\n await this.query({\n scenarioId,\n candidateId: opts.candidateId,\n splitTag: opts.splitTag,\n })\n ).filter((r) => !isRealnessGated(r))\n const scored = rows.flatMap((record) => {\n const score = runScore(record)\n return score === undefined ? [] : [{ record, score }]\n })\n if (scored.length === 0) return null\n let best = scored[0]!.record\n let bestScore = scored[0]!.score\n for (let i = 1; i < scored.length; i++) {\n const s = scored[i]!.score\n if (s > bestScore) {\n best = scored[i]!.record\n bestScore = s\n }\n }\n return best\n }\n\n /**\n * Compare two candidates on the scenarios they BOTH ran. When a candidate\n * ran a scenario more than once, its best `runScore` for that scenario is\n * used. Throws when there is no paired scenario — an unpaired \"comparison\" is\n * not one.\n *\n * Realness-gated runs are excluded and counted in `realnessGatedRuns`, never\n * folded in as a zero.\n */\n async compareRuns(candidateA: string, candidateB: string): Promise<CandidateComparison> {\n if (candidateA === candidateB) {\n throw new ValidationError(\n `EvalTraceStore.compareRuns: candidates must differ (\"${candidateA}\")`,\n )\n }\n const rows = await this.backend.load()\n let realnessGatedRuns = 0\n const bestByScenario = (candidate: string): Map<string, number> => {\n const m = new Map<string, number>()\n for (const r of rows) {\n if (r.candidateId !== candidate) continue\n const sid = r.scenarioId\n if (!sid) continue\n if (isRealnessGated(r)) {\n realnessGatedRuns++\n continue\n }\n const s = runScore(r)\n if (s === undefined) continue\n const prev = m.get(sid)\n if (prev === undefined || s > prev) m.set(sid, s)\n }\n return m\n }\n const aScores = bestByScenario(candidateA)\n const bScores = bestByScenario(candidateB)\n const paired = [...aScores.keys()].filter((sid) => bScores.has(sid)).sort()\n if (paired.length === 0) {\n // Distinguish \"the corpora never overlapped\" from \"they overlap, but\n // every shared scenario lost a side to the realness gate\" — the second\n // diagnosis points at gamed runs, not at a mislabeled corpus.\n throw new ValidationError(\n realnessGatedRuns > 0\n ? `EvalTraceStore.compareRuns: \"${candidateA}\" and \"${candidateB}\" share no scenario ` +\n `with honest runs on both sides (${realnessGatedRuns} run(s) were realness-gated)`\n : `EvalTraceStore.compareRuns: \"${candidateA}\" and \"${candidateB}\" share no scenario (need scenarioId on records)`,\n )\n }\n let sumA = 0\n let sumB = 0\n let bWins = 0\n let aWins = 0\n let ties = 0\n for (const sid of paired) {\n const sa = aScores.get(sid)!\n const sb = bScores.get(sid)!\n sumA += sa\n sumB += sb\n if (sb > sa) bWins++\n else if (sb < sa) aWins++\n else ties++\n }\n const meanA = sumA / paired.length\n const meanB = sumB / paired.length\n return {\n a: candidateA,\n b: candidateB,\n pairedScenarioIds: paired,\n meanA,\n meanB,\n meanDelta: meanB - meanA,\n bWins,\n ties,\n aWins,\n realnessGatedRuns,\n }\n }\n}\n","/**\n * Backend preflight: verify the models a campaign is about to spend tokens\n * against are actually served by the router BEFORE the run starts. The PRE-hoc\n * complement to `assertRealBackend` (which inspects RunRecords AFTER the run to\n * catch a stub/unconfigured backend).\n *\n * The caller owns the endpoint. Agent Eval holds no base URL and no\n * credential: it asks a caller-supplied `request` function for each check and\n * reads the `Response` that comes back, so the status and the provider's own\n * error text stay readable here.\n *\n * Two checks, increasing in cost:\n * - membership (free): one `list-models` request; a model is `listed` when\n * its id is in the served set.\n * - probe (spends a tiny number of tokens): one `probe` request per model\n * with a `maxOutputTokens` budget; `served` is whether the endpoint reached\n * a provider, with the HTTP `status` and the body's `error.message`\n * captured in `detail`, and `servedModel` recording WHICH model answered.\n *\n * A 2xx is not proof the requested model answered — a gateway can accept one\n * id and route to another. The probe therefore compares the echoed id against\n * the requested one and reports `substitution`; `assertModelsServed` fails on\n * a substituted id exactly as it fails on a dead one, because a campaign that\n * runs on a silently-swapped model produces per-model numbers about a model it\n * never called.\n *\n * A default model the router cannot serve is a config bug. Gate a campaign on\n * `assertModelsServed` and it surfaces every dead or substituted id with its\n * status + detail instead of silently producing a stub or mislabelled run.\n */\n\nimport { AgentEvalError, ConfigError } from '../errors'\nimport {\n checkServedModel,\n PROBE_MAX_TOKENS,\n type ServedModelCheck,\n servedModelAcceptable,\n} from './served-model'\n\n/**\n * Provider signature for \"the budget ran out before an answer\". The model is\n * alive — a provider took the request and consumed the budget — so this must\n * never be scored as a dead id.\n */\nconst REASONING_BUDGET_EXHAUSTED = /reasoning[\\s_-]?budget[\\s_-]?exhausted/i\n\nexport interface ModelPreflight {\n /** The model id as supplied by the caller. */\n model: string\n /** Membership in the `{baseUrl}/models` served set. */\n listed: boolean\n /**\n * The router reached a provider for this model. `null` when `probe` was not\n * requested. True on a 2xx, and also when the provider answered by\n * exhausting its reasoning budget — that proves reachability while leaving\n * identity unproven (see `budgetExhausted`).\n */\n served: boolean | null\n /** HTTP status of the probe. `null` when not probed. */\n status: number | null\n /** Probe body's `error.message` when present, else `null`. */\n detail: string | null\n /**\n * The probe died on the token budget rather than on the model. Identity is\n * unproven, not refuted: raise `probeMaxTokens` to resolve it.\n */\n budgetExhausted: boolean\n /**\n * Identity of the model that answered the probe, compared against `model`.\n * `null` when the model was not probed or the probe failed.\n */\n substitution: ServedModelCheck | null\n}\n\n/** One check Agent Eval asks the caller's endpoint to perform. */\nexport type ModelEndpointCheck =\n | { readonly kind: 'list-models' }\n | {\n readonly kind: 'probe'\n readonly model: string\n /** Output-token budget the probe completion may bill. */\n readonly maxOutputTokens: number\n }\n\n/**\n * Caller-owned request into the model endpoint. The caller binds the base URL\n * and the credential and returns the raw `Response`; a `list-models` request\n * answers with an OpenAI-compatible `{ data: [{ id }] }` body, and a `probe`\n * request answers with one minimal chat completion for `model`.\n */\nexport type ModelEndpointRequest = (check: ModelEndpointCheck) => Promise<Response>\n\nexport interface PreflightModelsOptions {\n /** Caller-owned endpoint request. Agent Eval issues no provider HTTP itself. */\n request: ModelEndpointRequest\n /** Model ids to check. */\n models: string[]\n /** When true, additionally spend a small chat probe per model. Default false. */\n probe?: boolean\n /**\n * Output-token budget per probe. Default `PROBE_MAX_TOKENS`. Lowering it\n * below the reasoning floor makes healthy reasoning models report\n * `budgetExhausted` instead of proving their identity.\n */\n probeMaxTokens?: number\n}\n\nexport interface PreflightOutcome {\n succeeded: boolean\n value: ModelPreflight[] | null\n error: string | null\n}\n\ninterface ModelsListBody {\n data?: ReadonlyArray<{ id?: unknown }>\n}\n\ninterface ChatErrorBody {\n error?: { message?: unknown }\n message?: unknown\n}\n\ninterface ChatProbeBody {\n model?: unknown\n}\n\n/** Extract `error.message` (then top-level `message`) from a chat-completions error body. */\nfunction errorMessage(body: unknown): string | null {\n if (body == null || typeof body !== 'object') return null\n const b = body as ChatErrorBody\n if (b.error && typeof b.error.message === 'string') return b.error.message\n if (typeof b.message === 'string') return b.message\n return null\n}\n\n/**\n * Check that `models` are reachable on the router. Returns a typed outcome —\n * a network failure yields `{ succeeded: false, error }`, never a throw and\n * never a partial result silently reported as success. No retries, no\n * fallbacks.\n *\n * The membership check (one GET) always runs. When `probe` is true, each model\n * additionally gets a small chat probe so a model that is listed but\n * unconfigured (a 401 `model_not_found` from the router) is caught.\n */\nexport async function preflightModels(opts: PreflightModelsOptions): Promise<PreflightOutcome> {\n const maxTokens = opts.probeMaxTokens ?? PROBE_MAX_TOKENS\n if (!Number.isInteger(maxTokens) || maxTokens <= 0) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: probeMaxTokens must be a positive integer, got ${maxTokens}`,\n }\n }\n\n let served: Set<string>\n try {\n const res = await opts.request({ kind: 'list-models' })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: list-models → ${res.status} ${text.slice(0, 400)}`,\n }\n }\n const body = (await res.json()) as ModelsListBody\n const ids = Array.isArray(body.data) ? body.data : []\n served = new Set(ids.map((m) => m.id).filter((id): id is string => typeof id === 'string'))\n } catch (err) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: list-models failed — ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n\n const results: ModelPreflight[] = []\n for (const model of opts.models) {\n const listed = served.has(model)\n if (!opts.probe) {\n results.push({\n model,\n listed,\n served: null,\n status: null,\n detail: null,\n budgetExhausted: false,\n substitution: null,\n })\n continue\n }\n try {\n const res = await opts.request({ kind: 'probe', model, maxOutputTokens: maxTokens })\n let detail: string | null = null\n let substitution: ServedModelCheck | null = null\n let budgetExhausted = false\n const body = await res.json().catch(() => null)\n if (res.ok) {\n const echoed = (body as ChatProbeBody | null)?.model\n substitution = checkServedModel(\n model,\n typeof echoed === 'string' && echoed.trim() !== '' ? echoed : null,\n )\n } else {\n detail = errorMessage(body)\n budgetExhausted = detail !== null && REASONING_BUDGET_EXHAUSTED.test(detail)\n // The provider took the request and burned the budget, so the id is\n // live. It echoed no model, so identity stays unproven and the default\n // `allowUnreported: false` still refuses the run.\n if (budgetExhausted) substitution = checkServedModel(model, null)\n }\n results.push({\n model,\n listed,\n served: res.ok || budgetExhausted,\n status: res.status,\n detail,\n budgetExhausted,\n substitution,\n })\n } catch (err) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: probe (model ${model}) failed — ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n return { succeeded: true, value: results, error: null }\n}\n\nexport class ModelsUnreachableError extends AgentEvalError {\n constructor(\n message: string,\n public readonly results: ReadonlyArray<ModelPreflight>,\n ) {\n super('config', message)\n this.name = 'ModelsUnreachableError'\n }\n}\n\nfunction describeFailure(r: ModelPreflight): string {\n if (!r.listed) {\n const probeNote =\n r.served === false ? ` (probe ${r.status}${r.detail ? `: ${r.detail}` : ''})` : ''\n return `${r.model}: not in /models${probeNote}`\n }\n if (r.served === false) {\n return `${r.model}: listed but probe ${r.status}${r.detail ? ` — ${r.detail}` : ''}`\n }\n if (r.budgetExhausted) {\n return (\n `${r.model}: alive but the probe ran out of reasoning budget (status ${r.status}` +\n `${r.detail ? `: ${r.detail}` : ''}) — it echoed no model id, so identity is unproven. ` +\n 'Raise probeMaxTokens, or pass allowUnreported to accept reachability without identity.'\n )\n }\n // listed, probe 2xx — but a different model answered\n const s = r.substitution\n if (s?.verdict === 'unreported') {\n return `${r.model}: probe answered without echoing a model id — identity unproven`\n }\n return `${r.model}: probe answered by ${s?.served} (${s?.verdict})`\n}\n\nexport interface AssertModelsServedOptions extends PreflightModelsOptions {\n /**\n * Accept a probe answered by a different model of the same provider family.\n * Default false. Only meaningful with `probe: true`.\n */\n allowWithinFamily?: boolean\n /**\n * Accept a probe whose response echoed no model id. Default false — an\n * unidentified response cannot prove the requested model is the one running.\n */\n allowUnreported?: boolean\n}\n\n/**\n * Throw `ModelsUnreachableError` naming EVERY model that is unusable for a\n * measured run — with status, detail, and served identity per model. A model\n * is unusable when it is unlisted, when its probe fails, or when its probe is\n * answered by a different model than the one requested. Callers gate a\n * campaign on this before spending tokens. When the network call itself fails\n * the underlying outcome error is rethrown — there is no partial silent pass.\n *\n * Substitution is only detectable with `probe: true`; a membership-only check\n * proves an id is in the catalogue, never that the catalogue entry answers.\n */\nexport async function assertModelsServed(\n opts: AssertModelsServedOptions,\n): Promise<ModelPreflight[]> {\n const outcome = await preflightModels(opts)\n if (!outcome.succeeded || outcome.value === null) {\n throw new ConfigError(\n outcome.error ?? 'assertModelsServed: preflight failed without an error message',\n )\n }\n const bad = outcome.value.filter(\n (r) =>\n !r.listed ||\n r.served === false ||\n (r.substitution !== null && !servedModelAcceptable(r.substitution, opts)),\n )\n if (bad.length > 0) {\n throw new ModelsUnreachableError(\n `assertModelsServed: ${bad.length}/${outcome.value.length} model(s) unusable on the router — ${bad\n .map(describeFailure)\n .join('; ')}`,\n outcome.value,\n )\n }\n return outcome.value\n}\n","/**\n * ModelSeats — the program's model seating chart.\n *\n * One object names which model fills each role in an eval program: the worker\n * under evaluation, the judge panel, the analyst, the reflection/driver model,\n * and the verifier. Re-tiering an entire program (economy ↔ frontier) is one\n * swapped object instead of a hunt through call sites.\n *\n * Wiring points — consumers thread seats; this module implements none of them\n * (those files belong to other surfaces):\n * - `judges` → `ensembleJudge({ models: seats.judges, … })` (src/judge-panel.ts)\n * and the `JudgeConfig`s handed to `makeEvalTools({ judges })`\n * (src/eval-tools.ts).\n * - `reflection` → the model configured by a custom `SurfaceProposer` or\n * external optimization engine.\n * - `worker` → the dispatch model the agent itself calls — the model an\n * `AgentProfile` declares.\n * - `analyst` → the LLM behind `analyzeRuns` / analyst-registry kinds.\n * - `verifier` → completion-verifier / objective-checker model.\n * - campaign cells thread `judges` + driver models the same way; that wiring\n * lands with the campaign surface, not here.\n *\n * `resolveSeat` is the only read path: an unset seat with no explicit fallback\n * throws — a model id is a budget decision, never a silent default.\n */\n\nimport { ConfigError, ValidationError } from './errors'\n\nexport interface ModelSeats {\n /** The model under evaluation — what the agent itself dispatches with. */\n worker?: string\n /** Judge-panel model ids — thread into `ensembleJudge({ models })`. */\n judges?: string[]\n /** Analyst model — `analyzeRuns` / analyst-registry LLM calls. */\n analyst?: string\n /** Reflection or candidate-generation model. */\n reflection?: string\n /** Verifier model — completion/objective checking. */\n verifier?: string\n}\n\nexport type SeatName = keyof ModelSeats\n\nexport type SeatPresetName = keyof typeof seatPresets\n\n/**\n * Tier presets — plain data, swap or spread freely.\n *\n * A preset names REQUESTED ids, and a requested id is NOT a guarantee of\n * family, of provider, or of liveness. A routing gateway can accept any id\n * below and answer from a different model on HTTP 200, with only the response\n * body's `model` field betraying the swap. The served assertion is the\n * guarantee: gate a run on `assertModelsServed({ probe: true })` and assert\n * `assertServedModel` per call. `assertCrossFamily` over these ids proves the\n * configuration is diverse; only `assertCrossFamilyServed` over the ids that\n * ANSWERED proves the run was.\n *\n * `economy` names ids a live router probe answered from the provider their\n * name implies, so the judge trio spanned three provider families (deepseek /\n * zhipu / google) as configured and, at that probe, as served. A preset is\n * only as good as its last probe: ids go dead and start resolving elsewhere\n * without notice, so re-probe rather than trusting this list.\n *\n * `frontier` is deliberately EMPTY: entitled frontier ids vary per router\n * account, and a hardcoded claude/gpt-5 id 401s on keys that lack it. Supply\n * your own: `{ ...seatPresets.frontier, worker: '<your-frontier-id>', … }` —\n * `resolveSeat` throws on every seat you haven't filled.\n */\nexport const seatPresets: Record<'economy' | 'frontier', ModelSeats> = {\n economy: {\n worker: 'zai/glm-5.2',\n judges: ['deepseek-v4-pro', 'zai/glm-5.2', 'google/gemini-2.5-flash'],\n analyst: 'zai/glm-5.2',\n reflection: 'zai/glm-5.2',\n verifier: 'deepseek-v4-pro',\n },\n frontier: {},\n}\n\n/** Thrown by `resolveSeat` when a seat is unset and no fallback was given. */\nexport class SeatUnsetError extends ConfigError {\n constructor(public readonly seat: SeatName) {\n super(\n `ModelSeats: seat '${seat}' is unset and no fallback was given — ` +\n 'name a model explicitly (a model id is a budget decision, never a silent default)',\n )\n }\n}\n\n/**\n * Read one seat. Blank strings and empty arrays count as unset (env-var\n * plumbing produces them); malformed values (non-string seat, non-array or\n * blank-entry `judges`) throw `ValidationError`. When the seat is unset, an\n * explicit `fallback` is returned (`[fallback]` for `judges` — a one-model\n * panel); without one, `SeatUnsetError`.\n */\nexport function resolveSeat(seats: ModelSeats, seat: 'judges', fallback?: string): string[]\nexport function resolveSeat(\n seats: ModelSeats,\n seat: Exclude<SeatName, 'judges'>,\n fallback?: string,\n): string\nexport function resolveSeat(seats: ModelSeats, seat: SeatName, fallback?: string): string | string[]\nexport function resolveSeat(\n seats: ModelSeats,\n seat: SeatName,\n fallback?: string,\n): string | string[] {\n const value = seats[seat]\n if (seat === 'judges') {\n if (value !== undefined && !Array.isArray(value)) {\n throw new ValidationError(`ModelSeats: seat 'judges' must be a string[], got ${typeof value}`)\n }\n const models = Array.isArray(value) ? value : []\n if (models.length > 0) {\n const blank = models.findIndex((m) => typeof m !== 'string' || m.trim() === '')\n if (blank >= 0) {\n throw new ValidationError(\n `ModelSeats: judges[${blank}] is blank — every panel model must be a non-empty id`,\n )\n }\n return [...models]\n }\n } else {\n if (value !== undefined && typeof value !== 'string') {\n throw new ValidationError(`ModelSeats: seat '${seat}' must be a string, got ${typeof value}`)\n }\n if (typeof value === 'string' && value.trim() !== '') return value\n }\n if (fallback !== undefined) {\n if (fallback.trim() === '') {\n throw new ValidationError(`ModelSeats: fallback for seat '${seat}' is blank`)\n }\n return seat === 'judges' ? [fallback] : fallback\n }\n throw new SeatUnsetError(seat)\n}\n","/**\n * Versioned prompt registry.\n *\n * Every prompt used in an eval run is registered with an explicit version.\n * Reports include the content hash so A/B compares are rigorous: if the\n * hash changes between two reports, the prompt actually changed; if it\n * matches, the variance is elsewhere.\n *\n * Hash is SHA-256(content), truncated to 12 hex chars for readability.\n * Uses the Web Crypto API (works in Workers, Node 22+, browsers).\n */\n\nexport interface PromptHandle {\n /** Stable human-readable id, e.g. 'browser.system' */\n id: string\n /** Caller-chosen version string, e.g. 'v3' or '2026-04-20' */\n version: string\n /** SHA-256 of content, 12-hex-char prefix */\n hash: string\n /** Full prompt body */\n content: string\n}\n\nexport class PromptRegistry {\n private readonly entries = new Map<string, PromptHandle>() // `${id}@${version}` → handle\n\n /**\n * Register a prompt. Re-registering the same id+version with DIFFERENT\n * content throws — versions are immutable. Re-registering with the SAME\n * content is a no-op (idempotent).\n */\n async register(id: string, version: string, content: string): Promise<PromptHandle> {\n validateId(id)\n validateVersion(version)\n\n const key = makeKey(id, version)\n const hash = await hashContent(content)\n const existing = this.entries.get(key)\n if (existing) {\n if (existing.hash !== hash) {\n throw new Error(\n `Prompt ${key} already registered with a different hash (${existing.hash} vs ${hash}). Bump the version.`,\n )\n }\n return existing\n }\n const handle: PromptHandle = { id, version, hash, content }\n this.entries.set(key, handle)\n return handle\n }\n\n /** Look up a registered prompt. Throws if unknown — no implicit defaults. */\n get(id: string, version: string): PromptHandle {\n const key = makeKey(id, version)\n const handle = this.entries.get(key)\n if (!handle) throw new Error(`Prompt ${key} not registered`)\n return handle\n }\n\n /** Return all versions of an id, newest-first (lex-descending on version). */\n listVersions(id: string): PromptHandle[] {\n return [...this.entries.values()]\n .filter((h) => h.id === id)\n .sort((a, b) => b.version.localeCompare(a.version))\n }\n\n /** Snapshot the whole registry — useful for including in reports. */\n list(): PromptHandle[] {\n return [...this.entries.values()]\n }\n\n /** Verify a hash against registered content. Returns null if not found. */\n verifyHash(id: string, version: string, expectedHash: string): boolean | null {\n const handle = this.entries.get(makeKey(id, version))\n if (!handle) return null\n return handle.hash === expectedHash\n }\n}\n\n/** SHA-256(content) → first 12 hex chars. Stable across runtimes. */\nexport async function hashContent(content: string): Promise<string> {\n const bytes = new TextEncoder().encode(content)\n const digest = await crypto.subtle.digest('SHA-256', bytes)\n const full = Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return full.slice(0, 12)\n}\n\nfunction makeKey(id: string, version: string): string {\n return `${id}@${version}`\n}\n\nconst ID_RE = /^[a-z][a-z0-9._-]*$/i\nfunction validateId(id: string): void {\n if (!ID_RE.test(id)) {\n throw new Error(`Invalid prompt id \"${id}\": must match ${ID_RE}`)\n }\n}\n\nfunction validateVersion(version: string): void {\n if (!version || version.length > 64) {\n throw new Error(`Invalid version \"${version}\": must be 1–64 chars`)\n }\n}\n","import { aggregateRunScore, type RunScore, type RunScoreWeights } from './run-score'\nimport type { SteeringBundle } from './steering'\n\nexport type SteeringOptimizerBackend = 'pairwise'\n\nexport interface SteeringOptimizationRow {\n variantId: string\n scenarioId: string\n bundle: SteeringBundle\n score: RunScore\n metadata?: Record<string, unknown>\n}\n\nexport interface SteeringOptimizationSelector {\n backend: SteeringOptimizerBackend\n signature?: string\n labels?: string[]\n rationale?: string\n}\n\nexport interface SteeringOptimizationResult {\n backend: SteeringOptimizerBackend\n recommendedVariantId: string\n rationale: string\n rankings: Array<{ variantId: string; mean: number; runs: number }>\n selector?: SteeringOptimizationSelector\n skipped?: boolean\n}\n\nexport interface SteeringOptimizerConfig {\n weights?: Partial<RunScoreWeights>\n}\n\n/**\n * Rank already-evaluated steering variants.\n *\n * Model-backed candidate generation belongs to the official GEPA campaign\n * integration. This class only performs the deterministic selection it owns.\n */\nexport class PairwiseSteeringOptimizer {\n optimize(\n rows: SteeringOptimizationRow[],\n config: SteeringOptimizerConfig = {},\n ): SteeringOptimizationResult {\n const rankings = rankRows(rows, config.weights)\n if (rankings.length === 0) throw new Error('no steering optimization rows')\n return {\n backend: 'pairwise',\n recommendedVariantId: rankings[0]!.variantId,\n rationale: `Highest observed mean aggregate across ${rows.length} scored run(s).`,\n rankings,\n }\n }\n}\n\nfunction rankRows(\n rows: readonly SteeringOptimizationRow[],\n weights?: Partial<RunScoreWeights>,\n): Array<{ variantId: string; mean: number; runs: number }> {\n const buckets = new Map<string, number[]>()\n for (const row of rows) {\n const values = buckets.get(row.variantId) ?? []\n values.push(aggregateRunScore(row.score, weights))\n buckets.set(row.variantId, values)\n }\n return [...buckets.entries()]\n .map(([variantId, values]) => ({\n variantId,\n mean: values.reduce((sum, value) => sum + value, 0) / values.length,\n runs: values.length,\n }))\n .sort((a, b) => b.mean - a.mean)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["packageVersion","fsConstants","fs","DEFAULT_FALLBACK_INSTRUCTION","clamp01","expectString","expectStringArray","clamp01","clamp01","isObject","packageVersion","packageVersion"],"sources":["../src/profile/baselines.ts","../src/profile/index.ts","../src/verification-strategy.ts","../src/budget-guard.ts","../src/feedback-trajectory.ts","../src/scorecard.ts","../src/trace-contracts.ts","../src/active-learning.ts","../src/deprecation.ts","../src/client.ts","../src/command-runner.ts","../src/detectors/index.ts","../src/control-runtime.ts","../src/discover-personas.ts","../src/propose-review.ts","../src/propose-review-control.ts","../src/analyst/steer-firewall.ts","../src/analyst/policy-edit.ts","../src/capability-headroom.ts","../src/cost-tracker.ts","../src/error-count-extractor.ts","../src/knowledge/readiness.ts","../src/leaderboard.ts","../src/partition-held-out.ts","../src/product-benchmark/export.ts","../src/product-benchmark/index.ts","../src/runtime-trajectory.ts","../src/action-policy.ts","../src/deploy-gate-layer.ts","../src/held-out-gate.ts","../src/hidden-criteria-grading.ts","../src/integrity/single-backend.ts","../src/intent-match-judge.ts","../src/judge-ensemble.ts","../src/judge-retry.ts","../src/judge-panel.ts","../src/keyword-coverage-judge.ts","../src/multi-layer-verifier.ts","../src/oracle.ts","../src/treatment-gate.ts","../src/anti-slop.ts","../src/eval-trace-store.ts","../src/integrity/preflight.ts","../src/model-seats.ts","../src/prompt-registry.ts","../src/steering-optimizer.ts"],"sourcesContent":["/**\n * Strong, generically-useful baseline ROLES — the top zone of an `AgentProfile`\n * before any domain layer. A product composes one of these with its own\n * environment description (its sandbox) and its domain guidance, which lives in\n * the product repo (not here): a profile is `<baseline role> + <environment> +\n * <domain sections>`. Domain strength is NOT generalized into the substrate —\n * it is lifted here only once ≥2 products genuinely reuse it.\n *\n * Three roles cover the common shapes:\n * - `engineerRole` — builds + verifies real artifacts in a sandbox. Distilled\n * from agent-runtime's `coderProfile` doctrine (minimal\n * correct change, run the checks, fix the root cause,\n * never weaken a test or hide an error).\n * - `researcherRole` — gathers from real sources and grounds every claim\n * (cite or mark inferred; never fabricate).\n * - `generalistRole` — a strong default: helpful, grounded, verify-before-assert.\n *\n * All three are verification-first and domain-agnostic. They describe HOW a\n * capable IC operates, not WHAT domain it works in.\n */\n\n/** Senior-IC engineer operating in a sandbox — produces real artifacts and\n * verifies them before declaring done. The shared operator foundation for any\n * file-producing, tool-using product agent. */\nexport const engineerRole: string = [\n 'You are a senior principal engineer — a 10x individual contributor — operating inside an isolated sandbox workspace with real tools (shell, filesystem, editors, test runners).',\n 'You do not behave like a chatbot that describes work. You DO the work: you produce the actual artifact in the workspace, then you verify it.',\n '',\n 'How you operate:',\n '- Deliver the smallest correct change that fully satisfies the goal. Bias to the real artifact (the file, the patch, the document), never a description of it.',\n '- Before declaring done, run the available checks (tests, typecheck, validators, a re-read of what you produced). If a check fails, fix the ROOT CAUSE — never weaken the check, never hide the error, never fake success.',\n '- External-boundary calls (shell, network, filesystem) can fail. Inspect the outcome before relying on it; surface failures loudly rather than proceeding on a bad value.',\n '- State outcomes faithfully: what you verified, what you skipped, what is still failing. \"Done\" means produced AND verified.',\n].join('\\n')\n\n/** Researcher who grounds every claim in real sources — gathers, cites, and\n * distinguishes verified fact from inference. */\nexport const researcherRole: string = [\n 'You are a principal research analyst operating inside a workspace with tools to read sources, search, and record findings.',\n 'Your output is only as good as its grounding. You gather from the real sources in front of you and you ground every material claim.',\n '',\n 'How you operate:',\n '- Read the actual sources before concluding. Do not answer from memory when a source is available to check.',\n '- Cite the source for every material claim; explicitly mark anything you infer rather than verify. Never fabricate a source, a quote, a number, or a citation.',\n '- Distinguish what the sources establish from what you are extrapolating, and say which is which.',\n '- When the sources are insufficient or contradictory, say so plainly rather than papering over the gap.',\n].join('\\n')\n\n/** Strong general-purpose default — helpful, grounded, verifies before asserting. */\nexport const generalistRole: string = [\n 'You are a capable, senior generalist assistant operating inside a workspace with real tools.',\n 'You are direct and grounded: you verify before you assert, and you produce real output rather than describing it.',\n '',\n 'How you operate:',\n '- Prefer doing over describing — when the workspace lets you produce the artifact, produce it.',\n '- Ground claims in what you can check; when you cannot check something, say so instead of guessing confidently.',\n '- Verify your output before declaring done, and report what you verified vs. what remains uncertain.',\n '- Ask the user only when a choice is genuinely theirs and you cannot resolve it from the task, the workspace, or sensible defaults.',\n].join('\\n')\n\n/** The named baseline roles, for selection by key (e.g. from a product config). */\nexport const BASELINE_ROLES = {\n engineer: engineerRole,\n researcher: researcherRole,\n generalist: generalistRole,\n} as const\n\nexport type BaselineRoleKey = keyof typeof BASELINE_ROLES\n","/**\n * Structured prompt profile — the system prompt as named, addressable sections\n * instead of one opaque blob. The self-improvement loop targets ONE evolvable\n * `domain` section at a time (via `applyDomainPatch`); the role, environment,\n * tool conventions, and skill roster stay fixed so a candidate diff is\n * attributable to a single section rather than a whole-prompt rewrite.\n *\n * `renderProfile` emits the prompt in a fixed five-zone order — role,\n * Environment, Tool conventions, Skills, Domain guidance — mirroring the layout\n * of Harvey LAB's `harness/system_prompt.md` (workspace root, read-only\n * documents, output dir, skills dir). `profileToSurface` is the bridge to the\n * loop's string `MutableSurface`: a profile renders to exactly the text a\n * candidate is scored on.\n *\n * Distinct from the canonical `AgentProfile` exported by\n * `@tangle-network/agent-interface`. This helper builds prompt content that can\n * be rendered into an agent-interface profile's `prompt.systemPrompt`.\n */\n\nimport { surfaceContentHash } from '../campaign/surface-identity'\nimport { BASELINE_ROLES, type BaselineRoleKey } from './baselines'\n\nexport {\n BASELINE_ROLES,\n type BaselineRoleKey,\n engineerRole,\n generalistRole,\n researcherRole,\n} from './baselines'\n\n/** A named, addressable region of the system prompt. `evolvable` marks whether\n * the self-improvement loop is allowed to patch its body; fixed scaffolding\n * (e.g. a compliance preamble) sets `evolvable: false`. */\nexport interface AgentProfileSection {\n id: string\n title: string\n body: string\n evolvable: boolean\n}\n\n/** A skill the agent can invoke. `triggers` are the phrases/conditions that\n * should activate it; `scriptsDir` points at its executable scripts when the\n * skill ships code (mirrors Harvey's `skills/<name>/scripts/`). */\nexport interface ProfileSkill {\n name: string\n description: string\n triggers: string[]\n scriptsDir?: string\n}\n\n/** The structured system prompt. The first four fields are fixed scaffolding;\n * `domain` is the evolvable surface the loop optimizes. */\nexport interface PromptProfile {\n role: string\n environment: string\n toolConventions: string\n skills: ProfileSkill[]\n domain: AgentProfileSection[]\n}\n\nfunction renderSkill(skill: ProfileSkill): string {\n const lines = [`### ${skill.name}`, skill.description]\n if (skill.triggers.length > 0) {\n lines.push(`Triggers: ${skill.triggers.join(', ')}`)\n }\n if (skill.scriptsDir !== undefined) {\n lines.push(`Scripts: ${skill.scriptsDir}`)\n }\n return lines.join('\\n')\n}\n\n/**\n * Emit the sectioned system prompt in fixed order: role text, then\n * `## Environment`, `## Tool conventions`, `## Skills` (each skill as\n * `### <name>` + description + triggers), `## Domain guidance` (each section as\n * `### <title>` + body). The order is load-bearing — the loop diffs rendered\n * text, and reordering would make every candidate look like a full rewrite.\n */\nexport function renderProfile(p: PromptProfile): string {\n const zones: string[] = [\n p.role.trim(),\n `## Environment\\n\\n${p.environment.trim()}`,\n `## Tool conventions\\n\\n${p.toolConventions.trim()}`,\n `## Skills\\n\\n${\n p.skills.length > 0 ? p.skills.map(renderSkill).join('\\n\\n') : '_No skills configured._'\n }`,\n `## Domain guidance\\n\\n${\n p.domain.length > 0\n ? p.domain.map((s) => `### ${s.title}\\n\\n${s.body.trim()}`).join('\\n\\n')\n : '_No domain guidance yet._'\n }`,\n ]\n return zones.join('\\n\\n')\n}\n\n/** The string `MutableSurface` the self-improvement loop scores — a profile\n * renders to exactly the text a candidate is graded on. */\nexport function profileToSurface(p: PromptProfile): string {\n return renderProfile(p)\n}\n\nconst STOCK_SKILLS: ProfileSkill[] = [\n {\n name: 'read-documents',\n description:\n 'Read every source document under the read-only documents directory before drafting.',\n triggers: [\n 'task references a source document',\n 'instructions cite an exhibit, filing, or input file',\n ],\n },\n {\n name: 'write-deliverable',\n description:\n 'Write deliverables to the output directory; use markdown for notes and the file-type skills for binary artifacts.',\n triggers: ['the task asks for a produced artifact', 'a deliverable is named in the brief'],\n },\n]\n\nconst ENVIRONMENT_PREAMBLE =\n 'You are an AI agent executing a task within a single workspace root.\\n\\n' +\n '- Workspace root: bash starts here. Use it for notes, scratch files, and intermediate work.\\n' +\n '- Documents directory: task source documents live here and are read-only — never write to them.\\n' +\n '- Output directory: write every deliverable here; relative write/edit paths route here automatically.\\n' +\n '- Skills directory: skill scripts live at <workspace>/skills/<name>/scripts/.'\n\nconst TOOL_CONVENTIONS_PREAMBLE =\n 'Use read to consume input files. Use write only for plain markdown (typically a response summary). ' +\n 'Use edit for incremental refinement of a file you already created. ' +\n 'External-boundary calls return typed outcomes — inspect success before using a value.'\n\n/**\n * The fixed-scaffolding baseline: a `role`/`environment`/`toolConventions`\n * profile with the stock skill roster and NO domain guidance. The\n * production profile is this plus shipped domain sections.\n */\nexport function baselineProfile(args: {\n role: string\n environment?: string\n toolConventions?: string\n skills?: ProfileSkill[]\n}): PromptProfile {\n return {\n role: args.role,\n environment: args.environment ?? ENVIRONMENT_PREAMBLE,\n toolConventions: args.toolConventions ?? TOOL_CONVENTIONS_PREAMBLE,\n skills: args.skills ?? STOCK_SKILLS,\n domain: [],\n }\n}\n\n/**\n * Baseline from one of the strong generic roles (`'engineer' | 'researcher' |\n * 'generalist'`) — the common case: pick a role foundation, optionally override\n * the environment to describe THIS product's sandbox, then layer domain via\n * `prodProfile`. Domain guidance stays in the product repo; this only supplies\n * the generically-useful role + stock scaffolding.\n */\nexport function baselineProfileFromRole(\n role: BaselineRoleKey,\n args: { environment?: string; toolConventions?: string; skills?: ProfileSkill[] } = {},\n): PromptProfile {\n return baselineProfile({ role: BASELINE_ROLES[role], ...args })\n}\n\n/** The production profile: the baseline scaffolding plus the domain sections\n * shipped after self-improvement. Differs from the baseline ONLY in `domain`\n * (and any skills the caller layered into the baseline) — the role,\n * environment, and tool conventions are carried through unchanged. */\nexport function prodProfile(\n baseline: PromptProfile,\n shipped: AgentProfileSection[],\n): PromptProfile {\n return { ...baseline, domain: [...baseline.domain, ...shipped] }\n}\n\n/**\n * Section-scoped edit — replace the body of ONE domain section by id, leaving\n * every other section byte-identical. This is how the loop targets a single\n * evolvable surface. Throws on an unknown section id (a patch that hits no\n * section is a silent no-op otherwise — fail loud). Throws when the targeted\n * section is `evolvable: false`.\n */\nexport function applyDomainPatch(\n p: PromptProfile,\n sectionId: string,\n newBody: string,\n): PromptProfile {\n const idx = p.domain.findIndex((s) => s.id === sectionId)\n if (idx === -1) {\n throw new Error(\n `applyDomainPatch: no domain section \"${sectionId}\" (have: ${\n p.domain.map((s) => s.id).join(', ') || '<none>'\n })`,\n )\n }\n const target = p.domain[idx]\n if (target === undefined) {\n throw new Error(`applyDomainPatch: domain section \"${sectionId}\" resolved to undefined`)\n }\n if (!target.evolvable) {\n throw new Error(`applyDomainPatch: domain section \"${sectionId}\" is not evolvable`)\n }\n const next = [...p.domain]\n next[idx] = { ...target, body: newBody }\n return { ...p, domain: next }\n}\n\n/**\n * Content hash of a single section — its loop identity. Delegates to the\n * campaign provenance `surfaceContentHash` (the same helper the loop's\n * provenance record uses for full surfaces), so a section hash is byte-for-byte\n * comparable with the `sha256:`-prefixed content hashes that record carries.\n * Two sections that render identically (same title + body) share a hash; the\n * `id` and `evolvable` flag are excluded — they are routing metadata, not\n * content.\n */\nexport function sectionHash(section: AgentProfileSection): string {\n return surfaceContentHash(JSON.stringify({ title: section.title, body: section.body }))\n}\n","/**\n * Verification-strategy family — the shared vocabulary for \"what certified\n * this result\", covering tasks with an answer key and tasks without one.\n *\n * Charter Wave 5 (docs/charter.md): an unsolved problem has no held-out\n * suite by definition, so the held-out suite must be ONE member of a\n * strategy family, not the family itself. This module carries the taxonomy,\n * the port shape, and the one protocol built directly on that port: the\n * blind two-arm statement-equivalence check. A checker is an injected\n * executable boundary that returns a typed outcome, so a consumer binds its\n * own kernel (a Lean toolchain, a metamorphic harness, a replication\n * runner) and this package never chooses one. Instruments, never methods.\n *\n * Full family doc, per-member failure modes in prose, and the BCWW pilot\n * worked example: docs/verification-strategies.md. How every executed\n * verdict lands in `DefaultVerdict` with a certification: docs/verdicts.md.\n *\n * Leaf module: no imports from this package. `src/verdict.ts` and\n * `src/rl/verifiable-reward.ts` both build on these types.\n */\n\n/**\n * One member of the verification-strategy family.\n *\n * Every member has a documented failure mode — the specific way it can\n * certify a wrong result. A consumer that reads a certification must weigh\n * the member's failure mode, not treat \"certified\" as one bit.\n *\n * - `'compile'` — typecheck / build / lint passed. Deterministic.\n * Failure mode: code that compiles is not code that is correct; the\n * weakest deterministic member.\n * - `'test'` — unit / integration / held-out suite pass-rate. Deterministic.\n * Failure mode: assumes an answer key exists; certifies nothing outside\n * the suite's coverage, and a stubbed integration reports green.\n * - `'schema'` — structured output validates. Deterministic.\n * Failure mode: shape is not meaning; a well-formed wrong answer passes.\n * - `'sandbox'` — sandbox execution exit code. Deterministic.\n * Failure mode: an exit code compresses the whole run to one bit; a\n * faked success exits 0.\n * - `'judge'` — LLM judge score. Probabilistic.\n * Failure mode: drifts across model versions and is Goodhart-gameable by\n * the graded policy.\n * - `'composite'` — weighted blend across members. Determinism inherited\n * from its members.\n * Failure mode: scalar collapse — the blend hides which member carried\n * the score and which failed.\n * - `'proof-kernel'` — a proof assistant's kernel accepted a formal proof.\n * Deterministic.\n * Failure mode: the formalization gap. The kernel certifies the formal\n * statement, never that the formal statement matches the informal claim;\n * a proved theorem about the wrong statement is a wrong result with a\n * valid certificate. Discharge it with the blind statement-equivalence\n * protocol (`runEquivalenceCheck` in this module).\n * - `'invariant'` — invariant / metamorphic properties held on the result.\n * Deterministic.\n * Failure mode: weak invariants pass everything. An invariant set earns\n * weight only through seeded-bug calibration — a mutation the set\n * provably rejects; an uncalibrated set is a rubber stamp.\n * - `'replication'` — an independent re-execution reproduced the result\n * from pinned inputs. Deterministic given the pins.\n * Failure mode: replication re-runs the method, so it catches\n * nondeterminism and environment drift, never a methodological error the\n * method itself carries.\n * - `'agreement'` — independently-derived results agree. Probabilistic.\n * Failure mode: the shared blind spot. Derivers that share training\n * corpora, priors, or the same misread of the source agree for the same\n * wrong reason; the blindness provenance of each arm is what the\n * certificate rests on.\n */\nexport type VerificationStrategySource =\n | 'compile'\n | 'test'\n | 'schema'\n | 'sandbox'\n | 'judge'\n | 'composite'\n | 'proof-kernel'\n | 'invariant'\n | 'replication'\n | 'agreement'\n\n/**\n * What a strategy member can honestly claim about its outcomes.\n *\n * `determinism: 'inherited'` exists only for `'composite'`: a blend takes\n * the class of its members. The reward axis stays binary\n * (`VerifiableReward.determinism`); this registry describes the family,\n * it never scores a run.\n */\nexport interface VerificationStrategyProfile {\n /** Determinism class a well-formed checker of this member can claim. */\n determinism: 'deterministic' | 'probabilistic' | 'inherited'\n /** The documented way this member certifies a wrong result. */\n failureMode: string\n}\n\n/**\n * The family registry. `Record` over the union keeps it exhaustive: adding\n * a member to `VerificationStrategySource` without a profile here fails to\n * compile. The failure mode travels with the taxonomy so a reader of a\n * certification can surface it without this package's docs at hand.\n */\nexport const VERIFICATION_STRATEGIES: Record<\n VerificationStrategySource,\n VerificationStrategyProfile\n> = {\n compile: {\n determinism: 'deterministic',\n failureMode: 'code that compiles is not code that is correct',\n },\n test: {\n determinism: 'deterministic',\n failureMode:\n 'assumes an answer key; certifies nothing outside suite coverage, and a stubbed integration reports green',\n },\n schema: {\n determinism: 'deterministic',\n failureMode: 'shape is not meaning; a well-formed wrong answer passes',\n },\n sandbox: {\n determinism: 'deterministic',\n failureMode: 'an exit code compresses the run to one bit; a faked success exits 0',\n },\n judge: {\n determinism: 'probabilistic',\n failureMode: 'drifts across model versions and is Goodhart-gameable by the graded policy',\n },\n composite: {\n determinism: 'inherited',\n failureMode: 'scalar collapse: the blend hides which member carried the score',\n },\n 'proof-kernel': {\n determinism: 'deterministic',\n failureMode:\n 'the formalization gap: the kernel certifies the formal statement, never that it matches the informal claim',\n },\n invariant: {\n determinism: 'deterministic',\n failureMode:\n 'weak invariants pass everything; a set uncalibrated by seeded bugs is a rubber stamp',\n },\n replication: {\n determinism: 'deterministic',\n failureMode:\n 're-runs the method, so it catches drift and nondeterminism, never an error the method itself carries',\n },\n agreement: {\n determinism: 'probabilistic',\n failureMode:\n 'the shared blind spot: derivers with common corpora or priors agree for the same wrong reason',\n },\n}\n\n/** Every family member, derived from the registry so it cannot drift. */\nexport const VERIFICATION_STRATEGY_SOURCES = Object.keys(\n VERIFICATION_STRATEGIES,\n) as readonly VerificationStrategySource[]\n\n/**\n * Exact identity of the thing that checked. \"lean4 4.33.0 with Mathlib\n * db584cd6d46c\" and \"lean4, some version\" are different certificates: the\n * first is re-runnable, the second is a story.\n */\nexport interface CheckerIdentity {\n /** Toolchain or model name, e.g. `'lean4'` or a judge model id. */\n name: string\n /** Exact version or snapshot, e.g. `'4.33.0'` or a model snapshot id. */\n version: string\n /**\n * Content pins the version alone does not capture, e.g.\n * `{ mathlib: 'db584cd6d46c' }`. Keyed by dependency name.\n */\n pins?: Record<string, string>\n}\n\n/**\n * Typed outcome of an external checker call. Callers MUST inspect\n * `succeeded` before touching `value`; a failed check keeps its full error\n * text instead of collapsing to null.\n */\nexport type CheckerOutcome<Result> =\n | { succeeded: true; value: Result }\n | { succeeded: false; error: string }\n\n/**\n * The port shape every strategy binds through: an injected executable\n * boundary. This package defines the port and refuses to ship any\n * implementation behind it — the consumer binds its own kernel, invariant\n * harness, replication runner, or judge, and the binding carries its own\n * identity and determinism claim.\n *\n * A checker that ran but could not decide returns\n * `{ succeeded: false, error }` with the reason; `succeeded: true` is\n * reserved for a discharged check.\n */\nexport interface StrategyChecker<Input, Result> {\n /** Which family member this checker discharges obligations for. */\n strategy: VerificationStrategySource\n identity: CheckerIdentity\n /** Determinism class this checker claims for its outcomes. */\n determinism: 'deterministic' | 'probabilistic'\n check(input: Input): Promise<CheckerOutcome<Result>>\n}\n\n// ── Blind statement-equivalence protocol ─────────────────────────────\n\n/**\n * Statement-equivalence protocol — the blind two-arm design as a typed\n * primitive.\n *\n * The problem it closes is the proof-kernel failure mode (the\n * formalization gap): a kernel certifies a formal statement, never that\n * the formal statement matches the informal claim. The protocol makes the\n * gap measurable: two arms derive the formal statement independently and\n * blind to each other, then a checker discharges the obligation that the\n * two statements are equivalent. A statement mismatch is a successful\n * outcome — it is the formalization gap made visible with a separating\n * witness in hand.\n *\n * The protocol is pure contract + record types + the asymmetry refusals.\n * Execution binds through the same `StrategyChecker` port as every other\n * strategy: the consumer injects its own kernel. The pilot record this\n * shape reproduces was assembled by hand for the BCWW (4.6) inequality;\n * docs/verification-strategies.md carries the worked example with artifact\n * paths. `equivalenceVerdict` (src/verdict.ts) lands a finished record in\n * the shared verdict spine.\n *\n * The refusals are the design. An arm that saw the other arm's statement,\n * or the outcome it feeds, did not independently derive anything — the\n * check is invalid, and this module throws rather than record it.\n */\n\n/**\n * The two-arm blind design. `arms: 2` and `blind: true` are literal types\n * on purpose: a wider design is a different protocol, not a parameter.\n */\nexport interface EquivalenceCheckSpec {\n /**\n * The strategy member whose obligation the check discharges — the pilot\n * used `'proof-kernel'`: the Lean kernel proved the two statements\n * equivalent. The bound checker must declare the same member.\n */\n source: VerificationStrategySource\n /**\n * Stable identity of the claim under verification: a path, digest, or\n * citation. Pilot: arXiv:1507.05650 inequality (4.6) plus the\n * five-atom counterexample record.\n */\n artifact: string\n /** Exactly two independent arms. An N-arm design is not this protocol. */\n arms: 2\n /**\n * Blind derivation is the point: a non-blind run is not a weaker check,\n * it is no check. `false` is unrepresentable here and refused at runtime\n * for untyped callers.\n */\n blind: true\n}\n\n/** A validated, frozen spec. Produced only by `defineEquivalenceCheck`. */\nexport interface EquivalenceCheckDefinition {\n readonly spec: Readonly<EquivalenceCheckSpec>\n}\n\n/** One arm's committed statement plus the provenance the record rests on. */\nexport interface EquivalenceArm {\n armId: string\n /** The committed formal statement text (pilot: the arm's `Statement.lean` source). */\n statement: string\n /**\n * What this arm derived the statement from. Pilot arm A: the paper's\n * LaTeX source; pilot arm B: the campaign's artifacts. The two arms\n * SHOULD derive from different renderings of the claim — that is what\n * makes agreement informative.\n */\n derivedFrom: string\n /**\n * The blindness declaration. Both flags must be `true`; a `false` value\n * is refused loudly, because recording a non-blind arm would launder an\n * invalid check into a valid-looking record.\n */\n blindness: {\n /** This arm never saw any other arm's statement before committing its own. */\n toOtherArms: boolean\n /** This arm never saw the verification outcome before committing. */\n toOutcome: boolean\n }\n}\n\nexport type EquivalenceObligationStatus =\n | 'proved'\n | 'refuted-with-separating-witness'\n | 'unresolved'\n\n/**\n * The discharged (or undischarged) equivalence obligation.\n *\n * Field presence is status-dependent and enforced by\n * `buildEquivalenceRecord`:\n * - `'proved'` requires `evidenceDigest` and forbids `separatingWitness`.\n * - `'refuted-with-separating-witness'` requires both the witness and\n * `evidenceDigest`.\n * - `'unresolved'` requires `unresolvedReason` and forbids the witness —\n * an undischarged obligation keeps its diagnostic instead of faking\n * either verdict.\n */\nexport interface EquivalenceObligation {\n status: EquivalenceObligationStatus\n /** The input on which the two statements provably disagree. */\n separatingWitness?: string\n /** Why the obligation could not be discharged (checker error text, coverage limit). */\n unresolvedReason?: string\n /** The checker that ran (or failed to run) the obligation. */\n checker: CheckerIdentity\n /** Digest of the checker's evidence artifact (pilot: the kernel-checked `Check.lean` run). */\n evidenceDigest?: string\n}\n\n/** The record the protocol produces — the by-hand pilot record, typed. */\nexport interface EquivalenceRecord {\n spec: Readonly<EquivalenceCheckSpec>\n arms: readonly [EquivalenceArm, EquivalenceArm]\n obligation: EquivalenceObligation\n}\n\n/** Input the bound checker receives: the artifact identity and both committed statements. */\nexport interface EquivalenceCheckerInput {\n artifact: string\n statements: readonly [string, string]\n}\n\n/**\n * What a checker that RAN must return. `'unresolved'` is deliberately not\n * a checker result: a checker that could not decide returns\n * `{ succeeded: false, error }` through the port, and the protocol records\n * the unresolved obligation with that reason.\n */\nexport interface EquivalenceCheckerResult {\n status: 'proved' | 'refuted-with-separating-witness'\n /** Required when `status` is refuted. */\n separatingWitness?: string\n evidenceDigest: string\n}\n\n/** An equivalence checker is a `StrategyChecker` — same port as every strategy. */\nexport type EquivalenceChecker = StrategyChecker<EquivalenceCheckerInput, EquivalenceCheckerResult>\n\n/** A refused equivalence check. `code` names the exact refusal for programmatic handling. */\nexport class EquivalenceProtocolError extends Error {\n readonly code:\n | 'arm-count'\n | 'not-blind'\n | 'arm-saw-other'\n | 'arm-saw-outcome'\n | 'duplicate-arm-id'\n | 'empty-field'\n | 'unknown-source'\n | 'witness-missing'\n | 'witness-on-proved'\n | 'witness-on-unresolved'\n | 'reason-missing'\n | 'evidence-missing'\n | 'checker-strategy-mismatch'\n\n constructor(code: EquivalenceProtocolError['code'], message: string) {\n super(message)\n this.name = 'EquivalenceProtocolError'\n this.code = code\n }\n}\n\n/**\n * Validate and freeze a two-arm blind equivalence check spec.\n *\n * The literal types already refuse a wide design at compile time; the\n * runtime checks hold the same line for untyped callers. There is no\n * escape hatch: `arms: 3` or `blind: false` throws, never downgrades.\n */\nexport function defineEquivalenceCheck(spec: EquivalenceCheckSpec): EquivalenceCheckDefinition {\n if (spec.arms !== 2) {\n throw new EquivalenceProtocolError(\n 'arm-count',\n `equivalence check requires exactly 2 arms, received ${String(spec.arms)}`,\n )\n }\n if (spec.blind !== true) {\n throw new EquivalenceProtocolError(\n 'not-blind',\n 'equivalence check requires blind: true — a non-blind run is not a weaker check, it is no check',\n )\n }\n if (typeof spec.artifact !== 'string' || spec.artifact.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n 'spec.artifact must identify the claim under verification',\n )\n }\n if (!VERIFICATION_STRATEGY_SOURCES.includes(spec.source)) {\n throw new EquivalenceProtocolError(\n 'unknown-source',\n `spec.source '${String(spec.source)}' is not a verification-strategy member`,\n )\n }\n return Object.freeze({ spec: Object.freeze({ ...spec }) })\n}\n\n/**\n * Assemble the equivalence record, refusing every asymmetry.\n *\n * Refusals (each throws `EquivalenceProtocolError`):\n * - an arm whose `blindness.toOtherArms` is false — it saw the other\n * statement, so nothing was independently derived;\n * - an arm whose `blindness.toOutcome` is false — it could steer its\n * statement toward (or away from) the known result;\n * - duplicate arm ids, empty statements, empty derivations;\n * - an obligation whose fields contradict its status (see\n * `EquivalenceObligation`).\n */\nexport function buildEquivalenceRecord(\n definition: EquivalenceCheckDefinition,\n arms: readonly [EquivalenceArm, EquivalenceArm],\n obligation: EquivalenceObligation,\n): EquivalenceRecord {\n assertArms(arms)\n assertObligation(obligation)\n return Object.freeze({\n spec: definition.spec,\n arms: Object.freeze([Object.freeze({ ...arms[0] }), Object.freeze({ ...arms[1] })] as const),\n obligation: Object.freeze({ ...obligation }),\n })\n}\n\n/**\n * Discharge the obligation through an injected checker and return the\n * record.\n *\n * Order matters: every arm refusal fires BEFORE the checker runs — an\n * invalid check must not spend. A checker whose `strategy` differs from\n * `spec.source` is refused for the same reason: a judge cannot silently\n * discharge a proof-kernel obligation.\n *\n * A checker failure (`succeeded: false`) is not thrown: it becomes an\n * `'unresolved'` obligation carrying the full error text, which is the\n * honest record of an undischarged check.\n */\nexport async function runEquivalenceCheck(\n definition: EquivalenceCheckDefinition,\n arms: readonly [EquivalenceArm, EquivalenceArm],\n checker: EquivalenceChecker,\n): Promise<EquivalenceRecord> {\n assertArms(arms)\n if (checker.strategy !== definition.spec.source) {\n throw new EquivalenceProtocolError(\n 'checker-strategy-mismatch',\n `spec.source is '${definition.spec.source}' but the bound checker declares '${checker.strategy}'`,\n )\n }\n const outcome = await checker.check({\n artifact: definition.spec.artifact,\n statements: [arms[0].statement, arms[1].statement],\n })\n if (!outcome.succeeded) {\n return buildEquivalenceRecord(definition, arms, {\n status: 'unresolved',\n unresolvedReason: outcome.error,\n checker: checker.identity,\n })\n }\n const { status, separatingWitness, evidenceDigest } = outcome.value\n return buildEquivalenceRecord(definition, arms, {\n status,\n ...(separatingWitness === undefined ? {} : { separatingWitness }),\n checker: checker.identity,\n evidenceDigest,\n })\n}\n\nfunction assertArms(arms: readonly [EquivalenceArm, EquivalenceArm]): void {\n if (arms.length !== 2) {\n throw new EquivalenceProtocolError(\n 'arm-count',\n `equivalence record requires exactly 2 arms, received ${arms.length}`,\n )\n }\n if (arms[0].armId === arms[1].armId) {\n throw new EquivalenceProtocolError(\n 'duplicate-arm-id',\n `both arms declare armId '${arms[0].armId}' — two labels for one derivation is one arm`,\n )\n }\n for (const arm of arms) {\n if (arm.statement.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n `arm '${arm.armId}' committed an empty statement`,\n )\n }\n if (arm.derivedFrom.trim() === '') {\n throw new EquivalenceProtocolError(\n 'empty-field',\n `arm '${arm.armId}' declares no derivation provenance`,\n )\n }\n if (arm.blindness.toOtherArms !== true) {\n throw new EquivalenceProtocolError(\n 'arm-saw-other',\n `arm '${arm.armId}' saw another arm's statement — the derivation is not independent and the check is invalid`,\n )\n }\n if (arm.blindness.toOutcome !== true) {\n throw new EquivalenceProtocolError(\n 'arm-saw-outcome',\n `arm '${arm.armId}' saw the outcome before committing — the check is invalid`,\n )\n }\n }\n}\n\nfunction assertObligation(obligation: EquivalenceObligation): void {\n const { status, separatingWitness, unresolvedReason, evidenceDigest } = obligation\n if (status === 'refuted-with-separating-witness') {\n if (typeof separatingWitness !== 'string' || separatingWitness.trim() === '') {\n throw new EquivalenceProtocolError(\n 'witness-missing',\n 'a refuted equivalence must carry the separating witness — a refutation without one is an assertion',\n )\n }\n if (typeof evidenceDigest !== 'string' || evidenceDigest.trim() === '') {\n throw new EquivalenceProtocolError(\n 'evidence-missing',\n 'a refuted equivalence must carry its evidence digest',\n )\n }\n return\n }\n if (status === 'proved') {\n if (separatingWitness !== undefined) {\n throw new EquivalenceProtocolError(\n 'witness-on-proved',\n 'a proved equivalence cannot carry a separating witness — the two claims contradict',\n )\n }\n if (typeof evidenceDigest !== 'string' || evidenceDigest.trim() === '') {\n throw new EquivalenceProtocolError(\n 'evidence-missing',\n 'a proved equivalence must carry its evidence digest',\n )\n }\n return\n }\n // status === 'unresolved'\n if (separatingWitness !== undefined) {\n throw new EquivalenceProtocolError(\n 'witness-on-unresolved',\n 'an unresolved obligation cannot carry a separating witness — a witness in hand is a refutation',\n )\n }\n if (typeof unresolvedReason !== 'string' || unresolvedReason.trim() === '') {\n throw new EquivalenceProtocolError(\n 'reason-missing',\n \"an unresolved obligation must say why — 'unresolved' with no reason erases the diagnostic\",\n )\n }\n}\n","/**\n * BudgetGuard — enforces token / wall-clock / call / $ caps, records\n * a ledger entry on every decrement, emits `budget_breach` + throws\n * `BudgetBreachError` when a cap is hit.\n *\n * Wraps a TraceEmitter. The emitter persists ledger entries + breach\n * events so the classifier, pipelines, and reports can all read\n * budget state from the trace corpus — no separate accounting.\n */\n\nimport { AgentEvalError } from './errors'\nimport type { TraceEmitter } from './trace/emitter'\nimport type { BudgetSpec } from './trace/schema'\n\nexport class BudgetBreachError extends AgentEvalError {\n constructor(\n public dimension: keyof BudgetSpec,\n public limit: number,\n public attempted: number,\n ) {\n super('verification', `budget breach on ${dimension}: attempted ${attempted} vs limit ${limit}`)\n }\n}\n\nexport class BudgetGuard {\n private consumed: Record<keyof BudgetSpec, number> = { tokens: 0, wallMs: 0, calls: 0, usd: 0 }\n private emitter: TraceEmitter\n private budget: BudgetSpec\n private startedAt: number\n\n constructor(emitter: TraceEmitter, budget: BudgetSpec, now: () => number = () => Date.now()) {\n this.emitter = emitter\n this.budget = budget\n this.startedAt = now()\n }\n\n /** Record consumption. Throws `BudgetBreachError` if any dimension exceeds its cap. */\n async charge(delta: Partial<Record<keyof BudgetSpec, number>>, spanId?: string): Promise<void> {\n for (const [dim, value] of Object.entries(delta) as Array<[keyof BudgetSpec, number]>) {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`BudgetGuard.charge: non-finite or negative ${dim}=${value}`)\n }\n this.consumed[dim] += value\n const limit = this.budget[dim]\n const consumed = this.consumed[dim]\n const remaining = limit === undefined ? Infinity : limit - consumed\n const breached = limit !== undefined && consumed > limit\n if (limit !== undefined) {\n await this.emitter.recordBudget({\n dimension: dim,\n limit,\n consumed,\n remaining,\n breached,\n spanId,\n })\n }\n if (breached) {\n throw new BudgetBreachError(dim, limit!, consumed)\n }\n }\n }\n\n /** Convenience: advance wall-clock budget based on elapsed wall time. */\n async tickWall(nowMs: number, spanId?: string): Promise<void> {\n const elapsed = nowMs - this.startedAt\n const already = this.consumed.wallMs\n const delta = Math.max(0, elapsed - already)\n if (delta > 0) await this.charge({ wallMs: delta }, spanId)\n }\n\n get state(): Record<keyof BudgetSpec, number> {\n return { ...this.consumed }\n }\n}\n","import type { AnalystFinding, AnalystRunResult } from './analyst/types'\nimport type { ControlEvalResult, ControlRunResult, ControlStep } from './control-runtime'\nimport type { DatasetScenario, DatasetSplit } from './dataset'\nimport {\n type AnalystReviewDecision,\n analystFindingDigest,\n analystRunDigest,\n assertUniqueFindingIds,\n completedAnalystReviewQuality,\n readAnalystReview,\n snapshotAnalystRun,\n validateAnalystReviewDecisions,\n} from './feedback-trajectory-review'\nimport { canonicalString, compareCodeUnits } from './ledger-core/canonical'\n\nexport type {\n AnalystFindingDigest,\n AnalystMissedIssue,\n AnalystReviewCounts,\n AnalystReviewDecision,\n AnalystReviewQuality,\n AnalystReviewSource,\n AnalystRunDigest,\n} from './feedback-trajectory-review'\nexport { analystFindingDigest, analystRunDigest } from './feedback-trajectory-review'\n\nexport type FeedbackArtifactType =\n | 'text'\n | 'code'\n | 'plan'\n | 'research'\n | 'action'\n | 'ui'\n | 'decision'\n | 'data'\n | 'other'\n\nexport type FeedbackLabelSource = 'user' | 'judge' | 'environment' | 'metric' | 'policy' | 'system'\n\nexport type FeedbackLabelKind =\n | 'approve'\n | 'reject'\n | 'select'\n | 'edit'\n | 'rank'\n | 'rate'\n | 'comment'\n | 'metric_outcome'\n | 'policy_block'\n | 'revision_request'\n\nexport type FeedbackSeverity = 'info' | 'warning' | 'error' | 'critical'\n\nexport interface FeedbackTask {\n intent: string\n context?: unknown\n}\n\nexport interface ProposedSideEffect {\n type: string\n risk?: 'low' | 'medium' | 'high'\n costUsd?: number\n externalSideEffect?: boolean\n requiresApproval?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackLabel {\n id?: string\n source: FeedbackLabelSource\n kind: FeedbackLabelKind\n value: unknown\n reason?: string\n severity?: FeedbackSeverity\n createdAt: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackAttempt {\n id: string\n stepIndex: number\n artifactType: FeedbackArtifactType\n artifact: unknown\n options?: unknown[]\n proposedAction?: ProposedSideEffect\n evals?: ControlEvalResult[]\n feedback?: FeedbackLabel[]\n createdAt: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackOutcome {\n success?: boolean\n score?: number\n metrics?: Record<string, number>\n costUsd?: number\n detail?: string\n observedAt?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTrajectory {\n id: string\n projectId?: string\n scenarioId?: string\n task: FeedbackTask\n attempts: FeedbackAttempt[]\n labels: FeedbackLabel[]\n outcome?: FeedbackOutcome\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt: string\n updatedAt?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTrajectoryStore {\n save(trajectory: FeedbackTrajectory): Promise<void>\n get(id: string): Promise<FeedbackTrajectory | null>\n list(filter?: FeedbackTrajectoryFilter): Promise<FeedbackTrajectory[]>\n appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory>\n appendLabel(id: string, label: FeedbackLabel, attemptId?: string): Promise<FeedbackTrajectory>\n}\n\nexport interface FeedbackTrajectoryFilter {\n projectId?: string\n scenarioId?: string\n split?: DatasetSplit\n tag?: [string, string]\n}\n\nexport interface FeedbackSplitPolicy {\n trainPct?: number\n devPct?: number\n testPct?: number\n holdoutPct?: number\n}\n\nexport interface PreferenceMemoryEntry {\n instruction: string\n rationale: string\n weight: number\n sourceTrajectoryId: string\n sourceLabelId?: string\n category?: string\n}\n\nexport interface FeedbackOptimizerRow {\n scenarioId: string\n trajectoryId: string\n labelKinds: FeedbackLabelKind[]\n score?: number\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackReplayResult {\n trajectoryId: string\n pass: boolean\n score?: number\n labels: FeedbackLabel[]\n outcome?: FeedbackOutcome\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackReplayAdapter {\n replay(\n trajectory: FeedbackTrajectory,\n ):\n | Promise<Omit<FeedbackReplayResult, 'trajectoryId'>>\n | Omit<FeedbackReplayResult, 'trajectoryId'>\n}\n\nexport interface AnalystFeedbackTrajectoryOptions {\n task: FeedbackTask\n labels?: readonly FeedbackLabel[]\n reviewRequests?: readonly AnalystReviewRequest[]\n reviewDecisions?: readonly AnalystReviewDecision[]\n outcome?: FeedbackOutcome\n id?: string\n projectId?: string\n scenarioId?: string\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt?: string\n trace?: {\n source?: string\n traceIds?: readonly string[]\n artifactUri?: string\n }\n metadata?: Record<string, unknown>\n}\n\nexport interface AnalystReviewRequest {\n id: string\n runId: string\n runDigest: `sha256:${string}`\n findingId: string\n findingDigest: `sha256:${string}`\n analystId: string\n area: string\n claim: string\n evidence: AnalystFinding['evidence_refs']\n recommendedAction?: string\n validationPlan?: string\n severity: FeedbackSeverity\n confidence: number\n createdAt: string\n}\n\nconst DEFAULT_SPLIT_POLICY: Required<FeedbackSplitPolicy> = {\n trainPct: 70,\n devPct: 15,\n testPct: 10,\n holdoutPct: 5,\n}\n\nexport class InMemoryFeedbackTrajectoryStore implements FeedbackTrajectoryStore {\n private readonly trajectories = new Map<string, FeedbackTrajectory>()\n\n async save(trajectory: FeedbackTrajectory): Promise<void> {\n this.trajectories.set(trajectory.id, cloneTrajectory(trajectory))\n }\n\n async get(id: string): Promise<FeedbackTrajectory | null> {\n const trajectory = this.trajectories.get(id)\n return trajectory ? cloneTrajectory(trajectory) : null\n }\n\n async list(filter: FeedbackTrajectoryFilter = {}): Promise<FeedbackTrajectory[]> {\n return [...this.trajectories.values()]\n .filter((trajectory) => matchesFilter(trajectory, filter))\n .map(cloneTrajectory)\n }\n\n async appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory> {\n const trajectory = this.trajectories.get(id)\n if (!trajectory)\n throw new Error(`FeedbackTrajectoryStore.appendAttempt: unknown trajectory \"${id}\"`)\n const next = cloneTrajectory({\n ...trajectory,\n attempts: [...trajectory.attempts, attempt],\n updatedAt: attempt.createdAt,\n })\n this.trajectories.set(id, next)\n return cloneTrajectory(next)\n }\n\n async appendLabel(\n id: string,\n label: FeedbackLabel,\n attemptId?: string,\n ): Promise<FeedbackTrajectory> {\n const trajectory = this.trajectories.get(id)\n if (!trajectory)\n throw new Error(`FeedbackTrajectoryStore.appendLabel: unknown trajectory \"${id}\"`)\n const attempts = attemptId\n ? trajectory.attempts.map((attempt) =>\n attempt.id === attemptId\n ? { ...attempt, feedback: [...(attempt.feedback ?? []), label] }\n : attempt,\n )\n : trajectory.attempts\n const next = cloneTrajectory({\n ...trajectory,\n attempts,\n labels: attemptId ? trajectory.labels : [...trajectory.labels, label],\n updatedAt: label.createdAt,\n })\n this.trajectories.set(id, next)\n return cloneTrajectory(next)\n }\n}\n\nexport class FileSystemFeedbackTrajectoryStore implements FeedbackTrajectoryStore {\n private readonly dir: string\n private readonly memory = new InMemoryFeedbackTrajectoryStore()\n private loaded = false\n\n constructor(options: { dir: string }) {\n this.dir = options.dir\n }\n\n async save(trajectory: FeedbackTrajectory): Promise<void> {\n await this.load()\n await this.memory.save(trajectory)\n await this.append({ op: 'save', trajectory })\n }\n\n async get(id: string): Promise<FeedbackTrajectory | null> {\n await this.load()\n return this.memory.get(id)\n }\n\n async list(filter: FeedbackTrajectoryFilter = {}): Promise<FeedbackTrajectory[]> {\n await this.load()\n return this.memory.list(filter)\n }\n\n async appendAttempt(id: string, attempt: FeedbackAttempt): Promise<FeedbackTrajectory> {\n await this.load()\n const next = await this.memory.appendAttempt(id, attempt)\n await this.append({ op: 'appendAttempt', id, attempt })\n return next\n }\n\n async appendLabel(\n id: string,\n label: FeedbackLabel,\n attemptId?: string,\n ): Promise<FeedbackTrajectory> {\n await this.load()\n const next = await this.memory.appendLabel(id, label, attemptId)\n await this.append({ op: 'appendLabel', id, label, attemptId })\n return next\n }\n\n private async append(record: unknown): Promise<void> {\n const { appendFile, mkdir } = await import('node:fs/promises')\n const { join } = await import('node:path')\n await mkdir(this.dir, { recursive: true })\n await appendFile(\n join(this.dir, 'feedback-trajectories.ndjson'),\n `${JSON.stringify(record)}\\n`,\n 'utf8',\n )\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return\n const { readFile } = await import('node:fs/promises')\n const { join } = await import('node:path')\n const file = join(this.dir, 'feedback-trajectories.ndjson')\n try {\n const raw = await readFile(file, 'utf8')\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n try {\n const record = JSON.parse(line) as\n | { op: 'save'; trajectory: FeedbackTrajectory }\n | { op: 'appendAttempt'; id: string; attempt: FeedbackAttempt }\n | { op: 'appendLabel'; id: string; label: FeedbackLabel; attemptId?: string }\n if (record.op === 'save') await this.memory.save(record.trajectory)\n if (record.op === 'appendAttempt')\n await this.memory.appendAttempt(record.id, record.attempt)\n if (record.op === 'appendLabel')\n await this.memory.appendLabel(record.id, record.label, record.attemptId)\n } catch {\n /* corrupt records are skipped so one bad line does not discard the corpus */\n }\n }\n } catch {\n /* first run */\n }\n this.loaded = true\n }\n}\n\nexport function createFeedbackTrajectory(input: {\n id?: string\n projectId?: string\n scenarioId?: string\n task: FeedbackTask\n attempts?: FeedbackAttempt[]\n labels?: FeedbackLabel[]\n outcome?: FeedbackOutcome\n split?: DatasetSplit\n tags?: Record<string, string>\n createdAt?: string\n metadata?: Record<string, unknown>\n}): FeedbackTrajectory {\n const createdAt = input.createdAt ?? new Date().toISOString()\n const id =\n input.id ??\n `ft_${stableHash(`${input.projectId ?? ''}|${input.scenarioId ?? ''}|${input.task.intent}|${createdAt}`).toString(16)}`\n return {\n id,\n projectId: input.projectId,\n scenarioId: input.scenarioId,\n task: input.task,\n attempts: input.attempts ?? [],\n labels: input.labels ?? [],\n outcome: input.outcome,\n split: input.split,\n tags: input.tags,\n createdAt,\n metadata: input.metadata,\n }\n}\n\n/** Preserve a trace-analysis run for review, whether or not review is complete. */\nexport function analystRunToFeedbackTrajectory(\n run: AnalystRunResult,\n options: AnalystFeedbackTrajectoryOptions,\n): FeedbackTrajectory {\n const archivedRun = snapshotAnalystRun(run, `analyst run \"${run.run_id}\"`)\n const runDigest = analystRunDigest(archivedRun)\n const findings = archivedRun.findings\n const findingIds = findings.map((finding) => finding.finding_id)\n assertUniqueFindingIds(findingIds)\n const analystIds = [\n ...new Set([\n ...findings.map((finding) => finding.analyst_id),\n ...archivedRun.per_analyst.map((summary) => summary.analyst_id),\n ]),\n ]\n const reviewDecisions = validateAnalystReviewDecisions({\n runId: archivedRun.run_id,\n runDigest,\n findings,\n analystIds,\n decisions: options.reviewDecisions ?? [],\n })\n const reviewRequests =\n options.reviewRequests === undefined\n ? undefined\n : validateAnalystReviewRequests(archivedRun, options.reviewRequests)\n const createdAt = options.createdAt ?? archivedRun.started_at\n const knownCostUsd = archivedRun.total_cost_usd\n const capturedCost =\n archivedRun.total_cost_provenance?.kind === 'uncaptured'\n ? undefined\n : archivedRun.total_cost_usd\n return createFeedbackTrajectory({\n id: options.id,\n projectId: options.projectId,\n scenarioId: options.scenarioId,\n task: options.task,\n attempts: [\n {\n id: `analysis:${archivedRun.run_id}`,\n stepIndex: 0,\n artifactType: 'research',\n artifact: {\n type: 'analyst-run',\n analystRunId: archivedRun.run_id,\n runDigest,\n correlationId: archivedRun.correlation_id,\n analystIds,\n findings,\n ...('execution_plan' in archivedRun ? { executionPlan: archivedRun.execution_plan } : {}),\n ...('completion' in archivedRun ? { completion: archivedRun.completion } : {}),\n },\n createdAt,\n metadata: {\n perAnalyst: archivedRun.per_analyst,\n trace: options.trace,\n reviewRequests,\n },\n },\n ],\n labels: [...(options.labels ?? [])],\n outcome: options.outcome\n ? {\n ...options.outcome,\n costUsd: options.outcome.costUsd ?? capturedCost,\n }\n : capturedCost === undefined\n ? undefined\n : { costUsd: capturedCost, observedAt: archivedRun.ended_at },\n split: options.split,\n tags: options.tags,\n createdAt,\n metadata: {\n ...options.metadata,\n analysis: {\n kind: 'analyst-run',\n runId: archivedRun.run_id,\n runDigest,\n startedAt: archivedRun.started_at,\n endedAt: archivedRun.ended_at,\n reviewDecisions,\n costProvenance: archivedRun.total_cost_provenance,\n knownCostUsd,\n },\n },\n })\n}\n\n/** Convert one immutable analyst run into revision requests for an independent reviewer. */\nexport function analystRunToReviewRequests(\n run: AnalystRunResult,\n options: { createdAt?: string } = {},\n): AnalystReviewRequest[] {\n const archivedRun = snapshotAnalystRun(run, `analyst run \"${run.run_id}\"`)\n const runDigest = analystRunDigest(archivedRun)\n const createdAt = options.createdAt ?? new Date().toISOString()\n return archivedRun.findings.map((finding) => ({\n id: analystReviewRequestId(runDigest, finding.finding_id),\n runId: archivedRun.run_id,\n runDigest,\n findingId: finding.finding_id,\n findingDigest: analystFindingDigest(finding),\n analystId: finding.analyst_id,\n area: finding.area,\n claim: finding.claim,\n evidence: finding.evidence_refs,\n recommendedAction: finding.recommended_action,\n validationPlan: finding.validation_plan,\n severity: feedbackSeverityFromFinding(finding),\n confidence: finding.confidence,\n createdAt,\n }))\n}\n\nfunction validateAnalystReviewRequests(\n run: AnalystRunResult,\n requests: readonly AnalystReviewRequest[],\n): AnalystReviewRequest[] {\n const runDigest = analystRunDigest(run)\n const findingsById = new Map(run.findings.map((finding) => [finding.finding_id, finding]))\n const seenFindingIds = new Set<string>()\n return requests.map((request, index) => {\n if (request.runId !== run.run_id) {\n throw new TypeError(`analyst review request ${index} run id mismatch`)\n }\n if (request.runDigest !== runDigest) {\n throw new TypeError(`analyst review request ${index} run digest mismatch`)\n }\n const finding = findingsById.get(request.findingId)\n if (!finding) {\n throw new TypeError(\n `analyst review request ${index} references unknown finding id \"${request.findingId}\"`,\n )\n }\n if (seenFindingIds.has(request.findingId)) {\n throw new TypeError(`duplicate analyst review request for finding id \"${request.findingId}\"`)\n }\n seenFindingIds.add(request.findingId)\n if (request.findingDigest !== analystFindingDigest(finding)) {\n throw new TypeError(`analyst review request ${index} finding digest mismatch`)\n }\n if (request.id !== analystReviewRequestId(runDigest, request.findingId)) {\n throw new TypeError(`analyst review request ${index} id mismatch`)\n }\n return request\n })\n}\n\nfunction analystReviewRequestId(runDigest: `sha256:${string}`, findingId: string): string {\n return `analyst:${runDigest}:${findingId}`\n}\n\nexport function assignFeedbackSplit(\n trajectory: Pick<FeedbackTrajectory, 'id' | 'projectId' | 'scenarioId' | 'task'>,\n policy: FeedbackSplitPolicy = {},\n): DatasetSplit {\n const split = { ...DEFAULT_SPLIT_POLICY, ...policy }\n const total = split.trainPct + split.devPct + split.testPct + split.holdoutPct\n if (total <= 0) throw new Error('assignFeedbackSplit: split percentages must sum above zero')\n const bucket =\n stableHash(\n `${trajectory.projectId ?? ''}|${trajectory.scenarioId ?? ''}|${trajectory.id}|${trajectory.task.intent}`,\n ) % total\n if (bucket < split.trainPct) return 'train'\n if (bucket < split.trainPct + split.devPct) return 'dev'\n if (bucket < split.trainPct + split.devPct + split.testPct) return 'test'\n return 'holdout'\n}\n\nexport function withAssignedFeedbackSplit(\n trajectory: FeedbackTrajectory,\n policy?: FeedbackSplitPolicy,\n): FeedbackTrajectory {\n return {\n ...trajectory,\n split: trajectory.split ?? assignFeedbackSplit(trajectory, policy),\n }\n}\n\nexport function feedbackTrajectoryToDatasetScenario(\n trajectory: FeedbackTrajectory,\n): DatasetScenario {\n const withSplit = withAssignedFeedbackSplit(trajectory)\n return {\n id: withSplit.scenarioId ?? withSplit.id,\n split: withSplit.split,\n payload: withSplit,\n tags: {\n ...(withSplit.projectId ? { projectId: withSplit.projectId } : {}),\n ...(withSplit.tags ?? {}),\n source: 'feedback-trajectory',\n },\n }\n}\n\nexport function feedbackTrajectoriesToDatasetScenarios(\n trajectories: FeedbackTrajectory[],\n): DatasetScenario[] {\n return trajectories.map(feedbackTrajectoryToDatasetScenario)\n}\n\nexport function feedbackTrajectoryToOptimizerRow(\n trajectory: FeedbackTrajectory,\n): FeedbackOptimizerRow {\n const labels = allLabels(trajectory)\n const analystReview = readAnalystReview(trajectory)\n const analystQuality = analystReview ? completedAnalystReviewQuality(analystReview) : undefined\n const reviewLabelKinds = analystReview\n ? analystReview.reviewDecisions.map((decision): FeedbackLabelKind => {\n if (decision.verdict === 'rejected') return 'reject'\n if (decision.verdict === 'completeness_assessed' && decision.missedIssues.length > 0) {\n return 'revision_request'\n }\n return 'approve'\n })\n : []\n return {\n scenarioId: trajectory.scenarioId ?? trajectory.id,\n trajectoryId: trajectory.id,\n labelKinds: [...new Set([...labels.map((label) => label.kind), ...reviewLabelKinds])],\n score: analystQuality?.f1 ?? trajectory.outcome?.score ?? scoreFromLabels(labels),\n metadata: {\n projectId: trajectory.projectId,\n split: trajectory.split,\n intent: trajectory.task.intent,\n attempts: trajectory.attempts.length,\n outcome: trajectory.outcome,\n labels,\n ...(analystReview\n ? {\n analystReview: {\n findingIds: analystReview.findingIds,\n findingDigests: analystReview.findings.map((finding) => ({\n findingId: finding.finding_id,\n findingDigest: analystFindingDigest(finding),\n })),\n decisions: analystReview.reviewDecisions,\n precision: analystQuality?.precision,\n recall: analystQuality?.recall,\n f1: analystQuality?.f1,\n counts: analystQuality?.counts,\n },\n }\n : {}),\n },\n }\n}\n\nexport function feedbackTrajectoriesToOptimizerRows(\n trajectories: FeedbackTrajectory[],\n): FeedbackOptimizerRow[] {\n return trajectories.map(feedbackTrajectoryToOptimizerRow)\n}\n\nexport async function replayFeedbackTrajectory(\n trajectory: FeedbackTrajectory,\n adapter: FeedbackReplayAdapter,\n): Promise<FeedbackReplayResult> {\n try {\n const result = await adapter.replay(trajectory)\n return {\n trajectoryId: trajectory.id,\n ...result,\n }\n } catch (err) {\n const createdAt = new Date().toISOString()\n const message = err instanceof Error ? err.message : String(err)\n return {\n trajectoryId: trajectory.id,\n pass: false,\n labels: [\n {\n source: 'system',\n kind: 'reject',\n value: false,\n reason: message,\n severity: 'error',\n createdAt,\n },\n ],\n outcome: {\n success: false,\n score: 0,\n detail: message,\n observedAt: createdAt,\n },\n metadata: { replayError: true },\n }\n }\n}\n\nexport async function replayFeedbackTrajectories(\n trajectories: FeedbackTrajectory[],\n adapter: FeedbackReplayAdapter,\n): Promise<FeedbackReplayResult[]> {\n const results: FeedbackReplayResult[] = []\n for (const trajectory of trajectories) {\n results.push(await replayFeedbackTrajectory(trajectory, adapter))\n }\n return results\n}\n\nexport function summarizePreferenceMemory(\n trajectories: FeedbackTrajectory[],\n options: { maxEntries?: number } = {},\n): PreferenceMemoryEntry[] {\n const maxEntries = options.maxEntries ?? 20\n const entries: PreferenceMemoryEntry[] = []\n for (const trajectory of trajectories) {\n for (const label of allLabels(trajectory)) {\n const instruction = instructionFromLabel(trajectory, label)\n if (!instruction) continue\n entries.push({\n instruction,\n rationale: label.reason ?? `${label.kind} label from ${label.source}`,\n weight: weightForLabel(label),\n sourceTrajectoryId: trajectory.id,\n sourceLabelId: label.id,\n category: label.kind,\n })\n }\n }\n\n const byInstruction = new Map<string, PreferenceMemoryEntry>()\n for (const entry of entries) {\n const key = entry.instruction.toLowerCase().replace(/\\s+/g, ' ').trim()\n const existing = byInstruction.get(key)\n if (!existing || entry.weight > existing.weight) byInstruction.set(key, entry)\n }\n return [...byInstruction.values()].sort((a, b) => b.weight - a.weight).slice(0, maxEntries)\n}\n\nexport function renderPreferenceMemoryMarkdown(entries: PreferenceMemoryEntry[]): string {\n const lines = ['# Preference Memory', '']\n for (const entry of entries) {\n lines.push(`- ${entry.instruction}`)\n lines.push(` Rationale: ${entry.rationale}`)\n lines.push(` Source: ${entry.sourceTrajectoryId}`)\n lines.push('')\n }\n return `${lines.join('\\n').trim()}\\n`\n}\n\n/** One RFC 8785 canonical JSON row per trajectory, sorted by id, so two exports\n * of equal stores are byte-equal. Each row is the trajectory's JSON document\n * form — the same form every store persists. */\nexport function serializeFeedbackTrajectoriesJsonl(trajectories: FeedbackTrajectory[]): string {\n return `${trajectories\n .slice()\n .sort((a, b) => compareCodeUnits(a.id, b.id))\n .map((trajectory) => canonicalString(cloneTrajectory(trajectory)))\n .join('\\n')}\\n`\n}\n\nexport function parseFeedbackTrajectoriesJsonl(jsonl: string): FeedbackTrajectory[] {\n const trajectories: FeedbackTrajectory[] = []\n for (const line of jsonl.split('\\n')) {\n if (!line.trim()) continue\n trajectories.push(JSON.parse(line) as FeedbackTrajectory)\n }\n return trajectories\n}\n\nexport function controlRunToFeedbackTrajectory<TState, TAction, TActionResult>(\n run: ControlRunResult<TState, TAction, TActionResult>,\n options: {\n projectId?: string\n scenarioId?: string\n artifactType?: FeedbackArtifactType\n artifactFromStep?: (step: ControlStep<TState, TAction, TActionResult>) => unknown\n proposedActionFromStep?: (\n step: ControlStep<TState, TAction, TActionResult>,\n ) => ProposedSideEffect | undefined\n createdAt?: string\n } = {},\n): FeedbackTrajectory {\n const createdAt = options.createdAt ?? new Date().toISOString()\n const trajectoryId =\n run.runId ?? `ft_control_${stableHash(`${run.intent}|${createdAt}`).toString(16)}`\n return createFeedbackTrajectory({\n id: trajectoryId,\n projectId: options.projectId,\n scenarioId: options.scenarioId,\n task: { intent: run.intent },\n createdAt,\n attempts: run.steps.map((step) => ({\n id: `${trajectoryId}_step_${step.index}`,\n stepIndex: step.index,\n artifactType: options.artifactType ?? 'action',\n artifact: options.artifactFromStep?.(step) ?? step.actionOutcome?.result ?? step.decision,\n proposedAction: options.proposedActionFromStep?.(step),\n evals: step.evalsAfter,\n createdAt: step.startedAt,\n metadata: {\n decision: step.decision,\n actionOutcome: step.actionOutcome,\n },\n })),\n labels: [\n {\n source: 'system',\n kind: run.pass ? 'approve' : 'reject',\n value: run.pass,\n reason: run.reason,\n severity: run.pass ? 'info' : 'error',\n createdAt,\n },\n ],\n outcome: {\n success: run.pass,\n score: run.score,\n costUsd: run.spentCostUsd,\n detail: run.reason,\n observedAt: createdAt,\n metadata: {\n stoppedBy: run.stoppedBy,\n failureClass: run.failureClass,\n },\n },\n })\n}\n\nfunction allLabels(trajectory: FeedbackTrajectory): FeedbackLabel[] {\n const labels = [\n ...trajectory.labels,\n ...trajectory.attempts.flatMap((attempt) => attempt.feedback ?? []),\n ]\n const seen = new Set<string>()\n return labels.filter((label) => {\n const key =\n label.id ?? `${label.source}|${label.kind}|${label.createdAt}|${JSON.stringify(label.value)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\nfunction feedbackSeverityFromFinding(finding: AnalystFinding): FeedbackSeverity {\n switch (finding.severity) {\n case 'critical':\n return 'critical'\n case 'high':\n return 'error'\n case 'medium':\n return 'warning'\n default:\n return 'info'\n }\n}\n\nfunction scoreFromLabels(labels: FeedbackLabel[]): number | undefined {\n if (!labels.length) return undefined\n const scored = labels\n .map((label) => {\n if (label.kind === 'approve' || label.kind === 'select') return 1\n if (label.kind === 'reject' || label.kind === 'policy_block') return 0\n if (label.kind === 'rate' && typeof label.value === 'number')\n return Math.max(0, Math.min(1, label.value))\n return undefined\n })\n .filter((value): value is number => typeof value === 'number')\n if (!scored.length) return undefined\n return Math.round((scored.reduce((sum, value) => sum + value, 0) / scored.length) * 1000) / 1000\n}\n\nfunction instructionFromLabel(\n trajectory: FeedbackTrajectory,\n label: FeedbackLabel,\n): string | undefined {\n if (label.kind === 'reject' && label.reason)\n return `Avoid outputs like \"${compact(trajectory.task.intent, 80)}\" when: ${label.reason}`\n if (label.kind === 'revision_request' && label.reason)\n return `Revise similar work by applying: ${label.reason}`\n if (label.kind === 'select' && label.reason)\n return `Prefer selected options for \"${compact(trajectory.task.intent, 80)}\" because: ${label.reason}`\n if (label.kind === 'approve' && label.reason)\n return `Repeat the pattern approved for \"${compact(trajectory.task.intent, 80)}\": ${label.reason}`\n if (label.kind === 'comment' && label.reason) return label.reason\n return undefined\n}\n\nfunction weightForLabel(label: FeedbackLabel): number {\n const severity =\n label.severity === 'critical'\n ? 4\n : label.severity === 'error'\n ? 3\n : label.severity === 'warning'\n ? 2\n : 1\n const source =\n label.source === 'user'\n ? 3\n : label.source === 'metric' || label.source === 'environment'\n ? 2\n : 1\n return severity * source\n}\n\nfunction matchesFilter(trajectory: FeedbackTrajectory, filter: FeedbackTrajectoryFilter): boolean {\n if (filter.projectId && trajectory.projectId !== filter.projectId) return false\n if (filter.scenarioId && trajectory.scenarioId !== filter.scenarioId) return false\n if (filter.split && trajectory.split !== filter.split) return false\n if (filter.tag) {\n const [key, value] = filter.tag\n if (trajectory.tags?.[key] !== value) return false\n }\n return true\n}\n\nfunction cloneTrajectory(trajectory: FeedbackTrajectory): FeedbackTrajectory {\n return JSON.parse(JSON.stringify(trajectory)) as FeedbackTrajectory\n}\n\nfunction compact(value: string, max: number): string {\n const normalized = value.replace(/\\s+/g, ' ').trim()\n return normalized.length > max ? `${normalized.slice(0, max).trim()}...` : normalized\n}\n\nfunction stableHash(input: string): number {\n let hash = 2166136261\n for (let i = 0; i < input.length; i += 1) {\n hash ^= input.charCodeAt(i)\n hash = Math.imul(hash, 16777619)\n }\n return hash >>> 0\n}\n","/**\n * @stable\n *\n * Eval scorecard — the persistent (persona × profile) score timeline.\n *\n * Every benchmark run folds into per-cell entries; a cell is\n * `(scenarioId, profileHash)` and its timeline carries one entry per commit.\n * The scorecard answers the question a single run cannot: did THIS change\n * regress persona P on profile F, even while the aggregate improved?\n *\n * Storage is an append-only JSONL log — one line per (cell, commit). Appends\n * never read-modify-write, so concurrent campaign runs cannot clobber each\n * other; `loadScorecard` folds the log into the queryable `Scorecard`, and a\n * malformed line never breaks the read. `diffScorecard` compares the latest\n * entry of each cell against its predecessor with Cohen's d + Welch's t-test.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport type { AgentProfile } from './agent-profile'\nimport { agentProfileHash, agentProfileModelId } from './agent-profile'\nimport { welchsTTest } from './baseline'\nimport { type RunRecord, runTaskScore } from './run-record'\nimport { cohensD } from './statistics'\n\n// ── Types ────────────────────────────────────────────────────────────\n\n/** One commit's measurement of one (scenario, profile) cell. */\nexport interface ScorecardEntry {\n commitSha: string\n /** ISO timestamp the entry was recorded. */\n timestamp: string\n /** Per-seed (or per-rep) scores for this cell at this commit. */\n scores: number[]\n /** Median of `scores` — the cell's headline score for the commit. */\n composite: number\n /** Per-dimension means, when the runs carried a judge breakdown. */\n perDimension?: Record<string, number>\n /** RunRecord ids folded into this entry — provenance. */\n runIds: string[]\n}\n\n/** A (scenario, profile) cell and its commit-ordered score timeline. */\nexport interface ScorecardCell {\n scenarioId: string\n profileHash: string\n /** Model id — denormalised from the profile for readable filtering. */\n model: string\n timeline: ScorecardEntry[]\n}\n\n/** The folded scorecard: every cell, plus the profile definitions by hash. */\nexport interface Scorecard {\n cells: ScorecardCell[]\n /** Profile definitions seen — keeps the scorecard self-describing. */\n profiles: Record<string, AgentProfile>\n}\n\n/** One append-only log line — a single cell's entry for a single commit. */\nexport interface ScorecardLogLine {\n scenarioId: string\n profileHash: string\n model: string\n profile: AgentProfile\n entry: ScorecardEntry\n}\n\n// ── Recording ────────────────────────────────────────────────────────\n\nexport interface RecordRunsOptions {\n /** The profile that produced these runs — keys the cell. */\n profile: AgentProfile\n commitSha: string\n /** Defaults to `new Date().toISOString()`. */\n timestamp?: string\n}\n\nfunction median(xs: number[]): number {\n if (xs.length === 0) return 0\n const sorted = [...xs].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!\n}\n\n// Cells rank on `runTaskScore` — RAW on purpose: a scorecard reports the\n// measurement, and hiding a gamed run's score behind a 0 would make the gaming\n// invisible in the report.\n\n/** Mean of each judge dimension across the runs that reported one. */\nfunction aggregatePerDimension(runs: RunRecord[]): Record<string, number> | undefined {\n const sums = new Map<string, { total: number; count: number }>()\n for (const run of runs) {\n const dims = run.outcome.judgeScores?.perDimMean\n if (!dims) continue\n for (const [dim, value] of Object.entries(dims)) {\n if (!Number.isFinite(value)) continue\n const acc = sums.get(dim) ?? { total: 0, count: 0 }\n acc.total += value\n acc.count += 1\n sums.set(dim, acc)\n }\n }\n if (sums.size === 0) return undefined\n const out: Record<string, number> = {}\n for (const [dim, acc] of sums) out[dim] = acc.total / acc.count\n return out\n}\n\n/**\n * Fold a benchmark's `RunRecord[]` into per-cell scorecard log lines — one\n * line per scenario the runs cover. All runs are attributed to the single\n * `profile` in `opts` (the harness ran them under it); the cell key is\n * `(scenarioId, agentProfileHash(profile))`.\n */\nexport function recordRuns(runs: RunRecord[], opts: RecordRunsOptions): ScorecardLogLine[] {\n const profileHash = agentProfileHash(opts.profile)\n const model = agentProfileModelId(opts.profile)\n const timestamp = opts.timestamp ?? new Date().toISOString()\n\n const byScenario = new Map<string, RunRecord[]>()\n for (const run of runs) {\n const scenarioId = run.scenarioId\n if (!scenarioId) continue // un-keyed run — cannot place it in a cell\n const bucket = byScenario.get(scenarioId)\n if (bucket) bucket.push(run)\n else byScenario.set(scenarioId, [run])\n }\n\n const lines: ScorecardLogLine[] = []\n for (const [scenarioId, scenarioRuns] of byScenario) {\n const scored = scenarioRuns\n .map((run) => ({ run, score: runTaskScore(run) }))\n .filter((s): s is { run: RunRecord; score: number } => s.score !== undefined)\n if (scored.length === 0) continue\n const scores = scored.map((s) => s.score)\n const entry: ScorecardEntry = {\n commitSha: opts.commitSha,\n timestamp,\n scores,\n composite: median(scores),\n runIds: scored.map((s) => s.run.runId),\n }\n const perDimension = aggregatePerDimension(scenarioRuns)\n if (perDimension) entry.perDimension = perDimension\n lines.push({\n scenarioId,\n profileHash,\n model,\n profile: opts.profile,\n entry,\n })\n }\n return lines\n}\n\n// ── Storage ──────────────────────────────────────────────────────────\n\n/** Append cell entries to the JSONL scorecard log. Creates the file/dir. */\nexport function appendScorecard(logPath: string, lines: ScorecardLogLine[]): void {\n if (lines.length === 0) return\n mkdirSync(dirname(logPath), { recursive: true })\n appendFileSync(logPath, `${lines.map((line) => JSON.stringify(line)).join('\\n')}\\n`)\n}\n\n/** Record runs and append them to the log in one call. Returns the lines. */\nexport function recordRunsToScorecard(\n logPath: string,\n runs: RunRecord[],\n opts: RecordRunsOptions,\n): ScorecardLogLine[] {\n const lines = recordRuns(runs, opts)\n appendScorecard(logPath, lines)\n return lines\n}\n\n/**\n * Fold the JSONL log into a queryable `Scorecard`. A missing file yields an\n * empty scorecard; a malformed line is skipped — a corrupt append never\n * breaks the read. Each cell's timeline is sorted chronologically.\n */\nexport function loadScorecard(logPath: string): Scorecard {\n if (!existsSync(logPath)) return { cells: [], profiles: {} }\n const cells = new Map<string, ScorecardCell>()\n const profiles: Record<string, AgentProfile> = {}\n\n for (const raw of readFileSync(logPath, 'utf8').split('\\n')) {\n const line = raw.trim()\n if (!line) continue\n let parsed: ScorecardLogLine\n try {\n parsed = JSON.parse(line) as ScorecardLogLine\n } catch {\n continue // skip a malformed line rather than failing the whole read\n }\n if (!parsed?.scenarioId || !parsed.profileHash || !parsed.entry) continue\n const key = `${parsed.scenarioId}::${parsed.profileHash}`\n let cell = cells.get(key)\n if (!cell) {\n cell = {\n scenarioId: parsed.scenarioId,\n profileHash: parsed.profileHash,\n model: parsed.model,\n timeline: [],\n }\n cells.set(key, cell)\n }\n cell.timeline.push(parsed.entry)\n if (parsed.profile) profiles[parsed.profileHash] = parsed.profile\n }\n\n for (const cell of cells.values()) {\n cell.timeline.sort((a, b) => a.timestamp.localeCompare(b.timestamp))\n }\n return { cells: [...cells.values()], profiles }\n}\n\n// ── Diff ─────────────────────────────────────────────────────────────\n\nexport type CellVerdict = 'improved' | 'regressed' | 'flat' | 'new'\n\nexport interface ScorecardCellDiff {\n scenarioId: string\n profileHash: string\n model: string\n verdict: CellVerdict\n /** Composite of the latest entry. */\n current: number\n /** Composite of the comparison entry — `null` when `verdict === 'new'`. */\n baseline: number | null\n /** `current − baseline` — `null` when new. */\n delta: number | null\n /** Cohen's d of current vs baseline samples — `null` when new or n < 2. */\n cohensD: number | null\n /** Welch's t-test p-value — `null` when new or n < 2. */\n pValue: number | null\n currentCommit: string\n baselineCommit: string | null\n}\n\nexport interface ScorecardDiff {\n cells: ScorecardCellDiff[]\n summary: { improved: number; regressed: number; flat: number; new: number }\n}\n\nexport interface DiffScorecardOptions {\n /** Compare each cell against this commit instead of its immediate predecessor. */\n baselineCommit?: string\n /** |Cohen's d| at/above which a move counts as real. Default 0.5. */\n minEffect?: number\n /** p-value at/below which a move is significant. Default 0.05. */\n maxP?: number\n /**\n * |delta| at/above which a move counts when statistics are unavailable\n * (a cell with fewer than 2 samples on either side). Default 0.05.\n */\n minDelta?: number\n}\n\n/**\n * Compare the latest entry of every cell against its predecessor (or against\n * `baselineCommit`) and classify the move. A move is `improved`/`regressed`\n * only when it clears both the effect-size and significance gates; otherwise\n * `flat`. Cells with no prior entry are `new`.\n */\nexport function diffScorecard(\n scorecard: Scorecard,\n opts: DiffScorecardOptions = {},\n): ScorecardDiff {\n const minEffect = opts.minEffect ?? 0.5\n const maxP = opts.maxP ?? 0.05\n const minDelta = opts.minDelta ?? 0.05\n\n const cells: ScorecardCellDiff[] = []\n for (const cell of scorecard.cells) {\n const timeline = cell.timeline\n if (timeline.length === 0) continue\n const current = timeline[timeline.length - 1]!\n\n const baseline = opts.baselineCommit\n ? [...timeline].reverse().find((e) => e.commitSha === opts.baselineCommit && e !== current)\n : timeline[timeline.length - 2]\n\n const base: Omit<\n ScorecardCellDiff,\n 'verdict' | 'baseline' | 'delta' | 'cohensD' | 'pValue' | 'baselineCommit'\n > = {\n scenarioId: cell.scenarioId,\n profileHash: cell.profileHash,\n model: cell.model,\n current: current.composite,\n currentCommit: current.commitSha,\n }\n\n if (!baseline) {\n cells.push({\n ...base,\n verdict: 'new',\n baseline: null,\n delta: null,\n cohensD: null,\n pValue: null,\n baselineCommit: null,\n })\n continue\n }\n\n const delta = current.composite - baseline.composite\n const canStat = baseline.scores.length >= 2 && current.scores.length >= 2\n let d: number | null = null\n let p: number | null = null\n let verdict: CellVerdict\n\n if (canStat) {\n d = cohensD(baseline.scores, current.scores)\n const t = welchsTTest(baseline.scores, current.scores)\n p = Number.isFinite(t.p) ? t.p : null\n // `canStat` guarantees ≥ 2 samples per side, so a null d means zero\n // pooled spread across a real mean gap — an unbounded standardized\n // effect, which clears any finite threshold.\n const effectClears = d === null || Math.abs(d) >= minEffect\n const significant = effectClears && p !== null && p <= maxP\n verdict = significant ? (delta > 0 ? 'improved' : 'regressed') : 'flat'\n } else {\n // Too few samples for a real test — fall back to a raw-delta threshold.\n verdict = Math.abs(delta) >= minDelta ? (delta > 0 ? 'improved' : 'regressed') : 'flat'\n }\n\n cells.push({\n ...base,\n verdict,\n baseline: baseline.composite,\n delta,\n cohensD: d,\n pValue: p,\n baselineCommit: baseline.commitSha,\n })\n }\n\n const summary = { improved: 0, regressed: 0, flat: 0, new: 0 }\n for (const cell of cells) summary[cell.verdict] += 1\n return { cells, summary }\n}\n\n/**\n * Render a scorecard diff as a human-readable report — the block a feature\n * PR prints. Regressions are listed first; flat cells are summarised, not\n * enumerated.\n */\nexport function formatScorecardDiff(diff: ScorecardDiff): string {\n const lines: string[] = []\n const { summary } = diff\n lines.push(\n `Scorecard: ${summary.regressed} regressed · ${summary.improved} improved · ` +\n `${summary.flat} flat · ${summary.new} new`,\n )\n\n const fmt = (n: number) => n.toFixed(3)\n const noteworthy = diff.cells\n .filter((c) => c.verdict === 'regressed' || c.verdict === 'improved')\n .sort((a, b) => {\n // Regressions first, then by magnitude of delta.\n if (a.verdict !== b.verdict) return a.verdict === 'regressed' ? -1 : 1\n return Math.abs(b.delta ?? 0) - Math.abs(a.delta ?? 0)\n })\n\n for (const cell of noteworthy) {\n const mark = cell.verdict === 'regressed' ? 'REGRESSED' : 'improved'\n const deltaStr =\n cell.delta !== null ? (cell.delta >= 0 ? `+${fmt(cell.delta)}` : fmt(cell.delta)) : '—'\n const stat =\n cell.cohensD !== null\n ? ` (d=${cell.cohensD.toFixed(2)}${cell.pValue !== null ? `, p=${cell.pValue.toFixed(3)}` : ''})`\n : ''\n lines.push(\n ` ${mark} ${cell.scenarioId} · ${cell.model} · ${cell.profileHash.slice(0, 8)} ` +\n `${fmt(cell.baseline ?? 0)} → ${fmt(cell.current)} ${deltaStr}${stat}`,\n )\n }\n\n return lines.join('\\n')\n}\n","/**\n * Trace contracts — finite-trace temporal assertions over span sequences.\n *\n * Five LTLf operators over one ordered span sequence — `always(p)`,\n * `never(p)`, `eventually(p)`, `precedes(a, b)`, `neverUnless(p, prior)` —\n * deterministic and judge-free. No nesting: each rule is one operator over\n * flat `SpanPredicate`s; compose richer checks with multiple rules.\n *\n * A built `TraceContract` is a serializable plain object (RegExp matchers\n * are normalized to `SerializedRegex`), so ONE contract definition is\n * dual-use:\n *\n * - recorded eval traces — `evaluateTraceContract(contract, await\n * store.spans({ runId }))`.\n * - the production OTLP stream — `ExportableSpan`s flattened by\n * `trace/otel-bridge` satisfy `ContractSpan` structurally. A production\n * monitor implements `OtelExporter`, buffers `exportSpan` payloads per\n * trace, and runs `checkTraceContracts(buffer, contracts)` on flush:\n *\n * const buffer: ContractSpan[] = []\n * const monitor: OtelExporter = {\n * exportSpan: (s) => { buffer.push(s) },\n * flush: async () => {\n * const { allValid, verdicts } = checkTraceContracts(buffer, contracts)\n * if (!allValid) alert(verdicts)\n * },\n * shutdown: async () => {},\n * }\n * const store = createOtelTracingStore(inner, monitor, runId)\n *\n * `custom` predicate functions are the one non-serializable escape hatch:\n * the builder stamps `requiresCustom: true` (which DOES survive JSON) so a\n * deserialized contract that lost its function fails loud at evaluation\n * instead of silently weakening.\n *\n * Naming: the root barrel exports ci-gate's threshold-contract\n * `evaluateContract`, so the evaluators here are `evaluateTraceContract` /\n * `checkTraceContracts`.\n */\n\nimport type { JudgeConfig, JudgeDimension, Scenario } from './campaign/types'\nimport { ValidationError } from './errors'\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\n// ── Span surface ──────────────────────────────────────────────────────\n\n/**\n * Minimal structural span the checker reads. Both the eval-side `Span`\n * (trace/schema) and the OTLP-flattened `ExportableSpan` (trace/otel-export)\n * satisfy it; any other producer only needs these fields.\n */\nexport interface ContractSpan {\n spanId?: string\n name?: string\n kind?: string\n startedAt?: number\n status?: string\n error?: string\n /** Typed field on eval-side ToolSpans; OTLP flattenings drop it (see\n * `tool` matching order in {@link matchSpan}). */\n toolName?: string\n attributes?: Record<string, unknown>\n}\n\n/** JSON-safe RegExp form — what the builder normalizes RegExp matchers to. */\nexport interface SerializedRegex {\n $regex: string\n flags: string\n}\n\nexport type TextMatcher = string | RegExp | SerializedRegex\n\n/**\n * Proposition over one span. All specified fields must match (AND).\n * At least one field is required — an empty predicate would match every\n * span and is rejected.\n *\n * `tool` resolution order covers both span shapes: `span.toolName` (typed\n * ToolSpan) → `attributes['tool.name']` / `attributes['toolName']`\n * (OTLP-flat attribute conventions) → `span.name` when `kind === 'tool'`\n * (otel-bridge's `ExportableSpan`, which drops `toolName`).\n *\n * `attr` values match by strict equality, or regex-test when the value is a\n * RegExp/SerializedRegex and the attribute is a string. Structured attribute\n * values need `custom`.\n */\nexport interface SpanPredicate {\n name?: TextMatcher\n tool?: TextMatcher\n attr?: Record<string, unknown>\n custom?: (span: ContractSpan) => boolean\n /** Stamped by the builder when `custom` is present. Survives JSON while\n * the function does not, so evaluation of a deserialized contract throws\n * instead of silently dropping the check. */\n requiresCustom?: true\n}\n\n// ── Contract shape ────────────────────────────────────────────────────\n\nexport type ContractRuleKind = 'always' | 'never' | 'eventually' | 'precedes' | 'neverUnless'\n\nexport interface ContractRule {\n kind: ContractRuleKind\n /** Unique within the contract — keys the per-rule score. */\n label: string\n /** Subject predicate for always / never / eventually / neverUnless. */\n p?: SpanPredicate\n /** precedes: the required precondition. */\n a?: SpanPredicate\n /** precedes: the guarded match — every b-match needs an earlier a-match. */\n b?: SpanPredicate\n /** neverUnless: the authorizing earlier match. */\n prior?: SpanPredicate\n}\n\n/** Serializable plain object — `traceContract(name)....build()` output. */\nexport interface TraceContract {\n name: string\n rules: ContractRule[]\n}\n\nexport interface ContractViolation {\n rule: string\n spanId?: string\n detail: string\n}\n\nexport interface ContractVerdict extends DefaultVerdict {\n /** Contract name — keys this verdict in multi-contract reports. */\n contract: string\n valid: boolean\n /** Fraction of rules passing, in [0, 1]. */\n score: number\n /** Per-rule 0|1 keyed by rule label. */\n scores: Record<string, number>\n violations: ContractViolation[]\n}\n\nexport interface ContractCheckResult {\n verdicts: ContractVerdict[]\n allValid: boolean\n}\n\n// ── Predicate matching ────────────────────────────────────────────────\n\nfunction isSerializedRegex(v: unknown): v is SerializedRegex {\n return (\n typeof v === 'object' &&\n v !== null &&\n typeof (v as SerializedRegex).$regex === 'string' &&\n typeof (v as SerializedRegex).flags === 'string'\n )\n}\n\nfunction matchText(actual: string | undefined, matcher: TextMatcher): boolean {\n if (typeof actual !== 'string') return false\n if (typeof matcher === 'string') return actual === matcher\n if (matcher instanceof RegExp) return matcher.test(actual)\n return new RegExp(matcher.$regex, matcher.flags).test(actual)\n}\n\nfunction resolveToolName(span: ContractSpan): string | undefined {\n if (typeof span.toolName === 'string') return span.toolName\n const fromAttr = span.attributes?.['tool.name'] ?? span.attributes?.toolName\n if (typeof fromAttr === 'string') return fromAttr\n if (span.kind === 'tool' && typeof span.name === 'string') return span.name\n return undefined\n}\n\nfunction assertPredicate(value: unknown, where: string): asserts value is SpanPredicate {\n if (value === null || typeof value !== 'object') {\n throw new ValidationError(`${where}: predicate must be an object, got ${typeof value}`)\n }\n const p = value as SpanPredicate\n for (const field of ['name', 'tool'] as const) {\n const m = p[field]\n if (\n m !== undefined &&\n typeof m !== 'string' &&\n !(m instanceof RegExp) &&\n !isSerializedRegex(m)\n ) {\n throw new ValidationError(`${where}: \"${field}\" must be string | RegExp | SerializedRegex`)\n }\n }\n if (\n p.attr !== undefined &&\n (p.attr === null || typeof p.attr !== 'object' || Array.isArray(p.attr))\n ) {\n throw new ValidationError(`${where}: \"attr\" must be a plain object`)\n }\n if (p.requiresCustom && typeof p.custom !== 'function') {\n throw new ValidationError(\n `${where}: rule was built with a custom predicate function, which does not survive JSON ` +\n 'serialization — re-attach `custom` after deserializing or drop the rule',\n )\n }\n const hasAttr = p.attr !== undefined && Object.keys(p.attr).length > 0\n if (p.name === undefined && p.tool === undefined && !hasAttr && typeof p.custom !== 'function') {\n throw new ValidationError(\n `${where}: empty predicate would match every span — specify name, tool, attr, or custom`,\n )\n }\n}\n\n/** Test one span against one predicate. All specified fields must match. */\nexport function matchSpan(span: ContractSpan, predicate: SpanPredicate): boolean {\n assertPredicate(predicate, 'matchSpan')\n if (predicate.name !== undefined && !matchText(span.name, predicate.name)) return false\n if (predicate.tool !== undefined && !matchText(resolveToolName(span), predicate.tool))\n return false\n if (predicate.attr !== undefined) {\n for (const [key, expected] of Object.entries(predicate.attr)) {\n const actual = span.attributes?.[key]\n if (expected instanceof RegExp || isSerializedRegex(expected)) {\n if (!matchText(typeof actual === 'string' ? actual : undefined, expected as TextMatcher)) {\n return false\n }\n } else if (actual !== expected) {\n return false\n }\n }\n }\n if (predicate.custom !== undefined && !predicate.custom(span)) return false\n return true\n}\n\n// ── Builder ───────────────────────────────────────────────────────────\n\nfunction describeMatcher(m: TextMatcher): string {\n if (typeof m === 'string') return m\n if (m instanceof RegExp) return `/${m.source}/${m.flags}`\n return `/${m.$regex}/${m.flags}`\n}\n\nfunction describePredicate(p: SpanPredicate): string {\n const parts: string[] = []\n if (p.name !== undefined) parts.push(`name=${describeMatcher(p.name)}`)\n if (p.tool !== undefined) parts.push(`tool=${describeMatcher(p.tool)}`)\n if (p.attr !== undefined) {\n for (const [k, v] of Object.entries(p.attr)) {\n parts.push(\n `attr.${k}=${v instanceof RegExp || isSerializedRegex(v) ? describeMatcher(v as TextMatcher) : JSON.stringify(v)}`,\n )\n }\n }\n if (typeof p.custom === 'function') parts.push(`custom=${p.custom.name || 'fn'}`)\n return parts.join(',')\n}\n\nfunction normalizeMatcher(m: TextMatcher): string | SerializedRegex {\n return m instanceof RegExp ? { $regex: m.source, flags: m.flags } : m\n}\n\nfunction normalizePredicate(p: SpanPredicate, where: string): SpanPredicate {\n assertPredicate(p, where)\n const out: SpanPredicate = {}\n if (p.name !== undefined) out.name = normalizeMatcher(p.name)\n if (p.tool !== undefined) out.tool = normalizeMatcher(p.tool)\n if (p.attr !== undefined) {\n out.attr = Object.fromEntries(\n Object.entries(p.attr).map(([k, v]) => [k, v instanceof RegExp ? normalizeMatcher(v) : v]),\n )\n }\n if (typeof p.custom === 'function') {\n out.custom = p.custom\n out.requiresCustom = true\n }\n return out\n}\n\nexport class TraceContractBuilder {\n private readonly rules: ContractRule[] = []\n\n constructor(private readonly name: string) {}\n\n /** Every span in the trace must satisfy `p`. */\n always(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").always`)\n return this.add({ kind: 'always', label: label ?? `always(${describePredicate(np)})`, p: np })\n }\n\n /** No span in the trace may satisfy `p`. */\n never(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").never`)\n return this.add({ kind: 'never', label: label ?? `never(${describePredicate(np)})`, p: np })\n }\n\n /** At least one span in the trace must satisfy `p`. */\n eventually(p: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").eventually`)\n return this.add({\n kind: 'eventually',\n label: label ?? `eventually(${describePredicate(np)})`,\n p: np,\n })\n }\n\n /** Every `b`-match must have a strictly earlier `a`-match. */\n precedes(a: SpanPredicate, b: SpanPredicate, label?: string): this {\n const na = normalizePredicate(a, `traceContract(\"${this.name}\").precedes (a)`)\n const nb = normalizePredicate(b, `traceContract(\"${this.name}\").precedes (b)`)\n return this.add({\n kind: 'precedes',\n label: label ?? `precedes(${describePredicate(na)} -> ${describePredicate(nb)})`,\n a: na,\n b: nb,\n })\n }\n\n /** Every `p`-match is a violation unless a strictly earlier `prior`-match exists. */\n neverUnless(p: SpanPredicate, prior: SpanPredicate, label?: string): this {\n const np = normalizePredicate(p, `traceContract(\"${this.name}\").neverUnless (p)`)\n const nprior = normalizePredicate(prior, `traceContract(\"${this.name}\").neverUnless (prior)`)\n return this.add({\n kind: 'neverUnless',\n label: label ?? `neverUnless(${describePredicate(np)} unless ${describePredicate(nprior)})`,\n p: np,\n prior: nprior,\n })\n }\n\n build(): TraceContract {\n if (this.rules.length === 0) {\n throw new ValidationError(\n `traceContract(\"${this.name}\").build(): no rules — an empty contract would vacuously pass`,\n )\n }\n return { name: this.name, rules: [...this.rules] }\n }\n\n private add(rule: ContractRule): this {\n // Labels key per-rule scores — auto-suffix duplicates so two identical\n // operator+predicate rules never collapse into one score entry.\n let label = rule.label\n let n = 2\n while (this.rules.some((r) => r.label === label)) {\n label = `${rule.label} #${n}`\n n += 1\n }\n this.rules.push({ ...rule, label })\n return this\n }\n}\n\nexport function traceContract(name: string): TraceContractBuilder {\n if (typeof name !== 'string' || name.length === 0) {\n throw new ValidationError('traceContract: name must be a non-empty string')\n }\n return new TraceContractBuilder(name)\n}\n\n// ── Evaluation ────────────────────────────────────────────────────────\n\nfunction assertContract(contract: TraceContract): void {\n if (typeof contract?.name !== 'string' || contract.name.length === 0) {\n throw new ValidationError('evaluateTraceContract: contract.name must be a non-empty string')\n }\n if (!Array.isArray(contract.rules) || contract.rules.length === 0) {\n throw new ValidationError(\n `evaluateTraceContract: contract \"${contract.name}\" has no rules — an empty contract would vacuously pass`,\n )\n }\n const seen = new Set<string>()\n for (const rule of contract.rules) {\n const where = `contract \"${contract.name}\" rule \"${rule?.label ?? '<unlabeled>'}\"`\n if (typeof rule?.label !== 'string' || rule.label.length === 0) {\n throw new ValidationError(`${where}: label must be a non-empty string`)\n }\n if (seen.has(rule.label)) {\n throw new ValidationError(`${where}: duplicate label would collapse per-rule scores`)\n }\n seen.add(rule.label)\n switch (rule.kind) {\n case 'always':\n case 'never':\n case 'eventually':\n assertPredicate(rule.p, `${where} (p)`)\n break\n case 'precedes':\n assertPredicate(rule.a, `${where} (a)`)\n assertPredicate(rule.b, `${where} (b)`)\n break\n case 'neverUnless':\n assertPredicate(rule.p, `${where} (p)`)\n assertPredicate(rule.prior, `${where} (prior)`)\n break\n default:\n throw new ValidationError(\n `${where}: unknown rule kind \"${String((rule as ContractRule).kind)}\"`,\n )\n }\n }\n}\n\n/**\n * Order spans for temporal evaluation: by `startedAt` when EVERY span carries\n * one (stable — ties keep array order), by array order when NONE does. Mixed\n * timestamps throw: neither time order nor array order is a trustworthy total\n * order over a partially-stamped sequence, and guessing would corrupt\n * `precedes` / `neverUnless` verdicts.\n */\nfunction orderSpans(spans: readonly ContractSpan[]): ContractSpan[] {\n const timed = spans.filter(\n (s) => typeof s.startedAt === 'number' && Number.isFinite(s.startedAt),\n ).length\n if (timed === spans.length) {\n return spans\n .map((span, i) => ({ span, i }))\n .sort((x, y) => x.span.startedAt! - y.span.startedAt! || x.i - y.i)\n .map((x) => x.span)\n }\n if (timed === 0) return [...spans]\n throw new ValidationError(\n `evaluateTraceContract: ${timed}/${spans.length} spans carry a finite startedAt — ` +\n 'mixed timestamps make ordering ambiguous; stamp every span or none',\n )\n}\n\nfunction spanRef(span: ContractSpan, index: number): string {\n return span.spanId ?? `#${index}`\n}\n\n// precedes(a, b) and neverUnless(p, prior) share one semantics: every\n// guarded-match must have a STRICTLY earlier guard-match. The guard flag\n// updates after the guarded check, so a span matching both cannot witness\n// itself.\nfunction checkGuarded(args: {\n label: string\n ordered: readonly ContractSpan[]\n guard: SpanPredicate\n guarded: SpanPredicate\n detail: (ref: string) => string\n}): ContractViolation[] {\n const out: ContractViolation[] = []\n let guardSeen = false\n for (let i = 0; i < args.ordered.length; i++) {\n const span = args.ordered[i]!\n if (!guardSeen && matchSpan(span, args.guarded)) {\n out.push({ rule: args.label, spanId: span.spanId, detail: args.detail(spanRef(span, i)) })\n }\n if (matchSpan(span, args.guard)) guardSeen = true\n }\n return out\n}\n\nfunction checkRule(rule: ContractRule, ordered: readonly ContractSpan[]): ContractViolation[] {\n switch (rule.kind) {\n case 'always': {\n const out: ContractViolation[] = []\n for (let i = 0; i < ordered.length; i++) {\n const span = ordered[i]!\n if (!matchSpan(span, rule.p!)) {\n out.push({\n rule: rule.label,\n spanId: span.spanId,\n detail: `span ${spanRef(span, i)} (\"${span.name ?? ''}\") fails always(${describePredicate(rule.p!)})`,\n })\n }\n }\n return out\n }\n case 'never': {\n const out: ContractViolation[] = []\n for (let i = 0; i < ordered.length; i++) {\n const span = ordered[i]!\n if (matchSpan(span, rule.p!)) {\n out.push({\n rule: rule.label,\n spanId: span.spanId,\n detail: `span ${spanRef(span, i)} (\"${span.name ?? ''}\") matches never(${describePredicate(rule.p!)})`,\n })\n }\n }\n return out\n }\n case 'eventually': {\n const hit = ordered.some((span) => matchSpan(span, rule.p!))\n return hit\n ? []\n : [\n {\n rule: rule.label,\n detail: `no span matches eventually(${describePredicate(rule.p!)}) over ${ordered.length} span(s)`,\n },\n ]\n }\n case 'precedes':\n return checkGuarded({\n label: rule.label,\n ordered,\n guard: rule.a!,\n guarded: rule.b!,\n detail: (ref) =>\n `span ${ref} matches ${describePredicate(rule.b!)} with no earlier ${describePredicate(rule.a!)} match`,\n })\n case 'neverUnless':\n return checkGuarded({\n label: rule.label,\n ordered,\n guard: rule.prior!,\n guarded: rule.p!,\n detail: (ref) =>\n `span ${ref} matches ${describePredicate(rule.p!)} with no earlier ${describePredicate(rule.prior!)} match`,\n })\n }\n}\n\n/**\n * Evaluate one contract over a span sequence. Pure and synchronous — works\n * on `Span[]` from a TraceStore, `ExportableSpan[]` from the otel-bridge\n * flattening, or any array satisfying `ContractSpan`.\n */\nexport function evaluateTraceContract(\n contract: TraceContract,\n spans: readonly ContractSpan[],\n): ContractVerdict {\n assertContract(contract)\n const ordered = orderSpans(spans)\n const scores: Record<string, number> = {}\n const violations: ContractViolation[] = []\n for (const rule of contract.rules) {\n const ruleViolations = checkRule(rule, ordered)\n scores[rule.label] = ruleViolations.length === 0 ? 1 : 0\n violations.push(...ruleViolations)\n }\n const ruleCount = contract.rules.length\n const passCount = Object.values(scores).filter((s) => s === 1).length\n // Steps the certificate rests on unverified: array ordering when no span\n // carries a timestamp, and any rule whose truth depends on a custom\n // predicate function that is not part of the serialized contract.\n const assumptions: string[] = []\n if (spans.length > 0 && ordered.every((s) => typeof s.startedAt !== 'number')) {\n assumptions.push('spans ordered by array position — no startedAt timestamps to order by')\n }\n for (const rule of contract.rules) {\n const predicates = [rule.p, rule.a, rule.b, rule.prior]\n if (predicates.some((p) => p !== undefined && typeof p.custom === 'function')) {\n assumptions.push(`rule '${rule.label}' rests on a custom predicate function`)\n }\n }\n return {\n contract: contract.name,\n valid: passCount === ruleCount,\n score: passCount / ruleCount,\n scores,\n violations,\n notes: `${passCount}/${ruleCount} rules passed`,\n certification: {\n strategy: 'invariant',\n checker: { name: 'agent-eval:trace-contracts', version: packageVersion() },\n assumptions,\n evidenceDigest: certificationEvidenceDigest({\n contract: contract.name,\n scores,\n violations,\n }),\n },\n }\n}\n\n/**\n * Evaluate many contracts over one span sequence. Throws on an empty\n * contract list — `allValid: true` over zero contracts is a silent pass.\n */\nexport function checkTraceContracts(\n spans: readonly ContractSpan[],\n contracts: readonly TraceContract[],\n): ContractCheckResult {\n if (contracts.length === 0) {\n throw new ValidationError(\n 'checkTraceContracts: empty contract list would vacuously pass — supply at least one contract',\n )\n }\n const verdicts = contracts.map((c) => evaluateTraceContract(c, spans))\n return { verdicts, allValid: verdicts.every((v) => v.valid) }\n}\n\n// ── Campaign judge adapter ────────────────────────────────────────────\n\nexport interface ContractJudgeOptions<TArtifact, TScenario extends Scenario = Scenario> {\n /**\n * Project the span sequence out of a cell's artifact. `JudgeConfig.score`\n * receives only `{ artifact, scenario, signal }` (src/campaign/types.ts) —\n * spans are NOT reachable generically — so the consumer supplies this\n * explicit extraction (e.g. dispatch writes spans into the artifact, or\n * closes over a per-cell TraceStore read).\n */\n spans: (input: { artifact: TArtifact; scenario: TScenario }) => readonly ContractSpan[]\n /** Judge name in campaign reports. Default 'trace-contracts'. */\n name?: string\n}\n\n/**\n * Adapt trace contracts to a campaign `JudgeConfig`. One judge dimension per\n * contract (key = contract name, value = its rule-pass fraction); composite\n * is the mean across contracts. Deterministic — no LLM call.\n */\nexport function contractJudge<TArtifact, TScenario extends Scenario = Scenario>(\n contracts: readonly TraceContract[],\n opts: ContractJudgeOptions<TArtifact, TScenario>,\n): JudgeConfig<TArtifact, TScenario> {\n if (contracts.length === 0) {\n throw new ValidationError('contractJudge: at least one contract required')\n }\n for (const c of contracts) assertContract(c)\n const names = new Set<string>()\n for (const c of contracts) {\n if (names.has(c.name)) {\n throw new ValidationError(\n `contractJudge: duplicate contract name \"${c.name}\" would collapse judge dimensions`,\n )\n }\n names.add(c.name)\n }\n if (typeof opts?.spans !== 'function') {\n throw new ValidationError('contractJudge: opts.spans extraction function is required')\n }\n const dimensions: JudgeDimension[] = contracts.map((c) => ({\n key: c.name,\n description: c.rules.map((r) => r.label).join('; '),\n }))\n return {\n name: opts.name ?? 'trace-contracts',\n dimensions,\n score({ artifact, scenario }) {\n const spans = opts.spans({ artifact, scenario })\n if (!Array.isArray(spans)) {\n throw new ValidationError(\n `contractJudge: spans() must return a span array, got ${typeof spans}`,\n )\n }\n const { verdicts } = checkTraceContracts(spans, contracts)\n const dims: Record<string, number> = {}\n const violations: ContractViolation[] = []\n for (const v of verdicts) {\n dims[v.contract] = v.score\n violations.push(...v.violations)\n }\n const composite = verdicts.reduce((acc, v) => acc + v.score, 0) / verdicts.length\n return {\n dimensions: dims,\n composite,\n notes:\n violations.length === 0\n ? 'all trace contracts satisfied'\n : violations\n .slice(0, 8)\n .map((x) => `${x.rule}: ${x.detail}`)\n .join('\\n'),\n }\n },\n }\n}\n","/**\n * Active learning — agent-as-scenario-author.\n *\n * Analyzes an existing Dataset + trace corpus for coverage gaps and\n * weak spots, returns a prioritized list of *synthesis targets*:\n * (gap description, existing-neighbor examples, suggested direction).\n *\n * Does NOT call an LLM itself — the proposer agent is caller-supplied.\n * This module's job is to identify WHERE new scenarios would compound\n * the most information, not to author them.\n *\n * Gaps we detect:\n * - dimensions with high score variance (unstable, need more data)\n * - dimensions with low coverage count (undersampled)\n * - failure classes with clusters (systematic weakness)\n * - difficulty bins with no coverage\n */\n\nimport type { Dataset, DatasetScenario } from './dataset'\nimport { classifyFailure } from './failure-taxonomy'\nimport type { Run } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport type SynthesisReason =\n | 'high-variance'\n | 'undersampled'\n | 'failure-cluster'\n | 'difficulty-gap'\n\nexport interface SynthesisTarget {\n reason: SynthesisReason\n description: string\n /** Existing scenarios that are closest to the gap; caller feeds these to\n * their LLM proposer as few-shot examples. */\n neighbors: DatasetScenario[]\n /** Suggested direction — e.g. \"harder variants\", \"edge cases of X\", \"failure class Y\". */\n direction: string\n /** Priority score — higher = more information-dense gap. 0..1. */\n priority: number\n}\n\nexport interface ActiveLearningOptions {\n /** Minimum scenarios per difficulty band to count as \"covered\". */\n minPerBand?: number\n /** Variance threshold above which a scenario's dimension is \"unstable\". */\n varianceThreshold?: number\n /** Max synthesis targets returned. */\n topK?: number\n}\n\nexport async function proposeSynthesisTargets(\n dataset: Dataset,\n traceStore: TraceStore,\n options: ActiveLearningOptions = {},\n): Promise<SynthesisTarget[]> {\n const minPerBand = options.minPerBand ?? 5\n const varianceThreshold = options.varianceThreshold ?? 0.05\n const topK = options.topK ?? 10\n const scenarios = dataset.all()\n\n const targets: SynthesisTarget[] = []\n\n // 1. Difficulty coverage gaps\n const BANDS: Array<DatasetScenario['difficulty']> = ['easy', 'medium', 'hard', 'extreme']\n for (const band of BANDS) {\n const count = scenarios.filter((s) => s.difficulty === band).length\n if (count < minPerBand) {\n const neighbors = scenarios.filter((s) => s.difficulty === band).slice(0, 3)\n targets.push({\n reason: 'difficulty-gap',\n description: `difficulty=\"${band}\" has ${count} scenario(s) — below minimum ${minPerBand}`,\n neighbors: [...neighbors],\n direction: `create more \"${band}\" scenarios; reuse domain but shift complexity`,\n priority: Math.max(0, 1 - count / minPerBand),\n })\n }\n }\n\n // 2. Undersampled scenarios (few runs per scenario)\n const runs = await traceStore.listRuns()\n const runCountByScenario = new Map<string, number>()\n for (const r of runs) {\n runCountByScenario.set(r.scenarioId, (runCountByScenario.get(r.scenarioId) ?? 0) + 1)\n }\n const runCounts = [...runCountByScenario.values()]\n const p25 = runCounts.length > 0 ? quantile(runCounts, 0.25) : 0\n for (const s of scenarios) {\n const count = runCountByScenario.get(s.id) ?? 0\n if (count <= p25 && count < 3) {\n targets.push({\n reason: 'undersampled',\n description: `scenario \"${s.id}\" has only ${count} run(s)`,\n neighbors: [s],\n direction: `create near-duplicates of \"${s.id}\" to stabilize its mean`,\n priority: Math.max(0, 1 - count / 3) * 0.7,\n })\n }\n }\n\n // 3. High-variance scenarios (same scenario scored inconsistently)\n for (const s of scenarios) {\n const sRuns = runs.filter((r) => r.scenarioId === s.id)\n const scores = sRuns\n .map((r) => r.outcome?.score)\n .filter((x): x is number => typeof x === 'number')\n if (scores.length < 3) continue\n const mean = scores.reduce((a, b) => a + b, 0) / scores.length\n const variance = scores.reduce((a, b) => a + (b - mean) ** 2, 0) / scores.length\n if (variance > varianceThreshold) {\n targets.push({\n reason: 'high-variance',\n description: `scenario \"${s.id}\" has unstable scoring (variance ${variance.toFixed(3)})`,\n neighbors: [s],\n direction: `disambiguate the scenario description — current wording admits too many valid interpretations`,\n priority: Math.min(1, variance * 5),\n })\n }\n }\n\n // 4. Failure-class clusters — run classifier across the corpus\n const failureByClass = new Map<string, Run[]>()\n for (const run of runs) {\n if (run.outcome?.pass === true) continue\n const spans = await traceStore.spans({ runId: run.runId })\n const events = await traceStore.events({ runId: run.runId })\n const { failureClass } = classifyFailure({ run, spans, events })\n if (failureClass === 'success' || failureClass === 'unknown') continue\n const arr = failureByClass.get(failureClass) ?? []\n arr.push(run)\n failureByClass.set(failureClass, arr)\n }\n for (const [cls, runs] of failureByClass) {\n if (runs.length < 3) continue\n const affectedScenarios = [...new Set(runs.map((r) => r.scenarioId))]\n const neighbors = scenarios.filter((s) => affectedScenarios.includes(s.id)).slice(0, 3)\n targets.push({\n reason: 'failure-cluster',\n description: `failure class \"${cls}\" observed ${runs.length}× across ${affectedScenarios.length} scenario(s)`,\n neighbors,\n direction: `create scenarios that exercise \"${cls}\" recovery — currently a systematic weakness`,\n priority: Math.min(1, runs.length / 10),\n })\n }\n\n return targets.sort((a, b) => b.priority - a.priority).slice(0, topK)\n}\n\nfunction quantile(xs: number[], p: number): number {\n const sorted = [...xs].sort((a, b) => a - b)\n const idx = p * (sorted.length - 1)\n const lo = Math.floor(idx)\n const hi = Math.ceil(idx)\n return sorted[lo]! + (sorted[hi]! - sorted[lo]!) * (idx - lo)\n}\n","/**\n * One-shot deprecation warnings. A deprecated surface warns the FIRST time it\n * is used in a process — loud enough to be seen, quiet enough not to flood a\n * matrix run that constructs it per cell.\n */\n\nconst warned = new Set<string>()\n\n/** Emit `message` on console.warn once per process per `key`. */\nexport function warnDeprecatedOnce(key: string, message: string): void {\n if (warned.has(key)) return\n warned.add(key)\n console.warn(`[agent-eval deprecation] ${message}`)\n}\n\n/** Test seam: forget prior warnings so once-semantics can be asserted. */\nexport function resetDeprecationWarnings(): void {\n warned.clear()\n}\n","import { warnDeprecatedOnce } from './deprecation'\nimport type { CheckResult, ProductClientConfig, RouteMap, TestResult } from './types'\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000\n\n/**\n * ProductClient — configurable HTTP client for exercising any agent's APIs.\n *\n * Routes are config, not hardcoded. Each agent provides its own RouteMap.\n *\n * @deprecated A one-product REST client does not belong in the generic\n * substrate. Moves to the product repo in the next major\n * (tangle-network/agent-runtime#694); vendor it if you construct it directly.\n */\nexport class ProductClient {\n private baseUrl: string\n private routes: RouteMap\n private cookies: string = ''\n private timeoutMs: number\n\n constructor(config: ProductClientConfig) {\n warnDeprecatedOnce(\n 'ProductClient',\n 'ProductClient is deprecated and moves to the product repo in the next major (tangle-network/agent-runtime#694).',\n )\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this.routes = config.routes\n this.timeoutMs = config.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS\n }\n\n private route(name: keyof RouteMap): string {\n const path = this.routes[name]\n if (!path) throw new Error(`Route \"${name}\" not configured`)\n return path\n }\n\n /**\n * Single HTTP boundary for every JSON request. Aborts after `timeoutMs`,\n * checks `res.ok` BEFORE parsing, and throws `${method} ${path} failed:\n * HTTP ${status} — ${body}` on a non-ok response so a 4xx/5xx error body\n * can never be parsed as a success shape. Callers inspect the resolved\n * value only after a successful return.\n */\n private async request(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs)\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n Origin: this.baseUrl,\n Cookie: this.cookies,\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n signal: controller.signal,\n })\n } finally {\n clearTimeout(timeout)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`${method} ${path} failed: HTTP ${res.status} — ${text.slice(0, 500)}`)\n }\n return res.json() as Promise<Record<string, unknown>>\n }\n\n /**\n * Read a required collection field. A missing/non-array field is a contract\n * violation (wrong route, drift, partial body) — surface it loud instead of\n * masking it as a healthy empty set. A genuinely empty `[]` passes through.\n */\n private requireArray<T>(res: Record<string, unknown>, field: string): T[] {\n const value = res[field]\n if (!Array.isArray(value)) {\n throw new Error(\n `Response missing array field \"${field}\" (got ${typeof value}: ${JSON.stringify(value)?.slice(0, 200)})`,\n )\n }\n return value as T[]\n }\n\n async signup(name: string, email: string, password: string): Promise<{ userId: string }> {\n const res = await this.post(this.route('signup'), { name, email, password })\n const user = res.user as Record<string, unknown> | undefined\n if (!user?.id) throw new Error(`Signup failed: ${JSON.stringify(res)}`)\n return { userId: user.id as string }\n }\n\n async login(email: string, password: string): Promise<void> {\n const res = await fetch(`${this.baseUrl}${this.route('login')}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Origin: this.baseUrl },\n body: JSON.stringify({ email, password }),\n redirect: 'manual',\n })\n const setCookie = res.headers.get('set-cookie')\n if (setCookie) {\n this.cookies = setCookie.split(';')[0] ?? ''\n }\n const body = (await res.json()) as Record<string, unknown>\n if (!body.user) throw new Error(`Login failed: ${JSON.stringify(body)}`)\n }\n\n async createWorkspace(name: string, type = 'project'): Promise<string> {\n const res = await this.post(this.route('workspaces'), { name, type })\n const ws = res.workspace as Record<string, unknown> | undefined\n if (!ws?.id) throw new Error(`Workspace creation failed: ${JSON.stringify(res)}`)\n return ws.id as string\n }\n\n async createThread(workspaceId: string): Promise<string> {\n const res = await this.post(this.route('threads'), { workspaceId })\n const thread = res.thread as Record<string, unknown> | undefined\n if (!thread?.id) throw new Error(`Thread creation failed: ${JSON.stringify(res)}`)\n return thread.id as string\n }\n\n async chat(\n workspaceId: string,\n threadId: string,\n content: string,\n _opts?: { blockPatterns?: RegExp[] },\n ): Promise<{ text: string; blocks: { type: string; title: string }[] }> {\n const res = await fetch(`${this.baseUrl}${this.route('chat')}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Origin: this.baseUrl,\n Cookie: this.cookies,\n },\n body: JSON.stringify({ workspaceId, threadId, content }),\n })\n\n if (!res.ok || !res.body) throw new Error(`Chat failed: ${res.status}`)\n\n // Parse NDJSON stream\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n let text = ''\n const blocks: { type: string; title: string }[] = []\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buf += decoder.decode(value, { stream: true })\n const lines = buf.split('\\n')\n buf = lines.pop() ?? ''\n for (const line of lines) {\n if (!line.trim()) continue\n try {\n const event = JSON.parse(line) as { type?: string; data?: { delta?: string } }\n if (event.type === 'message.part.updated' && event.data?.delta) {\n text += event.data.delta\n }\n } catch {\n /* skip non-JSON lines */\n }\n }\n }\n\n // Extract :::blocks from text\n const blockRe = /:::(\\w+)\\s*\\n([\\s\\S]*?)\\n\\s*:::/g\n let match: RegExpExecArray | null = blockRe.exec(text)\n while (match !== null) {\n const fields: Record<string, string> = {}\n for (const line of match[2]!.split('\\n')) {\n const idx = line.indexOf(':')\n if (idx > 0) fields[line.slice(0, idx).trim()] = line.slice(idx + 1).trim()\n }\n blocks.push({ type: match[1]!, title: fields.title ?? '' })\n match = blockRe.exec(text)\n }\n\n return { text, blocks }\n }\n\n async getTasks(\n workspaceId: string,\n ): Promise<{ id: string; title: string; status: string; priority: string }[]> {\n const res = await this.get(`${this.route('tasks')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; status: string; priority: string }>(\n res,\n 'tasks',\n )\n }\n\n async getEvents(workspaceId: string): Promise<{ id: string; title: string; type: string }[]> {\n const res = await this.get(`${this.route('events')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; type: string }>(res, 'events')\n }\n\n async getApprovals(\n workspaceId: string,\n ): Promise<{ id: string; title: string; status: string; type: string }[]> {\n const res = await this.get(`${this.route('approvals')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; title: string; status: string; type: string }>(\n res,\n 'actions',\n )\n }\n\n async getVaultTree(workspaceId: string): Promise<string[]> {\n const res = await this.get(`${this.route('vault')}?workspaceId=${workspaceId}`)\n const paths: string[] = []\n function extract(nodes: unknown[]) {\n for (const n of nodes) {\n const node = n as { path?: string; type?: string; children?: unknown[] }\n if (node.type === 'file' && node.path) paths.push(node.path)\n if (node.children) extract(node.children)\n }\n }\n extract(this.requireArray<unknown>(res, 'tree'))\n return paths\n }\n\n async approveAction(workspaceId: string, id: string): Promise<void> {\n await this.patch(this.route('approvals'), { workspaceId, id, status: 'approved' })\n }\n\n async rejectAction(workspaceId: string, id: string, reason: string): Promise<void> {\n await this.patch(this.route('approvals'), { workspaceId, id, status: 'rejected', reason })\n }\n\n async getGenerations(\n workspaceId: string,\n ): Promise<{ id: string; type: string; prompt: string }[]> {\n const res = await this.get(`${this.route('generations')}?workspaceId=${workspaceId}`)\n return this.requireArray<{ id: string; type: string; prompt: string }>(res, 'generations')\n }\n\n /** Generic GET for custom routes */\n async get(path: string): Promise<Record<string, unknown>> {\n return this.request('GET', path)\n }\n\n /** Generic POST for custom routes */\n async post(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n return this.request('POST', path, body)\n }\n\n /** Generic PATCH for custom routes */\n async patch(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n return this.request('PATCH', path, body)\n }\n}\n\n/**\n * Run a full e2e workflow test against a live product.\n *\n * The `workflow` callback receives a ProductClient and returns CheckResults.\n * This is the generic harness — each agent defines its own workflow steps.\n */\nexport async function runE2EWorkflow(\n client: ProductClient,\n name: string,\n workflow: (client: ProductClient) => Promise<CheckResult[]>,\n): Promise<TestResult> {\n const start = Date.now()\n const checks: CheckResult[] = []\n\n try {\n const results = await workflow(client)\n checks.push(...results)\n } catch (err) {\n checks.push({\n name: 'fatal_error',\n passed: false,\n expected: 'no crash',\n actual: err instanceof Error ? err.message : String(err),\n })\n }\n\n return {\n name,\n passed: checks.every((c) => c.passed),\n duration: Date.now() - start,\n detail: `${checks.filter((c) => c.passed).length}/${checks.length} checks passed`,\n checks,\n }\n}\n","/**\n * CommandRunner — abstract subprocess execution surface.\n *\n * Layers in a {@link MultiLayerVerifier} that need to invoke external\n * tools (compilers, test runners, package managers) call out via this\n * interface rather than directly using `child_process`. Two reasons:\n *\n * 1. **Sandbox interchangeability.** A run that targets a sandbox box\n * (via SDK-specific Box.exec) and a run that targets the host both\n * satisfy this same contract. The harness doesn't care which.\n * 2. **Testability.** Tests inject a fake runner and assert on calls\n * without spawning real subprocesses.\n *\n * agent-eval ships only the local implementation (host-process). Sandbox\n * implementations live with their consumer because they depend on\n * SDK-specific Box / Sandbox types that don't belong in this package.\n */\n\nimport {\n accessSync,\n existsSync,\n constants as fsConstants,\n readdirSync,\n readFileSync,\n statSync,\n} from 'node:fs'\nimport { delimiter, join } from 'node:path'\nimport { DEFAULT_BOUNDED_PROCESS_TIMEOUT_MS, runBoundedProcess } from './bounded-process'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface RunCommandInput {\n /** Executable name, looked up via PATH unless absolute. */\n cmd: string\n /** Argument vector, NOT shell-interpolated. Each element passed to argv. */\n argv: string[]\n /** Working directory. Defaults to runner's notion of cwd if omitted. */\n cwd?: string\n /**\n * Wall-clock cap in ms. The runner SHOULD return `timedOut: true` when\n * exceeded; callers MAY treat status null + timedOut as \"killed.\"\n *\n * Omitting it does NOT mean unbounded: {@link localCommandRunner} then\n * applies {@link LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS}. A command that\n * legitimately runs longer than that names its own `capMs`; it is never\n * killed silently, because a run stopped by the bound comes back with\n * `timedOut: true` and `status: null`.\n */\n capMs?: number\n /** Env overrides merged on top of the runner's base environment. */\n env?: Record<string, string>\n /** Optional stdin payload. */\n stdin?: string\n}\n\nexport interface RunCommandResult {\n /** Exit code, or null when the process couldn't start / was killed. */\n status: number | null\n stdout: string\n stderr: string\n durationMs: number\n timedOut: boolean\n /** Non-fatal runner-side error (binary missing, signal, etc.). */\n runnerError?: string\n}\n\nexport interface DirEntry {\n name: string\n isDirectory: boolean\n isFile: boolean\n /** File size in bytes. `null` for directories (not stat'd). */\n sizeBytes: number | null\n}\n\nexport interface CommandRunner {\n /** Identifier for telemetry + logs. Open-ended literal-union for new runners. */\n readonly name: string\n /** Execute a command in the runner's environment. */\n run(input: RunCommandInput): Promise<RunCommandResult>\n /** True iff `<name>` resolves on the runner's PATH. */\n hasBin(name: string): Promise<boolean>\n /** True iff the given path exists in the runner's filesystem. */\n fileExists(path: string): Promise<boolean>\n /** Read a file. Returns `null` if missing or unreadable. */\n readFile(path: string): Promise<string | null>\n /** List a directory. Returns `[]` if unreadable / missing. */\n readDir(path: string): Promise<DirEntry[]>\n}\n\n// ─── Local runner ───────────────────────────────────────────────────────\n\n/**\n * Host-process runner, mapped onto {@link runBoundedProcess} so the package\n * has one spawn site rather than two.\n *\n * It used `spawnSync` and therefore had none of the bounds that runner exists\n * to provide: a `capMs` timeout killed the direct child and left any\n * descendant it had started running, a killed run could still report exit\n * code 0, captured output was unbounded, and the whole run blocked the event\n * loop. This runner spawns build, test and lint commands, which are exactly\n * the commands most likely to start descendants.\n *\n * It is not the package's last private spawn: `nodeProcessRunner`\n * (`src/trace-repair/docker-environment.ts`) and `runProcess`\n * (`src/campaign/external-optimizer-subprocess.ts`) still spawn their own\n * detached children, and several one-shot `spawnSync` git and CLI calls\n * remain. What this removes is the second spawn behind the `CommandRunner`\n * contract, which is the one that graded build, test and lint commands.\n *\n * Two behaviours the mapping changes on purpose:\n * - a run with no `capMs` is now bounded by\n * {@link LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS} instead of running forever;\n * - the run no longer blocks the event loop, so a minutes-long `capMs` no\n * longer stalls everything else in the process.\n */\n/**\n * Wall clock {@link localCommandRunner} applies when the caller names no\n * `capMs`. It is `runBoundedProcess`'s own default, stated here because this\n * runner used to be unbounded: a consumer whose command runs longer names its\n * own `capMs`, and a run the bound stops says so with `timedOut: true`.\n */\nexport const LOCAL_COMMAND_RUNNER_DEFAULT_CAP_MS = DEFAULT_BOUNDED_PROCESS_TIMEOUT_MS\n\nexport const localCommandRunner: CommandRunner = {\n name: 'local',\n async run(input: RunCommandInput): Promise<RunCommandResult> {\n const result = await runBoundedProcess({\n command: input.cmd,\n args: input.argv,\n envMode: 'merge',\n env: { CI: '1', ...(input.env ?? {}) },\n ...(input.cwd === undefined ? {} : { cwd: input.cwd }),\n ...(input.capMs === undefined ? {} : { timeoutMs: input.capMs }),\n ...(input.stdin === undefined ? {} : { stdin: input.stdin }),\n })\n // `status: null` keeps its documented meaning — the process could not\n // start, or it was killed. A stdin payload the child did not drain is\n // neither: that command ran and exited on its own, so it keeps its code.\n const killed = result.killedByTimeout || result.killedBySignal\n return {\n status: killed || !result.spawned ? null : result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n durationMs: result.wallMs,\n timedOut: result.killedByTimeout,\n ...(result.runnerError === undefined ? {} : { runnerError: result.runnerError }),\n }\n },\n async hasBin(name: string): Promise<boolean> {\n return resolveBinOnPath(name) !== null\n },\n async fileExists(path: string): Promise<boolean> {\n return existsSync(path)\n },\n async readFile(path: string): Promise<string | null> {\n try {\n return readFileSync(path, 'utf8')\n } catch (err) {\n // ENOENT is the only \"legitimately absent\" signal → null. Any other\n // errno (EACCES, EISDIR, EIO, …) is a real failure that must NOT\n // masquerade as \"file not present\" — surface it so callers don't\n // treat a permission/IO error as a missing artifact.\n if (isErrnoCode(err, 'ENOENT')) return null\n throw err\n }\n },\n async readDir(path: string): Promise<DirEntry[]> {\n let entries: string[]\n try {\n entries = readdirSync(path)\n } catch (err) {\n // Same ENOENT-vs-real-error split as readFile: a missing directory\n // is legitimately empty (→ []); EACCES/ENOTDIR/EIO must surface so\n // an unreadable directory isn't silently reported as having no files.\n if (isErrnoCode(err, 'ENOENT')) return []\n throw err\n }\n const out: DirEntry[] = []\n for (const name of entries) {\n try {\n const st = statSync(join(path, name))\n out.push({\n name,\n isDirectory: st.isDirectory(),\n isFile: st.isFile(),\n sizeBytes: st.isFile() ? st.size : null,\n })\n } catch (err) {\n // An entry that vanished between readdir and stat (TOCTOU) is a\n // benign race → skip. Any other errno surfaces.\n if (isErrnoCode(err, 'ENOENT')) continue\n throw err\n }\n }\n return out\n },\n}\n\nfunction isErrnoCode(err: unknown, code: NodeJS.ErrnoException['code']): boolean {\n return typeof err === 'object' && err !== null && (err as NodeJS.ErrnoException).code === code\n}\n\n/**\n * Resolve `name` to an executable absolute path using the runner's PATH,\n * or `null` if not found. Cross-platform: does not depend on `which`\n * (absent on Windows) or a `command -v` shell (absent on minimal\n * containers). On Windows, candidate extensions come from PATHEXT.\n *\n * Throws only on a non-ENOENT/EACCES filesystem error while probing a\n * candidate — those indicate a real IO fault, not \"binary absent.\"\n */\nfunction resolveBinOnPath(name: string): string | null {\n // An explicit path component means PATH lookup doesn't apply: probe directly.\n if (name.includes('/') || name.includes('\\\\')) {\n return isExecutable(name) ? name : null\n }\n const pathEnv = process.env.PATH ?? ''\n const dirs = pathEnv.split(delimiter).filter((d) => d.length > 0)\n const exts =\n process.platform === 'win32'\n ? (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';').filter((e) => e.length > 0)\n : ['']\n for (const dir of dirs) {\n for (const ext of exts) {\n const candidate = join(dir, name + ext)\n if (isExecutable(candidate)) return candidate\n }\n }\n return null\n}\n\nfunction isExecutable(path: string): boolean {\n try {\n // On win32 X_OK is a no-op; presence of the file (with a PATHEXT\n // extension) is the executability signal there.\n accessSync(path, process.platform === 'win32' ? fsConstants.F_OK : fsConstants.X_OK)\n return true\n } catch (err) {\n // Not found / not executable / not permitted → \"not a usable binary\n // here,\" keep scanning. A different errno (EIO, ELOOP, …) is a real\n // fault and must surface rather than silently yield a false negative.\n if (isErrnoCode(err, 'ENOENT') || isErrnoCode(err, 'EACCES') || isErrnoCode(err, 'ENOTDIR')) {\n return false\n }\n throw err\n }\n}\n","/**\n * Streaming detectors — the canonical, online failure-mode kernel.\n *\n * A `StreamingDetector` is a pure incremental reducer: fold one normalized step, get a signal the\n * moment a threshold trips (else null). The SAME kernel runs in two places, so the logic lives once:\n * - ONLINE, over a live agent pipe (a worker's tool-call stream) → raise a finding mid-run.\n * - INSIDE the control loop (`control-runtime`) → its `stopOn*` policies fold these detectors.\n *\n * Detectors are stateful but self-contained; `streak` is exposed for telemetry and `reset` clears it.\n * Fingerprinting is the CALLER's job — the control loop hashes state/action with `stableFingerprint`,\n * a tool-call pipe hashes args with `argHash` — so a detector stays agnostic to what it's watching.\n */\n\nimport type { FailureClass } from '../trace/schema'\n\nexport type DetectorSeverity = 'info' | 'warn' | 'critical'\n\n/** A normalized step a detector folds over. Fields are optional; each detector reads only what it\n * needs (repeated-action → `actionFingerprint`; no-progress → `stateFingerprint` + `score`;\n * error-streak → `status`). */\nexport interface DetectorEvent {\n /** Fingerprint of the action/tool-call this step took (caller pre-hashes). */\n readonly actionFingerprint?: string\n /** Fingerprint of observable state AFTER this step. */\n readonly stateFingerprint?: string\n /** Score after this step (the score-flat half of no-progress). */\n readonly score?: number\n /** Whether this step errored. */\n readonly status?: 'ok' | 'error'\n /** Free-form label carried into the signal evidence (e.g. the tool name). */\n readonly label?: string\n}\n\nexport interface DetectorSignal {\n readonly detector: string\n readonly severity: DetectorSeverity\n readonly failureClass?: FailureClass\n readonly reason: string\n /** Consecutive matching steps at the moment the signal fired. */\n readonly streak: number\n readonly evidence?: Record<string, unknown>\n}\n\nexport interface StreamingDetector {\n readonly id: string\n /** Current streak (consecutive matching steps) — for telemetry/introspection between observes. */\n readonly streak: number\n /** Fold one event; return a signal when the threshold trips, else null. */\n observe(event: DetectorEvent): DetectorSignal | null\n /** Clear all state. */\n reset(): void\n}\n\nexport interface RepeatedActionOptions {\n /** Signal once the same action fingerprint repeats this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal (the streak is still tracked, for telemetry). */\n readonly maxRepeated?: number\n readonly severity?: DetectorSeverity\n /** Failure class to stamp on the signal (default `tool_recovery_failure`). */\n readonly failureClass?: FailureClass\n}\n\n/** Same action fingerprint N consecutive steps = a stuck loop (the #1 long-horizon failure mode). */\nexport function repeatedActionDetector(opts: RepeatedActionOptions = {}): StreamingDetector {\n const max = opts.maxRepeated ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let last: string | undefined\n let streak = 0\n return {\n id: 'repeated-action',\n get streak() {\n return streak\n },\n observe(event) {\n const fp = event.actionFingerprint\n if (fp === undefined) return null\n streak = fp === last ? streak + 1 : 1\n last = fp\n if (max <= 0 || streak < max) return null\n return {\n detector: 'repeated-action',\n severity,\n failureClass,\n reason: `stuck: repeated same action for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { action: event.label } } : {}),\n }\n },\n reset() {\n last = undefined\n streak = 0\n },\n }\n}\n\nexport interface NoProgressOptions {\n /** Signal once state is unchanged AND score is flat for this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal. */\n readonly maxNoProgress?: number\n /** Minimum |score change| that counts as progress (default 0.001). */\n readonly minScoreDelta?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** State + score unchanged across N steps = spinning wheels. Compares each step to the previous one,\n * so prime with the initial state (observe it once before the first real step) to detect on step 1. */\nexport function noProgressDetector(opts: NoProgressOptions = {}): StreamingDetector {\n const max = opts.maxNoProgress ?? 3\n const minScoreDelta = opts.minScoreDelta ?? 0.001\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let lastState: string | undefined\n let lastScore: number | undefined\n let streak = 0\n return {\n id: 'no-progress',\n get streak() {\n return streak\n },\n observe(event) {\n const stateUnchanged = lastState !== undefined && lastState === event.stateFingerprint\n const scoreFlat = Math.abs((event.score ?? 0) - (lastScore ?? 0)) < minScoreDelta\n streak = stateUnchanged && scoreFlat ? streak + 1 : 0\n lastState = event.stateFingerprint\n lastScore = event.score\n if (max <= 0 || streak < max) return null\n return {\n detector: 'no-progress',\n severity,\n failureClass,\n reason: `stuck: no state/score progress for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { state: event.label } } : {}),\n }\n },\n reset() {\n lastState = undefined\n lastScore = undefined\n streak = 0\n },\n }\n}\n\nexport interface ErrorStreakOptions {\n /** Signal once this many CONSECUTIVE steps errored (default 3). `<= 0` disables. */\n readonly maxErrors?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** N consecutive tool errors = the worker is hammering a broken approach. */\nexport function errorStreakDetector(opts: ErrorStreakOptions = {}): StreamingDetector {\n const max = opts.maxErrors ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let streak = 0\n return {\n id: 'error-streak',\n get streak() {\n return streak\n },\n observe(event) {\n if (event.status === undefined) return null\n streak = event.status === 'error' ? streak + 1 : 0\n if (max <= 0 || streak < max) return null\n return {\n detector: 'error-streak',\n severity,\n failureClass,\n reason: `stuck: ${streak} consecutive errored step(s)`,\n streak,\n ...(event.label ? { evidence: { lastError: event.label } } : {}),\n }\n },\n reset() {\n streak = 0\n },\n }\n}\n\n/** Fold one event through many detectors at once; returns every signal that fired this step. The\n * natural shape for an online pipe watching with a whole panel of detectors. */\nexport function observeAll(\n detectors: ReadonlyArray<StreamingDetector>,\n event: DetectorEvent,\n): DetectorSignal[] {\n const signals: DetectorSignal[] = []\n for (const d of detectors) {\n const s = d.observe(event)\n if (s) signals.push(s)\n }\n return signals\n}\n","/**\n * Policy-based agent control runtime.\n *\n * This is the minimal reusable loop behind driver-agent patterns:\n *\n * observe state -> validate -> decide next action -> act -> observe -> ...\n *\n * It deliberately does not model named \"topologies\". Direct execution,\n * critic/revise, driver intervention, specialist calls, and human escalation\n * are all just actions chosen by the control policy.\n */\n\nimport { noProgressDetector, repeatedActionDetector } from './detectors'\nimport { canonicalString } from './ledger-core/canonical'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport type ControlSeverity = 'info' | 'warning' | 'error' | 'critical'\nexport type ControlActionFailureMode = 'continue' | 'stop'\n\nexport interface ControlEvalResult {\n /** Stable validator or judge id. */\n id: string\n /** Whether this check passed. */\n passed: boolean\n /** Optional normalized score. 1 = best, 0 = worst. */\n score?: number\n /** Objective validators should usually be \"error\" or \"critical\" when failed. */\n severity?: ControlSeverity\n /** Human-readable result. */\n detail?: string\n /** Small evidence string or pointer. Avoid large payloads. */\n evidence?: string\n /** True when the result came from deterministic state, not LLM judgment. */\n objective?: boolean\n /** Structured details for downstream control policies and reports. */\n metadata?: Record<string, unknown>\n}\n\nexport interface ControlBudget {\n maxSteps: number\n maxWallMs?: number\n maxCostUsd?: number\n}\n\nexport interface ControlStopPolicies<TState, TAction> {\n /**\n * Stop after N consecutive steps with no state fingerprint change and\n * less than `minScoreDelta` score movement. Disabled when omitted.\n */\n maxNoProgressSteps?: number\n /**\n * Stop after the same action fingerprint is selected N consecutive\n * times. Disabled when omitted.\n */\n maxRepeatedActions?: number\n /** Minimum score movement that counts as progress. Default 0.001. */\n minScoreDelta?: number\n /** Override the default JSON/string fingerprint for state comparisons. */\n stateFingerprint?: (state: TState) => string\n /** Override the default JSON/string fingerprint for repeated-action checks. */\n actionFingerprint?: (action: TAction) => string\n}\n\nexport interface ControlContext<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n budget: ControlBudget\n stepIndex: number\n wallMs: number\n spentCostUsd: number\n remainingCostUsd?: number\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport type ControlDecision<TAction> =\n | {\n type: 'continue'\n action: TAction\n reason?: string\n }\n | {\n type: 'stop'\n reason: string\n pass?: boolean\n score?: number\n /** Canonical task-failure class when this stop represents a failed task. */\n failureClass?: FailureClass\n }\n\nexport interface StopDecision {\n stop: boolean\n pass: boolean\n reason: string\n score?: number\n failureClass?: FailureClass\n}\n\nexport interface ControlActionOutcome<TActionResult> {\n ok: boolean\n result?: TActionResult\n error?: string\n costUsd?: number\n durationMs: number\n}\n\nexport interface ControlRuntimeError {\n phase: 'observe' | 'validate' | 'decide' | 'act' | 'stop-policy' | 'on-step' | 'trace'\n stepIndex: number\n message: string\n}\n\nexport interface ControlStep<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n index: number\n decision: ControlDecision<TAction>\n beforeState: TState\n afterState: TState\n evalsBefore: TEval[]\n evalsAfter: TEval[]\n actionOutcome?: ControlActionOutcome<TActionResult>\n startedAt: string\n endedAt: string\n}\n\nexport interface ControlRunResult<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n pass: boolean\n completed: boolean\n reason: string\n score?: number\n steps: ControlStep<TState, TAction, TActionResult, TEval>[]\n finalState: TState | undefined\n finalEvals: TEval[]\n wallMs: number\n spentCostUsd: number\n /** null when the run executed without a TraceEmitter wired (no run record was persisted). */\n runId: string | null\n failureClass?: FailureClass\n runtimeErrors: ControlRuntimeError[]\n stoppedBy: 'policy' | 'stop-policy' | 'budget' | 'abort' | 'runtime-error'\n}\n\nexport interface ControlRuntimeConfig<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n budget?: Partial<ControlBudget>\n signal?: AbortSignal\n /** Defaults to `continue`: action failures are recorded, then the policy gets another chance. */\n actionFailure?: ControlActionFailureMode\n /**\n * Extract cost from an action result. Used for `maxCostUsd` budget\n * enforcement and trace budget ledger emission.\n */\n getActionCostUsd?: (ctx: {\n action: TAction\n result: TActionResult\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n }) => number | undefined\n\n /** Read typed task/product state. Prefer structured state over transcript-only context. */\n observe: (ctx: {\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TState> | TState\n\n /** Objective validators first, subjective judges only where objective state is insufficient. */\n validate: (ctx: {\n intent: string\n state: TState\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TEval[]> | TEval[]\n\n /** Choose the next control action. Can call a worker, ask user, run critic, inspect state, or stop. */\n decide: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<ControlDecision<TAction>> | ControlDecision<TAction>\n\n /** Execute the action selected by the policy. */\n act: (\n action: TAction,\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<TActionResult> | TActionResult\n\n /** Final stopping policy. Called before decide and after each action. */\n shouldStop?: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<StopDecision> | StopDecision\n\n /** Optional hook for tracing or live progress updates. */\n onStep?: (step: ControlStep<TState, TAction, TActionResult, TEval>) => Promise<void> | void\n\n /** Optional generic stuck-loop policies. Custom `shouldStop` still runs first. */\n stopPolicies?: ControlStopPolicies<TState, TAction>\n\n /** Optional trace sink. Emits one run plus one span per control step. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n}\n\nconst DEFAULT_BUDGET: ControlBudget = {\n maxSteps: 8,\n maxWallMs: 5 * 60 * 1000,\n}\n\nexport async function runAgentControlLoop<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n>(\n config: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n const budget = normalizeBudget(config.budget)\n const actionFailure = config.actionFailure ?? 'continue'\n const controller = new AbortController()\n const upstreamAbort = () => controller.abort(config.signal?.reason)\n if (config.signal) {\n if (config.signal.aborted) controller.abort(config.signal.reason)\n else config.signal.addEventListener('abort', upstreamAbort, { once: true })\n }\n\n const started = Date.now()\n const wallTimer = budget.maxWallMs\n ? setTimeout(\n () => controller.abort(new Error('control runtime wall timeout')),\n budget.maxWallMs,\n )\n : undefined\n const history: ControlStep<TState, TAction, TActionResult, TEval>[] = []\n const emitter = config.store ? new TraceEmitter(config.store) : undefined\n let spentCostUsd = 0\n const runtimeErrors: ControlRuntimeError[] = []\n // The stuck-detection kernels (shared with the online detectors). Thresholds 0 = disabled; the\n // streak is still tracked for telemetry. Both stops report `tool_recovery_failure`.\n const repeatedDetector = repeatedActionDetector({\n maxRepeated: config.stopPolicies?.maxRepeatedActions ?? 0,\n })\n const progressDetector = noProgressDetector({\n maxNoProgress: config.stopPolicies?.maxNoProgressSteps ?? 0,\n minScoreDelta: config.stopPolicies?.minScoreDelta ?? 0.001,\n })\n\n try {\n if (emitter) {\n await runTrace(runtimeErrors, 0, () =>\n emitter.startRun({\n scenarioId: config.scenarioId ?? 'agent-control-loop',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n intent: config.intent.slice(0, 120),\n maxSteps: String(budget.maxSteps),\n ...(budget.maxCostUsd !== undefined ? { maxCostUsd: String(budget.maxCostUsd) } : {}),\n },\n }),\n )\n }\n\n let state: TState\n let evals: TEval[]\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n const error = runtimeError('observe', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(emitter, evals, 'initial', runtimeErrors, 0)\n } catch (err) {\n const error = runtimeError('validate', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: state,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n // Prime the no-progress detector with the initial state + score so step 0 can already detect a\n // no-op (mirrors the pre-loop fingerprint baseline). The priming observe never signals (streak 0).\n progressDetector.observe({\n stateFingerprint: fingerprintState(state, config.stopPolicies),\n score: averageScore(evals),\n })\n\n for (let stepIndex = 0; stepIndex < budget.maxSteps; stepIndex++) {\n if (controller.signal.aborted) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: abortReason(controller.signal),\n score: undefined,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'timeout',\n runtimeErrors,\n stoppedBy: 'abort',\n })\n }\n\n const budgetStop = budgetStopDecision(budget, spentCostUsd)\n if (budgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: budgetStop.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const ctx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let stop: StopDecision\n try {\n stop = config.shouldStop ? await config.shouldStop(ctx) : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (stop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: stop.pass,\n completed: true,\n reason: stop.reason,\n score: stop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: stop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n let decision: ControlDecision<TAction>\n try {\n decision = await config.decide(ctx)\n } catch (err) {\n runtimeErrors.push(runtimeError('decide', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (decision.type === 'stop') {\n const pass = decision.pass ?? false\n return finish(emitter, {\n intent: config.intent,\n pass,\n completed: true,\n reason: decision.reason,\n score: decision.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: pass ? undefined : (decision.failureClass ?? 'unknown'),\n runtimeErrors,\n stoppedBy: 'policy',\n })\n }\n\n const actionFingerprint = fingerprintAction(decision.action, config.stopPolicies)\n const repeatedActionSignal = repeatedDetector.observe({ actionFingerprint })\n const repeatedActionStreak = repeatedDetector.streak\n if (repeatedActionSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: repeatedActionSignal.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const beforeState = state\n const evalsBefore = evals\n const scoreBefore = averageScore(evals)\n const actionStarted = Date.now()\n const stepHandle = emitter\n ? await runTrace(runtimeErrors, stepIndex, () =>\n emitter.tool({\n name: `control-step-${stepIndex}`,\n toolName: 'agent-control-action',\n args: decision.action,\n attributes: {\n decision: decision.reason ?? 'continue',\n repeatedActionStreak,\n },\n }),\n )\n : undefined\n let actionOutcome: ControlActionOutcome<TActionResult>\n try {\n const result = await config.act(decision.action, ctx)\n const rawCostUsd = config.getActionCostUsd?.({\n action: decision.action,\n result,\n state,\n evals,\n history,\n })\n const costUsd = normalizeActionCostUsd(rawCostUsd, runtimeErrors, stepIndex)\n if (costUsd !== undefined && Number.isFinite(costUsd) && costUsd > 0) {\n spentCostUsd += costUsd\n await recordCostBudget(\n emitter,\n budget,\n spentCostUsd,\n stepHandle,\n runtimeErrors,\n stepIndex,\n )\n }\n actionOutcome = {\n ok: true,\n result,\n ...(costUsd !== undefined ? { costUsd } : {}),\n durationMs: Date.now() - actionStarted,\n }\n } catch (err) {\n runtimeErrors.push(runtimeError('act', stepIndex, err))\n actionOutcome = {\n ok: false,\n error: runtimeErrors[runtimeErrors.length - 1]!.message,\n durationMs: Date.now() - actionStarted,\n }\n if (actionFailure === 'stop') {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed'),\n )\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: actionOutcome.error ?? 'action failed',\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n }\n\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n runtimeErrors.push(runtimeError('observe', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: beforeState,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: beforeState,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(\n emitter,\n evals,\n `step-${stepIndex}`,\n runtimeErrors,\n stepIndex,\n stepHandle?.span.spanId,\n )\n } catch (err) {\n runtimeErrors.push(runtimeError('validate', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n const scoreAfter = averageScore(evals)\n const stateFingerprint = fingerprintState(state, config.stopPolicies)\n const noProgressSignal = progressDetector.observe({ stateFingerprint, score: scoreAfter })\n const noProgressStreak = progressDetector.streak\n\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n if (actionOutcome.ok) {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.end({\n attributes: {\n actionCostUsd: actionOutcome.costUsd ?? null,\n spentCostUsd,\n scoreBefore: scoreBefore ?? null,\n scoreAfter: scoreAfter ?? null,\n noProgressStreak,\n },\n }),\n )\n } else {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed', {\n attributes: {\n spentCostUsd,\n noProgressStreak,\n },\n }),\n )\n }\n await runOnStep(config.onStep, step, runtimeErrors)\n\n if (noProgressSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: noProgressSignal.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const postStepBudgetStop = budgetStopDecision(budget, spentCostUsd)\n if (postStepBudgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: postStepBudgetStop.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const postStepCtx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex + 1,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let postStepStop: StopDecision\n try {\n postStepStop = config.shouldStop\n ? await config.shouldStop(postStepCtx)\n : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex + 1, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (postStepStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: postStepStop.pass,\n completed: true,\n reason: postStepStop.reason,\n score: postStepStop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: postStepStop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n }\n\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: `budget exhausted: maxSteps=${budget.maxSteps}`,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n } catch (err) {\n runtimeErrors.push(runtimeError('act', history.length, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n } finally {\n if (wallTimer) clearTimeout(wallTimer)\n if (config.signal) config.signal.removeEventListener('abort', upstreamAbort)\n }\n}\n\nexport function stopOnNoProgress<TState, TAction>(\n maxNoProgressSteps: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxNoProgressSteps'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxNoProgressSteps }\n}\n\nexport function stopOnRepeatedAction<TState, TAction>(\n maxRepeatedActions: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxRepeatedActions'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxRepeatedActions }\n}\n\nexport function objectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: true }\n}\n\nexport function subjectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: false }\n}\n\nfunction normalizeBudget(input: Partial<ControlBudget> | undefined): ControlBudget {\n const raw = { ...DEFAULT_BUDGET, ...input } as Record<string, unknown>\n if (!Number.isInteger(raw.maxSteps) || (raw.maxSteps as number) < 1) {\n throw new RangeError(\n `ControlRuntime budget.maxSteps must be an integer >= 1, got ${String(raw.maxSteps)}`,\n )\n }\n const budget: ControlBudget = { maxSteps: raw.maxSteps as number }\n if (raw.maxWallMs !== undefined) {\n if (\n typeof raw.maxWallMs !== 'number' ||\n !Number.isFinite(raw.maxWallMs) ||\n raw.maxWallMs <= 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxWallMs must be a positive finite number, got ${String(raw.maxWallMs)}`,\n )\n }\n budget.maxWallMs = raw.maxWallMs\n }\n if (raw.maxCostUsd !== undefined) {\n if (\n typeof raw.maxCostUsd !== 'number' ||\n !Number.isFinite(raw.maxCostUsd) ||\n raw.maxCostUsd < 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxCostUsd must be a nonnegative finite number, got ${String(raw.maxCostUsd)}`,\n )\n }\n budget.maxCostUsd = raw.maxCostUsd\n }\n return budget\n}\n\nfunction normalizeActionCostUsd(\n costUsd: number | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): number | undefined {\n if (costUsd === undefined) return undefined\n if (!Number.isFinite(costUsd) || costUsd < 0) {\n runtimeErrors.push(\n runtimeError('act', stepIndex, new Error(`invalid action costUsd: ${String(costUsd)}`)),\n )\n return undefined\n }\n return costUsd\n}\n\nexport function allCriticalPassed(evals: ControlEvalResult[]): boolean {\n return evals.every(\n (result) => result.passed || (result.severity !== 'critical' && result.severity !== 'error'),\n )\n}\n\nfunction makeContext<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n intent: string,\n state: TState,\n evals: TEval[],\n history: ControlStep<TState, TAction, TActionResult, TEval>[],\n budget: ControlBudget,\n stepIndex: number,\n started: number,\n spentCostUsd: number,\n abortSignal: AbortSignal,\n emitter?: TraceEmitter,\n): ControlContext<TState, TAction, TActionResult, TEval> {\n return {\n intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n wallMs: Date.now() - started,\n spentCostUsd,\n remainingCostUsd:\n budget.maxCostUsd === undefined ? undefined : Math.max(0, budget.maxCostUsd - spentCostUsd),\n abortSignal,\n emitter,\n }\n}\n\nfunction defaultStopDecision(evals: ControlEvalResult[]): StopDecision {\n if (!evals.length) return { stop: false, pass: false, reason: 'no evals yet' }\n const pass = allCriticalPassed(evals)\n return pass\n ? { stop: true, pass: true, reason: 'all critical evals passed', score: averageScore(evals) }\n : {\n stop: false,\n pass: false,\n reason: 'critical evals still failing',\n score: averageScore(evals),\n }\n}\n\nfunction averageScore(evals: ControlEvalResult[]): number | undefined {\n const scored = evals\n .map((result) => result.score)\n .filter((score): score is number => typeof score === 'number')\n if (!scored.length) return undefined\n return Math.round((scored.reduce((sum, score) => sum + score, 0) / scored.length) * 1000) / 1000\n}\n\nfunction budgetStopDecision(\n budget: ControlBudget,\n spentCostUsd: number,\n): { stop: boolean; reason: string } {\n if (budget.maxCostUsd !== undefined && spentCostUsd >= budget.maxCostUsd) {\n return {\n stop: true,\n reason: `budget exhausted: maxCostUsd=${budget.maxCostUsd}`,\n }\n }\n return { stop: false, reason: '' }\n}\n\nasync function recordCostBudget(\n emitter: TraceEmitter | undefined,\n budget: ControlBudget,\n spentCostUsd: number,\n handle: SpanHandle | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): Promise<void> {\n if (!emitter || budget.maxCostUsd === undefined) return\n const maxCostUsd = budget.maxCostUsd\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordBudget({\n dimension: 'usd',\n limit: maxCostUsd,\n consumed: spentCostUsd,\n remaining: Math.max(0, maxCostUsd - spentCostUsd),\n breached: spentCostUsd >= maxCostUsd,\n spanId: handle?.span.spanId,\n }),\n )\n}\n\nasync function recordEvalSpans(\n emitter: TraceEmitter | undefined,\n evals: ControlEvalResult[],\n phase: string,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n targetSpanId?: string,\n): Promise<void> {\n if (!emitter) return\n for (const result of evals) {\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordJudge({\n judgeId: result.objective ? 'objective-validator' : 'subjective-judge',\n targetSpanId: targetSpanId ?? emitter.runId,\n name: `control-eval/${result.id}`,\n dimension: result.id,\n score: typeof result.score === 'number' ? result.score : result.passed ? 1 : 0,\n rationale: result.detail,\n evidence: result.evidence,\n attributes: {\n phase,\n passed: result.passed,\n severity: result.severity,\n objective: result.objective,\n },\n }),\n )\n }\n}\n\nasync function runOnStep<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n onStep: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>['onStep'] | undefined,\n step: ControlStep<TState, TAction, TActionResult, TEval>,\n runtimeErrors: ControlRuntimeError[],\n): Promise<void> {\n if (!onStep) return\n try {\n await onStep(step)\n } catch (err) {\n runtimeErrors.push(runtimeError('on-step', step.index, err))\n }\n}\n\nasync function runTrace<T>(\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n write: () => Promise<T | undefined> | T | undefined,\n): Promise<T | undefined> {\n try {\n return await write()\n } catch (err) {\n runtimeErrors.push(runtimeError('trace', stepIndex, err))\n return undefined\n }\n}\n\nfunction fingerprintState<TState, TAction>(\n state: TState,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.stateFingerprint) return policies.stateFingerprint(state)\n return stableFingerprint(state)\n}\n\nfunction fingerprintAction<TState, TAction>(\n action: TAction,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.actionFingerprint) return policies.actionFingerprint(action)\n return stableFingerprint(action)\n}\n\n/** Default state/action fingerprint: the value itself for a string, `String(value)`\n * for a number, boolean, null or undefined, and RFC 8785 canonical JSON for\n * everything else. A value with no canonical JSON form (an `undefined`-valued\n * field, a non-finite number, a class instance) throws: two states that differ\n * in such a field must not fingerprint alike, and a caller with such state\n * supplies `stopPolicies.stateFingerprint` / `actionFingerprint`. */\nfunction stableFingerprint(value: unknown): string {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || value == null) return String(value)\n return canonicalString(value)\n}\n\nfunction abortReason(signal: AbortSignal): string {\n const reason = signal.reason\n if (reason instanceof Error) return reason.message\n return reason ? String(reason) : 'aborted'\n}\n\nfunction runtimeError(\n phase: ControlRuntimeError['phase'],\n stepIndex: number,\n err: unknown,\n): ControlRuntimeError {\n const message = err instanceof Error ? err.message : String(err)\n return { phase, stepIndex, message }\n}\n\nasync function finish<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n emitter: TraceEmitter | undefined,\n result: ControlRunResult<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n await runTrace(result.runtimeErrors, result.steps.length, () =>\n emitter?.endRun({\n pass: result.pass,\n score: result.score ?? averageScore(result.finalEvals),\n failureClass: result.failureClass,\n notes: result.reason,\n }),\n )\n return result\n}\n","/**\n * Walk a personas directory and return every file matching the convention\n * `NN-slug.{yaml,yml,json,md}`. Sorted by filename so the numeric prefix\n * gives stable persona ordering for reproducibility. Consumers filter\n * through `include` / `exclude`.\n */\n\nimport { promises as fs } from 'node:fs'\nimport { basename, extname, join } from 'node:path'\n\nexport interface DiscoverPersonasOptions {\n /**\n * Regex applied to filenames. Files that don't match are skipped.\n * Default: `^[0-9]{2}-.+\\.(yaml|yml|json|md)$`.\n */\n pattern?: RegExp\n /**\n * Filenames (or basenames) to skip. Use this to exclude WIP / archived\n * personas without removing the file.\n */\n exclude?: readonly string[]\n /**\n * If set, return only personas whose basename contains one of these\n * substrings (post-pattern filter).\n */\n include?: readonly string[]\n /** Recurse into subdirectories. Default false. */\n recursive?: boolean\n}\n\nexport interface DiscoveredPersona {\n /** Absolute file path. */\n path: string\n /** Filename without directory. */\n filename: string\n /** Filename without extension — the conventional persona id. */\n id: string\n}\n\nconst DEFAULT_PATTERN = /^\\d{2}-.+\\.(yaml|yml|json|md)$/\n\nexport async function discoverPersonas(\n dir: string,\n opts: DiscoverPersonasOptions = {},\n): Promise<DiscoveredPersona[]> {\n const pattern = opts.pattern ?? DEFAULT_PATTERN\n const exclude = new Set(opts.exclude ?? [])\n const include = opts.include\n\n async function walk(d: string): Promise<DiscoveredPersona[]> {\n let entries: Array<{ name: string; isDir: boolean }>\n try {\n const raw = await fs.readdir(d, { withFileTypes: true })\n entries = raw.map((e) => ({ name: e.name, isDir: e.isDirectory() }))\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code === 'ENOENT') return []\n throw err\n }\n const out: DiscoveredPersona[] = []\n for (const entry of entries) {\n const full = join(d, entry.name)\n if (entry.isDir) {\n if (opts.recursive) out.push(...(await walk(full)))\n continue\n }\n if (!pattern.test(entry.name)) continue\n if (exclude.has(entry.name) || exclude.has(basename(entry.name, extname(entry.name))))\n continue\n if (include && include.length > 0) {\n const id = basename(entry.name, extname(entry.name))\n const matched = include.some((needle) => entry.name.includes(needle) || id.includes(needle))\n if (!matched) continue\n }\n out.push({\n path: full,\n filename: entry.name,\n id: basename(entry.name, extname(entry.name)),\n })\n }\n return out\n }\n\n const results = await walk(dir)\n results.sort((a, b) => a.filename.localeCompare(b.filename))\n return results\n}\n","/**\n * Propose / Verify / Review — the core multi-shot primitive.\n *\n * shot N: propose(state, priorReview) → new state\n * verify(state) → pass/fail, optional layers\n * review(state, verification, memory) → observations + next-shot\n * instruction + shouldContinue\n * memory.append(entry)\n *\n * Roles are strictly separated:\n *\n * - The WORKER is whatever the caller wraps in `propose`. It is\n * stateful — caller owns its resume/session mechanism.\n * - The VERIFIER grades the state. It produces the ground truth.\n * The reviewer cannot overturn or downgrade a verification layer.\n * - The REVIEWER is stateless per call. Its continuity is the\n * `ReviewMemoryStore` — durable JSONL by default, or any store\n * implementing the interface. It reads memory + trace summary +\n * verification and directs the NEXT proposer shot.\n *\n * This shape is load-bearing. The reviewer never grades; the verifier\n * never directs. Two processes, two prompts, two concerns — which is\n * what keeps the loop from confirmation-biasing itself into \"all\n * passed\" when it didn't.\n *\n * Short-circuits and soft-fails are both first-class:\n * - verify.pass === true → reviewer LLM call is skipped, memory\n * records a success entry, loop exits.\n * - review throws → the shot still counts; the loop uses the\n * last-known instruction (or `fallbackInstruction`) for the next\n * propose call. A transient reviewer failure must NEVER abort a\n * valid arc.\n *\n * Composable: `propose` itself can be another `runProposeReview` call.\n * That's the dogfooding path — a harness built on this primitive is in\n * turn evaluable by it.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface Verification {\n pass: boolean\n score?: number\n failingLayers?: string[]\n details?: unknown\n}\n\nexport interface Review {\n observations: string\n diagnosis: string\n nextShotInstruction: string\n shouldContinue: boolean\n confidence: number\n}\n\nexport interface ReviewMemoryEntry extends Review {\n shot: number\n timestamp: number\n verification: {\n pass: boolean\n score?: number\n failingLayers?: string[]\n }\n}\n\nexport interface ProposeInput<State> {\n shot: number\n goal: string\n state: State\n priorReview: Review | null\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport interface ProposeOutput<State, Summary = unknown> {\n state: State\n traceSummary?: Summary\n}\n\nexport interface ReviewInput<State, Summary = unknown> {\n shot: number\n goal: string\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n memory: ReviewMemoryEntry[]\n}\n\nexport type ProposeFn<State, Summary = unknown> = (\n input: ProposeInput<State>,\n) => Promise<ProposeOutput<State, Summary>>\n\nexport type VerifyFn<State> = (state: State) => Promise<Verification>\n\nexport type ReviewFn<State, Summary = unknown> = (\n input: ReviewInput<State, Summary>,\n) => Promise<Review>\n\nexport interface ReviewMemoryStore {\n load(): Promise<ReviewMemoryEntry[]>\n append(entry: ReviewMemoryEntry): Promise<void>\n}\n\nexport interface ProposeReviewConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n /** Hard shot cap. Default 10. */\n maxShots?: number\n /** Wall-clock cap in ms. Default 10 min. */\n maxWallMs?: number\n /**\n * If the reviewer returns confidence ≤ floor on `confidenceFloorWindow`\n * consecutive shots, terminate early. Default floor 0.3, window 2.\n * Set window to 0 or floor to <0 to disable.\n */\n confidenceFloor?: number\n confidenceFloorWindow?: number\n /** Defaults to an in-memory store if omitted. */\n memory?: ReviewMemoryStore\n /** If provided, emit a Run + per-shot spans. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n /**\n * Used when the reviewer soft-fails on shot 1 (no prior instruction to\n * fall back to). Default is a generic \"inspect failures and fix\".\n */\n fallbackInstruction?: string\n}\n\nexport interface ProposeReviewShot<State, Summary = unknown> {\n shot: number\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n review: Review\n reviewAvailable: boolean\n reviewError?: string\n durationMs: number\n}\n\nexport interface ProposeReviewReport<State, Summary = unknown> {\n runId: string | null\n completed: boolean\n shots: ProposeReviewShot<State, Summary>[]\n finalState: State\n finalVerification: Verification\n failureClass?: FailureClass\n wallMs: number\n score: number\n}\n\n// ── Memory stores ────────────────────────────────────────────────────\n\nexport function inMemoryReviewStore(initial: ReviewMemoryEntry[] = []): ReviewMemoryStore {\n const entries: ReviewMemoryEntry[] = [...initial]\n return {\n async load() {\n return [...entries]\n },\n async append(entry) {\n entries.push(entry)\n },\n }\n}\n\nexport function jsonlReviewStore(path: string): ReviewMemoryStore {\n return {\n async load() {\n if (!existsSync(path)) return []\n const raw = readFileSync(path, 'utf8')\n const out: ReviewMemoryEntry[] = []\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n out.push(JSON.parse(trimmed) as ReviewMemoryEntry)\n } catch {\n // A corrupt line is an observability problem, not a correctness\n // one — skip it rather than aborting the loop.\n }\n }\n return out\n },\n async append(entry) {\n mkdirSync(dirname(path), { recursive: true })\n appendFileSync(path, `${JSON.stringify(entry)}\\n`)\n },\n }\n}\n\n// ── Core loop ────────────────────────────────────────────────────────\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReview<State, Summary = unknown>(\n config: ProposeReviewConfig<State, Summary>,\n): Promise<ProposeReviewReport<State, Summary>> {\n const maxShots = config.maxShots ?? 10\n const maxWallMs = config.maxWallMs ?? 10 * 60 * 1000\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n\n const emitter = config.store ? new TraceEmitter(config.store) : null\n if (emitter) {\n await emitter.startRun({\n scenarioId: config.scenarioId ?? 'propose-review',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n goal: config.goal.slice(0, 120),\n maxShots: String(maxShots),\n },\n })\n }\n\n const abort = new AbortController()\n const wallStart = Date.now()\n const wallTimer = setTimeout(\n () => abort.abort(new Error('propose-review wall timeout')),\n maxWallMs,\n )\n\n const shots: ProposeReviewShot<State, Summary>[] = []\n let state = config.initialState\n let priorReview: Review | null = null\n let lastVerification: Verification = { pass: false }\n let failureClass: FailureClass | undefined\n let completed = false\n let lowConfidenceStreak = 0\n\n try {\n for (let shot = 1; shot <= maxShots; shot++) {\n if (abort.signal.aborted) {\n failureClass = 'timeout'\n break\n }\n\n const shotStart = Date.now()\n const shotHandle = emitter ? await emitter.span({ kind: 'tool', name: `shot-${shot}` }) : null\n\n // 1. Propose.\n let proposeOut: ProposeOutput<State, Summary>\n try {\n proposeOut = await config.propose({\n shot,\n goal: config.goal,\n state,\n priorReview,\n abortSignal: abort.signal,\n emitter: emitter ?? undefined,\n })\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n state = proposeOut.state\n const traceSummary = proposeOut.traceSummary\n\n // 2. Verify.\n let verification: Verification\n try {\n verification = await config.verify(state)\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n lastVerification = verification\n\n // 3. Review — short-circuit on pass; soft-fail on throw.\n const memorySnapshot = await memory.load()\n const verificationDigest = {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers ?? [],\n }\n\n let review: Review\n let reviewAvailable = true\n let reviewError: string | undefined\n\n if (verification.pass) {\n review = {\n observations: 'verification passed — skipping reviewer LLM call',\n diagnosis: 'no failures to diagnose',\n nextShotInstruction: '(done)',\n shouldContinue: false,\n confidence: 1,\n }\n } else {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state,\n verification,\n traceSummary,\n memory: memorySnapshot,\n })\n review = coerceReview(review)\n } catch (err) {\n reviewAvailable = false\n reviewError = err instanceof Error ? err.message : String(err)\n const lastInstruction =\n memorySnapshot.length > 0\n ? memorySnapshot[memorySnapshot.length - 1]!.nextShotInstruction\n : fallbackInstruction\n review = {\n observations: '(reviewer unavailable — using last-known instruction)',\n diagnosis: reviewError,\n nextShotInstruction: lastInstruction,\n shouldContinue: true,\n confidence: 0.3,\n }\n }\n }\n\n const entry: ReviewMemoryEntry = {\n shot,\n timestamp: Date.now(),\n ...review,\n verification: verificationDigest,\n }\n await memory.append(entry)\n\n const shotRecord: ProposeReviewShot<State, Summary> = {\n shot,\n state,\n verification,\n traceSummary,\n review,\n reviewAvailable,\n reviewError,\n durationMs: Date.now() - shotStart,\n }\n shots.push(shotRecord)\n\n await shotHandle?.end({\n attributes: {\n verificationPass: verification.pass,\n verificationScore: verification.score ?? null,\n reviewShouldContinue: review.shouldContinue,\n reviewConfidence: review.confidence,\n reviewAvailable,\n },\n } as Partial<SpanHandle['span']>)\n\n // 4. Exit rules.\n if (verification.pass) {\n completed = true\n break\n }\n if (!review.shouldContinue) {\n break\n }\n if (confidenceFloorWindow > 0 && review.confidence <= confidenceFloor) {\n lowConfidenceStreak += 1\n if (lowConfidenceStreak >= confidenceFloorWindow) break\n } else {\n lowConfidenceStreak = 0\n }\n\n priorReview = review\n }\n\n if (!completed && !failureClass) {\n failureClass = shots.length >= maxShots ? 'budget_exceeded' : 'unknown'\n }\n } finally {\n clearTimeout(wallTimer)\n }\n\n const score = lastVerification.pass\n ? 1\n : typeof lastVerification.score === 'number'\n ? lastVerification.score\n : 0\n\n if (emitter) {\n await emitter.endRun({\n pass: completed,\n score,\n failureClass,\n notes: `${shots.length} shot(s); final pass=${lastVerification.pass}`,\n })\n }\n\n return {\n runId: emitter?.runId ?? null,\n completed,\n shots,\n finalState: state,\n finalVerification: lastVerification,\n failureClass,\n wallMs: Date.now() - wallStart,\n score,\n }\n}\n\n// ── Reviewer helper (LLM-backed) ─────────────────────────────────────\n\nexport type LlmJsonCall = (req: { system: string; user: string }) => Promise<unknown>\n\nexport interface LlmReviewerConfig<State, Summary = unknown> {\n callJson: LlmJsonCall\n renderState?: (state: State) => string\n renderTraceSummary?: (summary: Summary | undefined) => string\n /** Appended to the default system prompt. */\n systemPromptAddendum?: string\n}\n\nconst REVIEWER_SYSTEM_PROMPT = `You are a senior reviewer directing a multi-shot build loop.\nYou do NOT grade — the verifier already did. Your job is to direct the worker's next shot.\nYou are blind to the worker's inner monologue. You see what it DID, not what it thought.\nReturn STRICT JSON matching the schema. No prose outside the JSON.`\n\nexport function createLlmReviewer<State, Summary = unknown>(\n cfg: LlmReviewerConfig<State, Summary>,\n): ReviewFn<State, Summary> {\n const renderState = cfg.renderState ?? ((s: State) => safeJson(s))\n const renderTraceSummary =\n cfg.renderTraceSummary ??\n ((s: Summary | undefined) => (s === undefined ? '(none)' : safeJson(s)))\n const system = cfg.systemPromptAddendum\n ? `${REVIEWER_SYSTEM_PROMPT}\\n\\n${cfg.systemPromptAddendum}`\n : REVIEWER_SYSTEM_PROMPT\n\n return async (input) => {\n const memoryBlock =\n input.memory.length === 0\n ? '(no prior shots — this is shot 1)'\n : input.memory\n .map((m) =>\n [\n `shot ${m.shot} — verification.pass=${m.verification.pass}` +\n (typeof m.verification.score === 'number'\n ? ` score=${m.verification.score.toFixed(2)}`\n : '') +\n ` confidence=${m.confidence.toFixed(2)} failing=[${(m.verification.failingLayers ?? []).join(',')}]`,\n ` observations: ${m.observations.slice(0, 400)}`,\n ` diagnosis: ${m.diagnosis.slice(0, 400)}`,\n ` instruction given: ${m.nextShotInstruction.slice(0, 400)}`,\n ].join('\\n'),\n )\n .join('\\n\\n')\n\n const user = [\n `=== GOAL ===`,\n input.goal,\n ``,\n `=== SHOT NUMBER ===`,\n String(input.shot),\n ``,\n `=== CURRENT STATE ===`,\n renderState(input.state),\n ``,\n `=== TRACE SUMMARY ===`,\n renderTraceSummary(input.traceSummary),\n ``,\n `=== VERIFICATION ===`,\n summarizeVerification(input.verification),\n ``,\n `=== REVIEWER MEMORY (prior shots) ===`,\n memoryBlock,\n ``,\n `=== YOUR TASK ===`,\n `Return STRICT JSON:`,\n `{`,\n ` \"observations\": string (20..2000 chars, first-person worker behavior — quote counts, errors, loops)`,\n ` \"diagnosis\": string (20..1500 chars, root cause, NOT a restatement of verification)`,\n ` \"nextShotInstruction\": string (40..3000 chars, concrete directive to the worker)`,\n ` \"shouldContinue\": boolean (false if verification.pass, or if thrashing, or unachievable)`,\n ` \"confidence\": number in [0,1]`,\n `}`,\n ].join('\\n')\n\n const raw = await cfg.callJson({ system, user })\n return coerceReview(raw as Partial<Review>)\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction coerceReview(raw: Partial<Review> | null | undefined): Review {\n if (!raw || typeof raw !== 'object') {\n throw new Error('reviewer returned non-object')\n }\n const observations = typeof raw.observations === 'string' ? raw.observations : ''\n const diagnosis = typeof raw.diagnosis === 'string' ? raw.diagnosis : ''\n const nextShotInstruction =\n typeof raw.nextShotInstruction === 'string' ? raw.nextShotInstruction : ''\n if (!observations || !diagnosis || !nextShotInstruction) {\n throw new Error('reviewer missing required string fields')\n }\n if (typeof raw.shouldContinue !== 'boolean') {\n throw new Error('reviewer missing shouldContinue boolean')\n }\n const confidenceRaw = Number(raw.confidence)\n if (!Number.isFinite(confidenceRaw)) {\n throw new Error('reviewer confidence not finite')\n }\n return {\n observations,\n diagnosis,\n nextShotInstruction,\n shouldContinue: raw.shouldContinue,\n confidence: Math.max(0, Math.min(1, confidenceRaw)),\n }\n}\n\nfunction summarizeVerification(v: Verification): string {\n const header =\n `pass=${v.pass}` +\n (typeof v.score === 'number' ? ` score=${v.score.toFixed(3)}` : '') +\n (v.failingLayers && v.failingLayers.length > 0\n ? ` failing=[${v.failingLayers.join(', ')}]`\n : '')\n const details = v.details === undefined ? '' : `\\n${safeJson(v.details).slice(0, 1500)}`\n return header + details\n}\n\nfunction safeJson(x: unknown): string {\n try {\n return JSON.stringify(x, null, 2)\n } catch {\n return String(x)\n }\n}\n","import {\n type ControlRunResult,\n type ControlRuntimeConfig,\n objectiveEval,\n runAgentControlLoop,\n} from './control-runtime'\nimport {\n inMemoryReviewStore,\n type ProposeFn,\n type ProposeOutput,\n type Review,\n type ReviewFn,\n type ReviewMemoryEntry,\n type ReviewMemoryStore,\n type Verification,\n type VerifyFn,\n} from './propose-review'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport interface ProposeReviewControlState<State, Summary = unknown> {\n shot: number\n state: State\n priorReview: Review | null\n verification: Verification\n traceSummary?: Summary\n memory: ReviewMemoryEntry[]\n completed: boolean\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlAction {\n type: 'propose-review-shot'\n shot: number\n}\n\nexport interface ProposeReviewControlResult<State, Summary = unknown> {\n state: State\n verification: Verification\n traceSummary?: Summary\n review: Review | null\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n maxShots?: number\n maxWallMs?: number\n memory?: ReviewMemoryStore\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n fallbackInstruction?: string\n confidenceFloor?: number\n confidenceFloorWindow?: number\n failureClassFromVerification?: (verification: Verification) => FailureClass | undefined\n actionFailure?: ControlRuntimeConfig<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >['actionFailure']\n}\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReviewAsControlLoop<State, Summary = unknown>(\n config: ProposeReviewControlConfig<State, Summary>,\n): Promise<\n ControlRunResult<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >\n> {\n const maxShots = config.maxShots ?? 10\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n const failureClassFromVerification =\n config.failureClassFromVerification ?? controlFailureClassFromVerification\n let lowConfidenceStreak = 0\n\n let current: ProposeReviewControlState<State, Summary> = {\n shot: 0,\n state: config.initialState,\n priorReview: null,\n verification: { pass: false },\n memory: await memory.load(),\n completed: false,\n reviewAvailable: false,\n }\n\n return runAgentControlLoop({\n intent: config.goal,\n budget: { maxSteps: maxShots, maxWallMs: config.maxWallMs },\n store: config.store,\n scenarioId: config.scenarioId ?? 'propose-review-control',\n projectId: config.projectId,\n variantId: config.variantId,\n actionFailure: config.actionFailure ?? 'stop',\n observe: () => current,\n validate: ({ state }) => [\n objectiveEval({\n id: 'verification',\n passed: state.verification.pass,\n score: state.verification.score,\n severity: 'critical',\n detail: state.verification.pass\n ? 'verification passed'\n : `verification failed${state.verification.failingLayers?.length ? `: ${state.verification.failingLayers.join(', ')}` : ''}`,\n }),\n ],\n shouldStop: ({ state }) => {\n if (state.verification.pass) {\n return {\n stop: true,\n pass: true,\n reason: 'verification passed',\n score: state.verification.score,\n }\n }\n if (state.completed) {\n return {\n stop: true,\n pass: false,\n reason: 'reviewer stopped continuation',\n score: state.verification.score,\n failureClass: failureClassFromVerification(state.verification),\n }\n }\n return {\n stop: false,\n pass: false,\n reason: 'verification still failing',\n score: state.verification.score,\n }\n },\n decide: ({ state }) => ({\n type: 'continue',\n action: { type: 'propose-review-shot', shot: state.shot + 1 },\n reason: state.priorReview?.nextShotInstruction ?? fallbackInstruction,\n }),\n act: async (action, ctx) => {\n const shot = action.shot\n const proposeOut: ProposeOutput<State, Summary> = await config.propose({\n shot,\n goal: config.goal,\n state: current.state,\n priorReview: current.priorReview,\n abortSignal: ctx.abortSignal,\n emitter: ctx.emitter,\n })\n\n const nextState = proposeOut.state\n const verification = await config.verify(nextState)\n let review: Review | null = null\n let reviewAvailable = false\n let reviewError: string | undefined\n let shouldContinue = !verification.pass\n\n if (!verification.pass) {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n })\n reviewAvailable = true\n shouldContinue = review.shouldContinue\n lowConfidenceStreak = review.confidence <= confidenceFloor ? lowConfidenceStreak + 1 : 0\n if (confidenceFloorWindow > 0 && lowConfidenceStreak >= confidenceFloorWindow)\n shouldContinue = false\n } catch (err) {\n reviewError = err instanceof Error ? err.message : String(err)\n review = current.priorReview ?? {\n observations: 'Reviewer unavailable.',\n diagnosis: reviewError,\n nextShotInstruction: fallbackInstruction,\n shouldContinue: true,\n confidence: 0,\n }\n shouldContinue = true\n }\n } else {\n review = {\n observations: 'Verification passed.',\n diagnosis: 'No further revision needed.',\n nextShotInstruction: '',\n shouldContinue: false,\n confidence: 1,\n }\n }\n\n const entry: ReviewMemoryEntry = {\n ...(review ?? {\n observations: 'No review.',\n diagnosis: '',\n nextShotInstruction: fallbackInstruction,\n shouldContinue,\n confidence: 0,\n }),\n shot,\n timestamp: Date.now(),\n verification: {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers,\n },\n }\n await memory.append(entry)\n\n current = {\n shot,\n state: nextState,\n priorReview: review,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n completed: verification.pass || !shouldContinue,\n reviewAvailable,\n reviewError,\n }\n\n return {\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n review,\n reviewAvailable,\n reviewError,\n }\n },\n })\n}\n\nexport function controlFailureClassFromVerification(\n verification: Verification,\n): FailureClass | undefined {\n if (verification.pass) return undefined\n return verification.failingLayers?.length ? 'instruction_following' : 'unknown'\n}\n","// The realness-oracle firewall (agent-runtime docs/learning-flywheel.md, \"The steer is f(trace)\" — the doctrine lives in the runtime repo).\n//\n// A realness/authenticity signal has TWO legitimate roles that must stay\n// separated by a firewall:\n// (a) anchor judge J — write-only: scores the chosen output, gates promotion,\n// NEVER seen by the worker/optimizer mid-run (else the loop games it).\n// (b) steer f(trace) — an analyst observes the agent's OWN behavior in the\n// trace (\"imported a stub\", \"used a non-crypto PRNG where encryption was\n// required\") and steers the next attempt. Legitimate, because it is derived\n// from OBSERVABLE BEHAVIOR, not from J's held-out verdict.\n//\n// The correct discriminator is PROVENANCE, not evidence presence. A judge verdict\n// lifted into a finding (createJudgeAdapter → liftJudgeScore) is a verdict even\n// when it cites an artifact; an evidence-less trace-analyst bullet is an\n// observation even though it cites nothing. So the firewall keys on\n// `AnalystFinding.derived_from_judge` (set at the judge lift site), NOT on whether\n// evidence_refs is populated. The instant a verdict steers the next attempt it is\n// a back-channel for J and the loop Goodharts realness exactly as it would\n// Goodhart pass-rate.\n\nimport type { AnalystFinding, EvidenceRef } from './types'\n\n/** Evidence grounded in the agent's OWN execution: OTLP trace elements\n * (`span`/`event`) or the artifact it produced (`artifact`). */\nconst OBSERVABLE_KINDS: ReadonlySet<EvidenceRef['kind']> = new Set<EvidenceRef['kind']>([\n 'span',\n 'event',\n 'artifact',\n])\n\n/** DESCRIPTIVE predicate: does the finding cite at least one observable\n * (span/event/artifact) evidence ref. Useful for ranking evidence quality or\n * rendering — it is NOT the steer gate. Evidence presence is the WRONG\n * discriminator for steering: a legitimate trace-analyst observation may cite\n * nothing (it would be wrongly rejected), and a judge verdict may cite an\n * artifact (it would be wrongly admitted). Use `assertNoJudgeVerdict` to gate\n * steering; use this only where \"is this grounded in observable evidence\" is the\n * literal question. */\nexport function isTraceObservable(finding: AnalystFinding): boolean {\n return finding.evidence_refs.some((ref) => OBSERVABLE_KINDS.has(ref.kind))\n}\n\n/** True iff the finding is a JUDGE VERDICT (an acceptance score lifted into a\n * finding), identified by provenance set at the lift site — independent of\n * whatever evidence it cites. */\nexport function isJudgeVerdict(finding: AnalystFinding): boolean {\n return finding.derived_from_judge === true\n}\n\n/**\n * THE steer firewall. Fail-loud guard for any path that admits analyst findings\n * as STEERING input (the `f(trace)` role): rejects — naming the offenders — any\n * finding whose provenance is a judge verdict, rather than let `J` leak into the\n * loop. Returns the findings unchanged for chaining.\n *\n * Call this at the chokepoint where a detector that ALSO scores/gates has its\n * findings turned into a steer (the judge-and-steer dual-role case). It keys on\n * provenance, so it correctly admits evidence-less trace-analyst observations and\n * correctly rejects an artifact-citing judge verdict — the cases an evidence\n * check gets backwards.\n *\n * It is necessary, not sufficient: it stops PROVENANCE-tagged verdicts. A judge\n * whose output is laundered through a hand-built finding with no provenance flag\n * is out of its reach — provenance must be honestly set at every judge→finding\n * lift (today: createJudgeAdapter). That is why the integrity rule lives at the\n * lift site, and why ProposeContext.judgeScores?: never is the complementary\n * compile-time tripwire on the obvious direct channel.\n */\nexport function assertNoJudgeVerdict(\n findings: ReadonlyArray<AnalystFinding>,\n context = 'steer',\n): ReadonlyArray<AnalystFinding> {\n const leaks = findings.filter(isJudgeVerdict)\n if (leaks.length > 0) {\n throw new Error(\n `${context}: a judge verdict cannot be admitted as steering input — that is the ` +\n `held-out judge leaking into the loop. Offending judge-derived findings: [${leaks\n .map((f) => f.finding_id)\n .join(', ')}]. Steering consumes observations of behavior, never acceptance verdicts.`,\n )\n }\n return findings\n}\n","import type { AgentProfileCell, AgentProfileJson } from '../agent-profile-cell'\nimport { validateAgentProfileCell } from '../agent-profile-cell'\nimport { ValidationError } from '../errors'\nimport { hashCanonical } from '../ledger-core/canonical'\nimport { type FindingSubject, parseFindingSubject } from './finding-subject'\nimport { assertNoJudgeVerdict } from './steer-firewall'\nimport type { AnalystFinding, EvidenceRef } from './types'\n\nexport type PolicyEditSchemaVersion = 'policy-edit/v1'\n\nexport const POLICY_EDIT_AXES = [\n 'carrier',\n 'representation',\n 'budget',\n 'sampling',\n 'output_contract',\n 'tool_contract',\n 'routing',\n 'memory',\n 'agent_profile',\n 'deployment_target',\n] as const\n\nexport type PolicyEditAxis = (typeof POLICY_EDIT_AXES)[number]\n\nexport const POLICY_EDIT_TARGET_SURFACES = [\n 'prompt',\n 'tool-contract',\n 'runtime-config',\n 'memory',\n 'agent-profile',\n 'code',\n 'deployment',\n] as const\n\nexport type PolicyEditTargetSurface = (typeof POLICY_EDIT_TARGET_SURFACES)[number]\nexport type PolicyEditRisk = 'low' | 'medium' | 'high' | 'unknown'\nexport type PolicyEditGainDirection = 'increase' | 'decrease'\nexport type PolicyEditGainUnit = 'absolute' | 'relative' | 'percent' | 'score'\n\nexport interface PolicyEditTarget {\n surface: PolicyEditTargetSurface\n /** Stable path inside the target surface, for example `system-prompt:tools`\n * or `budget.maxTurns`. */\n path?: string\n /** Optional canonical deployment identity. Store the existing cell, not a\n * local profile shape. */\n agentProfileCell?: AgentProfileCell\n /** Human label when the path is not enough for a readable audit trail. */\n label?: string\n}\n\nexport type PolicyEditChange =\n | {\n kind: 'text'\n mode: 'append' | 'prepend' | 'replace'\n value: string\n /** Required when `mode === 'replace'`; exact match only. */\n find?: string\n }\n | {\n kind: 'json'\n mode: 'set' | 'merge' | 'remove'\n path: string\n value?: AgentProfileJson\n }\n\nexport interface PolicyEditExpectedGain {\n /** Metric this edit is expected to move, e.g. `holdout.composite`. */\n metric: string\n direction: PolicyEditGainDirection\n /** Positive magnitude in the metric's native units. */\n amount: number\n unit?: PolicyEditGainUnit\n rationale?: string\n}\n\nexport interface PolicyEditSource {\n findingIds: string[]\n analystIds: string[]\n evidenceRefs: EvidenceRef[]\n /** Mirrors `AnalystFinding.derived_from_judge`; admission rejects it. */\n derivedFromJudge?: boolean\n}\n\nexport interface PolicyEdit {\n schemaVersion: PolicyEditSchemaVersion\n editId: string\n axis: PolicyEditAxis\n target: PolicyEditTarget\n change: PolicyEditChange\n claim: string\n expectedGain: PolicyEditExpectedGain\n confidence: number\n risk: PolicyEditRisk\n source: PolicyEditSource\n rationale?: string\n validationPlan?: string\n metadata?: Record<string, unknown>\n}\n\nexport const POLICY_EDIT_CANDIDATE_RECORD_SCHEMA = 'tangle.policy-edit-candidate.v1' as const\n\n/** JSON-safe attribution carried with a measured candidate and its scores. */\nexport interface PolicyEditCandidateRecord {\n schema: typeof POLICY_EDIT_CANDIDATE_RECORD_SCHEMA\n policyEdit: PolicyEdit\n}\n\nexport type PolicyEditInit = Omit<PolicyEdit, 'schemaVersion' | 'editId'> & {\n schemaVersion?: PolicyEditSchemaVersion\n editId?: string\n}\n\nexport class PolicyEditValidationError extends ValidationError {\n readonly path: string\n constructor(message: string, path = '') {\n super(path ? `${message} (at ${path})` : message)\n this.path = path\n }\n}\n\nexport interface FindingToPolicyEditOptions {\n expectedGain?:\n | PolicyEditExpectedGain\n | ((finding: AnalystFinding) => PolicyEditExpectedGain | null | undefined)\n risk?: PolicyEditRisk | ((finding: AnalystFinding) => PolicyEditRisk)\n defaultAxis?: PolicyEditAxis\n defaultTargetSurface?: PolicyEditTargetSurface\n}\n\nexport interface PolicyEditAdmissionOptions {\n minScore?: number\n minExpectedGain?: number\n allowHighRisk?: boolean\n requireEvidence?: boolean\n}\n\nexport interface PolicyEditAdmission {\n edit: PolicyEdit\n decision: 'admit' | 'reject'\n score: number\n reasons: string[]\n}\n\nconst DEFAULT_MIN_SCORE = 0.7\nconst DEFAULT_MIN_EXPECTED_GAIN = 0.01\nconst POLICY_EDIT_ID = /^policy-edit:sha256:[0-9a-f]{64}$/\n\nexport function makePolicyEdit(init: PolicyEditInit): PolicyEdit {\n const normalized = normalizePolicyEdit({\n schemaVersion: 'policy-edit/v1',\n ...init,\n source: normalizeSource(init.source),\n })\n const edit = {\n ...normalized,\n editId: init.editId ?? computePolicyEditId(normalized),\n }\n return validatePolicyEdit(edit)\n}\n\nexport function computePolicyEditId(edit: Omit<PolicyEdit, 'editId'> | PolicyEdit): string {\n const { editId: _editId, schemaVersion, ...material } = edit as PolicyEdit\n void _editId\n return `policy-edit:${hashCanonical({ schemaVersion, ...material })}`\n}\n\nexport function validatePolicyEdit(input: unknown): PolicyEdit {\n if (input === null || typeof input !== 'object') {\n throw new PolicyEditValidationError('expected object')\n }\n const obj = input as PolicyEdit\n expectLiteral(obj.schemaVersion, 'policy-edit/v1', 'schemaVersion')\n expectString(obj.editId, 'editId')\n if (!POLICY_EDIT_ID.test(obj.editId)) {\n throw new PolicyEditValidationError(\n 'editId must match policy-edit:sha256:<64 lowercase hex chars>',\n 'editId',\n )\n }\n expectOneOf(obj.axis, POLICY_EDIT_AXES, 'axis')\n validateTarget(obj.target)\n validateChange(obj.change)\n expectString(obj.claim, 'claim')\n validateExpectedGain(obj.expectedGain)\n expectConfidence(obj.confidence, 'confidence')\n expectOneOf(obj.risk, ['low', 'medium', 'high', 'unknown'] as const, 'risk')\n validateSource(obj.source)\n if (obj.rationale !== undefined) expectString(obj.rationale, 'rationale')\n if (obj.validationPlan !== undefined) expectString(obj.validationPlan, 'validationPlan')\n if (obj.metadata !== undefined && (obj.metadata === null || typeof obj.metadata !== 'object')) {\n throw new PolicyEditValidationError('expected object', 'metadata')\n }\n const expectedId = computePolicyEditId(obj)\n if (obj.editId !== expectedId) {\n throw new PolicyEditValidationError('editId does not match policy edit content', 'editId')\n }\n return obj\n}\n\nexport function makePolicyEditCandidateRecord(edit: PolicyEdit): PolicyEditCandidateRecord {\n return validatePolicyEditCandidateRecord({\n schema: POLICY_EDIT_CANDIDATE_RECORD_SCHEMA,\n policyEdit: edit,\n })\n}\n\nexport function validatePolicyEditCandidateRecord(input: unknown): PolicyEditCandidateRecord {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n throw new PolicyEditValidationError('expected object', 'candidateRecord')\n }\n const obj = input as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n if (keys.length !== 2 || keys[0] !== 'policyEdit' || keys[1] !== 'schema') {\n throw new PolicyEditValidationError('expected exactly schema and policyEdit', 'candidateRecord')\n }\n expectLiteral(obj.schema, POLICY_EDIT_CANDIDATE_RECORD_SCHEMA, 'candidateRecord.schema')\n const policyEdit = validatePolicyEdit(obj.policyEdit)\n assertJsonSafe(policyEdit, 'candidateRecord.policyEdit')\n const snapshot = JSON.parse(JSON.stringify(policyEdit)) as unknown\n return {\n schema: POLICY_EDIT_CANDIDATE_RECORD_SCHEMA,\n policyEdit: validatePolicyEdit(snapshot),\n }\n}\n\nexport function isPolicyEdit(input: unknown): input is PolicyEdit {\n try {\n validatePolicyEdit(input)\n return true\n } catch {\n return false\n }\n}\n\nexport function policyEditsFromFindings(\n findings: ReadonlyArray<AnalystFinding>,\n opts: FindingToPolicyEditOptions = {},\n): PolicyEdit[] {\n assertNoJudgeVerdict(findings, 'policyEditsFromFindings')\n const edits: PolicyEdit[] = []\n for (const finding of findings) {\n const edit = policyEditFromFinding(finding, opts)\n if (edit) edits.push(edit)\n }\n return edits\n}\n\nexport function policyEditFromFinding(\n finding: AnalystFinding,\n opts: FindingToPolicyEditOptions = {},\n): PolicyEdit | null {\n assertNoJudgeVerdict([finding], 'policyEditFromFinding')\n if (!finding.recommended_action?.trim()) return null\n\n const expectedGain = resolveExpectedGain(finding, opts)\n if (!expectedGain) return null\n // A confidence outside [0,1] is a malformed model-produced row: skip the\n // finding rather than let one poisoned row abort the whole batch.\n if (\n typeof finding.confidence !== 'number' ||\n !Number.isFinite(finding.confidence) ||\n finding.confidence < 0 ||\n finding.confidence > 1\n ) {\n return null\n }\n\n const routed = routeFindingSubject(finding.subject, opts)\n const risk = resolveRisk(finding, opts)\n return makePolicyEdit({\n axis: routed.axis,\n target: routed.target,\n change: { kind: 'text', mode: 'append', value: finding.recommended_action.trim() },\n claim: finding.claim,\n rationale: finding.rationale,\n expectedGain,\n confidence: finding.confidence,\n risk,\n validationPlan: finding.validation_plan,\n source: {\n findingIds: [finding.finding_id],\n analystIds: [finding.analyst_id],\n evidenceRefs: finding.evidence_refs,\n derivedFromJudge: finding.derived_from_judge,\n },\n })\n}\n\nexport function scorePolicyEditReadiness(\n edit: PolicyEdit,\n opts: PolicyEditAdmissionOptions = {},\n): number {\n validatePolicyEdit(edit)\n const minExpectedGain = opts.minExpectedGain ?? DEFAULT_MIN_EXPECTED_GAIN\n const requireEvidence = opts.requireEvidence ?? false\n const evidenceScore = Math.min(1, edit.source.evidenceRefs.length / 2)\n const confidenceScore = clamp01(edit.confidence)\n const gainScore = clamp01(\n Math.abs(edit.expectedGain.amount) / Math.max(minExpectedGain * 5, 0.001),\n )\n const targetScore = targetSpecificityScore(edit)\n const riskPenalty =\n edit.risk === 'high' && opts.allowHighRisk !== true ? 0.35 : edit.risk === 'unknown' ? 0.2 : 0\n\n // Evidence weighs into the base score only when the caller requires it.\n // Otherwise it is a bonus on top: the steer firewall's discriminator is\n // provenance, and an evidence-less trace observation must be able to clear\n // the default bar on confidence, gain, and target specificity alone.\n const base = requireEvidence\n ? 0.3 * evidenceScore + 0.25 * confidenceScore + 0.25 * gainScore + 0.2 * targetScore\n : 0.35 * confidenceScore + 0.35 * gainScore + 0.3 * targetScore + 0.1 * evidenceScore\n return clamp01(base - riskPenalty)\n}\n\nexport function admitPolicyEdit(\n edit: PolicyEdit,\n opts: PolicyEditAdmissionOptions = {},\n): PolicyEditAdmission {\n const validated = validatePolicyEdit(edit)\n const score = scorePolicyEditReadiness(validated, opts)\n const reasons: string[] = []\n const minExpectedGain = opts.minExpectedGain ?? DEFAULT_MIN_EXPECTED_GAIN\n // Default OFF, matching the steer firewall: the admission discriminator is\n // PROVENANCE (derivedFromJudge), not evidence presence — an evidence-less\n // trace-analyst observation is a legitimate edit source. Callers opt IN to\n // an evidence requirement where their domain demands citations.\n const requireEvidence = opts.requireEvidence ?? false\n\n if (validated.source.derivedFromJudge) {\n reasons.push('source is judge-derived; judge verdicts cannot steer policy edits')\n }\n if (requireEvidence && validated.source.evidenceRefs.length === 0) {\n reasons.push('missing evidence refs')\n }\n if (Math.abs(validated.expectedGain.amount) < minExpectedGain) {\n reasons.push(`expected gain below ${minExpectedGain}`)\n }\n if (validated.risk === 'high' && opts.allowHighRisk !== true) {\n reasons.push('high-risk edit requires explicit allowHighRisk')\n }\n if (score < (opts.minScore ?? DEFAULT_MIN_SCORE)) {\n reasons.push(\n `readiness score ${score.toFixed(3)} below ${(opts.minScore ?? DEFAULT_MIN_SCORE).toFixed(3)}`,\n )\n }\n\n return {\n edit: validated,\n decision: reasons.length === 0 ? 'admit' : 'reject',\n score,\n reasons,\n }\n}\n\nexport function applyPolicyEditToSurface(surface: unknown, edit: PolicyEdit): unknown {\n const validated = validatePolicyEdit(edit)\n if (validated.change.kind === 'text') return applyTextChange(surface, validated.change)\n return applyJsonChange(surface, validated.change)\n}\n\nfunction routeFindingSubject(\n subject: string | undefined,\n opts: FindingToPolicyEditOptions,\n): { axis: PolicyEditAxis; target: PolicyEditTarget } {\n const parsed = parseFindingSubject(subject)\n if (!parsed) {\n return {\n axis: opts.defaultAxis ?? 'representation',\n target: { surface: opts.defaultTargetSurface ?? 'prompt' },\n }\n }\n return routeParsedSubject(parsed)\n}\n\nfunction routeParsedSubject(subject: FindingSubject): {\n axis: PolicyEditAxis\n target: PolicyEditTarget\n} {\n switch (subject.kind) {\n case 'system-prompt':\n return {\n axis: 'representation',\n target: { surface: 'prompt', path: `system-prompt:${subject.section}` },\n }\n case 'skill':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `skill:${subject.name}` },\n }\n case 'tool-doc':\n return {\n axis: 'tool_contract',\n target: {\n surface: 'tool-contract',\n path: subject.aspect\n ? `tool-doc:${subject.tool}:${subject.aspect}`\n : `tool-doc:${subject.tool}`,\n },\n }\n case 'new-tool':\n return {\n axis: 'tool_contract',\n target: { surface: 'tool-contract', path: `new-tool:${subject.name}` },\n }\n case 'mcp':\n return {\n axis: 'tool_contract',\n target: {\n surface: 'agent-profile',\n path: subject.tool ? `mcp:${subject.server}:${subject.tool}` : `mcp:${subject.server}`,\n },\n }\n case 'hook':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `hook:${subject.name}` },\n }\n case 'subagent':\n return {\n axis: 'routing',\n target: { surface: 'agent-profile', path: `subagent:${subject.name}` },\n }\n case 'workflow':\n return {\n axis: 'routing',\n target: { surface: 'runtime-config', path: `workflow:${subject.name}` },\n }\n case 'rollout-policy':\n return {\n axis: rolloutPolicyAxis(subject.field),\n target: { surface: 'runtime-config', path: `rollout-policy:${subject.field}` },\n }\n case 'agent-profile':\n return {\n axis: 'agent_profile',\n target: { surface: 'agent-profile', path: `agent-profile:${subject.field}` },\n }\n case 'code':\n return {\n axis: 'representation',\n target: { surface: 'code', path: `code:${subject.path}` },\n }\n case 'rag':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `rag:${subject.corpus}:${subject.docId}` },\n }\n case 'memory':\n return { axis: 'memory', target: { surface: 'memory', path: `memory:${subject.key}` } }\n case 'scaffolding':\n return {\n axis: 'routing',\n target: { surface: 'runtime-config', path: `scaffolding:${subject.concern}` },\n }\n case 'output-schema':\n return {\n axis: 'output_contract',\n target: { surface: 'runtime-config', path: `output-schema:${subject.field}` },\n }\n case 'knowledge.wiki':\n return {\n axis: 'memory',\n target: {\n surface: 'memory',\n path: `agent-knowledge:wiki:${subject.slug}${subject.heading ? `#${subject.heading}` : ''}`,\n },\n }\n case 'knowledge.claim':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:claim:${subject.topic}` },\n }\n case 'knowledge.raw':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:raw:${subject.sourceId}` },\n }\n case 'knowledge.stale':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `agent-knowledge:stale:${subject.slug}` },\n }\n case 'websearch.outdated':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `websearch:outdated:${subject.topic}` },\n }\n case 'prior-run-summary':\n return {\n axis: 'memory',\n target: { surface: 'memory', path: `prior-run-summary:${subject.topic}` },\n }\n case 'cluster':\n return { axis: 'representation', target: { surface: 'prompt', path: subject.label } }\n }\n}\n\nfunction rolloutPolicyAxis(field: string): PolicyEditAxis {\n const normalized = field.toLowerCase()\n if (/budget|max(?:imum)?[-_. ]?(?:turns?|tokens?|cost)|timeout|deadline/.test(normalized)) {\n return 'budget'\n }\n if (/temperature|top[-_. ]?p|sampling|seed|shots?|parallel|concurrency/.test(normalized)) {\n return 'sampling'\n }\n if (/output|schema|format/.test(normalized)) return 'output_contract'\n return 'routing'\n}\n\nfunction resolveExpectedGain(\n finding: AnalystFinding,\n opts: FindingToPolicyEditOptions,\n): PolicyEditExpectedGain | null {\n if (typeof opts.expectedGain === 'function') return opts.expectedGain(finding) ?? null\n if (opts.expectedGain) return opts.expectedGain\n return readExpectedGainFromMetadata(finding.metadata)\n}\n\nfunction readExpectedGainFromMetadata(\n metadata: Record<string, unknown> | undefined,\n): PolicyEditExpectedGain | null {\n const raw =\n readPolicyEditMetadata(metadata)?.expectedGain ??\n readPolicyEditMetadata(metadata)?.expected_gain\n if (!raw || typeof raw !== 'object') return null\n const obj = raw as Record<string, unknown>\n // Metadata is model-produced. A malformed row degrades to null (the finding\n // is skipped) instead of throwing, so one poisoned row cannot abort the\n // whole batch — the same contract as a finding with no expected gain.\n if (\n typeof obj.metric !== 'string' ||\n (obj.direction !== 'increase' && obj.direction !== 'decrease') ||\n typeof obj.amount !== 'number' ||\n !Number.isFinite(obj.amount) ||\n obj.amount <= 0\n ) {\n return null\n }\n const out: PolicyEditExpectedGain = {\n metric: obj.metric,\n direction: obj.direction,\n amount: obj.amount,\n }\n if (\n obj.unit === 'absolute' ||\n obj.unit === 'relative' ||\n obj.unit === 'percent' ||\n obj.unit === 'score'\n ) {\n out.unit = obj.unit\n }\n if (typeof obj.rationale === 'string') out.rationale = obj.rationale\n return out\n}\n\nfunction readPolicyEditMetadata(\n metadata: Record<string, unknown> | undefined,\n): Record<string, unknown> | null {\n const raw = metadata?.policyEdit ?? metadata?.policy_edit\n return raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : null\n}\n\nfunction resolveRisk(finding: AnalystFinding, opts: FindingToPolicyEditOptions): PolicyEditRisk {\n if (typeof opts.risk === 'function') return opts.risk(finding)\n if (opts.risk) return opts.risk\n const raw = readPolicyEditMetadata(finding.metadata)?.risk\n if (raw === 'low' || raw === 'medium' || raw === 'high' || raw === 'unknown') return raw\n if (finding.severity === 'critical' || finding.severity === 'high') return 'medium'\n return 'low'\n}\n\nfunction applyTextChange(\n surface: unknown,\n change: Extract<PolicyEditChange, { kind: 'text' }>,\n): string {\n if (typeof surface !== 'string') {\n throw new PolicyEditValidationError('text policy edits require a string surface', 'change')\n }\n if (change.mode === 'append') {\n if (hasExactTextBlock(surface, change.value)) return surface\n return `${surface.trimEnd()}\\n\\n${change.value}`.trimStart()\n }\n if (change.mode === 'prepend') {\n if (hasExactTextBlock(surface, change.value)) return surface\n return `${change.value}\\n\\n${surface.trimStart()}`.trimEnd()\n }\n const find = expectNonEmpty(change.find, 'change.find')\n if (!surface.includes(find)) {\n throw new PolicyEditValidationError('replace target not found in surface', 'change.find')\n }\n return surface.replace(find, change.value)\n}\n\nfunction applyJsonChange(\n surface: unknown,\n change: Extract<PolicyEditChange, { kind: 'json' }>,\n): AgentProfileJson {\n const root = parseJsonSurface(surface)\n const path = splitPath(change.path)\n if (change.mode === 'remove') return setJsonAtPath(root, path, undefined, 'remove')\n if (change.mode === 'set') return setJsonAtPath(root, path, change.value ?? null, 'set')\n const prior = readJsonAtPath(root, path)\n const merged =\n prior &&\n typeof prior === 'object' &&\n !Array.isArray(prior) &&\n change.value &&\n typeof change.value === 'object' &&\n !Array.isArray(change.value)\n ? { ...prior, ...change.value }\n : (change.value ?? null)\n return setJsonAtPath(root, path, merged as AgentProfileJson, 'set')\n}\n\nfunction parseJsonSurface(surface: unknown): AgentProfileJson {\n if (typeof surface === 'string') {\n try {\n return JSON.parse(surface) as AgentProfileJson\n } catch {\n throw new PolicyEditValidationError(\n 'json policy edits require a JSON string surface',\n 'change',\n )\n }\n }\n assertJson(surface, 'surface')\n return surface as AgentProfileJson\n}\n\nfunction readJsonAtPath(root: AgentProfileJson, path: string[]): AgentProfileJson | undefined {\n let cursor: AgentProfileJson | undefined = root\n for (const part of path) {\n if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor)) return undefined\n cursor = cursor[part]\n }\n return cursor\n}\n\nfunction setJsonAtPath(\n root: AgentProfileJson,\n path: string[],\n value: AgentProfileJson | undefined,\n mode: 'set' | 'remove',\n): AgentProfileJson {\n if (path.length === 0) {\n if (mode === 'remove') return null\n return value ?? null\n }\n if (root === null || typeof root !== 'object' || Array.isArray(root)) {\n throw new PolicyEditValidationError('json edit root must be an object', 'change.path')\n }\n const out: Record<string, AgentProfileJson> = { ...root }\n let cursor: Record<string, AgentProfileJson> = out\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i]!\n const existing = cursor[key]\n if (\n mode === 'remove' &&\n (!existing || typeof existing !== 'object' || Array.isArray(existing))\n ) {\n return out\n }\n const next =\n existing && typeof existing === 'object' && !Array.isArray(existing) ? { ...existing } : {}\n cursor[key] = next\n cursor = next\n }\n const leaf = path[path.length - 1]!\n if (mode === 'remove') delete cursor[leaf]\n else cursor[leaf] = value ?? null\n return out\n}\n\nfunction normalizePolicyEdit(input: Omit<PolicyEdit, 'editId'>): Omit<PolicyEdit, 'editId'> {\n const out: Omit<PolicyEdit, 'editId'> = {\n schemaVersion: 'policy-edit/v1',\n axis: input.axis,\n target: normalizeTarget(input.target),\n change: normalizeChange(input.change),\n claim: input.claim.trim(),\n expectedGain: normalizeExpectedGain(input.expectedGain),\n confidence: input.confidence,\n risk: input.risk,\n source: normalizeSource(input.source),\n }\n if (input.rationale?.trim()) out.rationale = input.rationale.trim()\n if (input.validationPlan?.trim()) out.validationPlan = input.validationPlan.trim()\n if (input.metadata) out.metadata = input.metadata\n return out\n}\n\nfunction assertJsonSafe(value: unknown, path: string, ancestors = new WeakSet<object>()): void {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return\n throw new PolicyEditValidationError('expected finite JSON number', path)\n }\n if (typeof value !== 'object') {\n throw new PolicyEditValidationError('expected JSON-safe value', path)\n }\n if (ancestors.has(value)) {\n throw new PolicyEditValidationError('cyclic value is not JSON-safe', path)\n }\n ancestors.add(value)\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!(i in value)) {\n throw new PolicyEditValidationError('sparse array is not JSON-safe', `${path}.${i}`)\n }\n assertJsonSafe(value[i], `${path}.${i}`, ancestors)\n }\n } else {\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) {\n throw new PolicyEditValidationError('expected plain JSON object', path)\n }\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw new PolicyEditValidationError('symbol keys are not JSON-safe', path)\n }\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n assertJsonSafe(child, `${path}.${key}`, ancestors)\n }\n }\n ancestors.delete(value)\n}\n\nfunction normalizeTarget(target: PolicyEditTarget): PolicyEditTarget {\n const out: PolicyEditTarget = { surface: target.surface }\n if (target.path?.trim()) out.path = target.path.trim()\n if (target.agentProfileCell)\n out.agentProfileCell = validateAgentProfileCell(target.agentProfileCell)\n if (target.label?.trim()) out.label = target.label.trim()\n return out\n}\n\nfunction normalizeChange(change: PolicyEditChange): PolicyEditChange {\n if (change.kind === 'text') {\n const out: Extract<PolicyEditChange, { kind: 'text' }> = {\n kind: 'text',\n mode: change.mode,\n value: change.value.trim(),\n }\n if (change.find?.trim()) out.find = change.find.trim()\n return out\n }\n const out: Extract<PolicyEditChange, { kind: 'json' }> = {\n kind: 'json',\n mode: change.mode,\n path: change.path.trim(),\n }\n if (change.value !== undefined) out.value = change.value\n return out\n}\n\nfunction normalizeExpectedGain(gain: PolicyEditExpectedGain): PolicyEditExpectedGain {\n const out: PolicyEditExpectedGain = {\n metric: gain.metric.trim(),\n direction: gain.direction,\n amount: gain.amount,\n }\n if (gain.unit) out.unit = gain.unit\n if (gain.rationale?.trim()) out.rationale = gain.rationale.trim()\n return out\n}\n\nfunction normalizeSource(source: PolicyEditSource): PolicyEditSource {\n const out: PolicyEditSource = {\n findingIds: uniqueSorted(source.findingIds.map((s) => s.trim()).filter(Boolean)),\n analystIds: uniqueSorted(source.analystIds.map((s) => s.trim()).filter(Boolean)),\n evidenceRefs: source.evidenceRefs,\n }\n if (source.derivedFromJudge) out.derivedFromJudge = true\n return out\n}\n\nfunction validateTarget(target: unknown): asserts target is PolicyEditTarget {\n if (!target || typeof target !== 'object')\n throw new PolicyEditValidationError('expected object', 'target')\n const obj = target as PolicyEditTarget\n expectOneOf(obj.surface, POLICY_EDIT_TARGET_SURFACES, 'target.surface')\n if (obj.path !== undefined) expectString(obj.path, 'target.path')\n if (obj.label !== undefined) expectString(obj.label, 'target.label')\n if (obj.agentProfileCell !== undefined) validateAgentProfileCell(obj.agentProfileCell)\n}\n\nfunction validateChange(change: unknown): asserts change is PolicyEditChange {\n if (!change || typeof change !== 'object')\n throw new PolicyEditValidationError('expected object', 'change')\n const obj = change as PolicyEditChange\n if (obj.kind !== 'text' && obj.kind !== 'json') {\n throw new PolicyEditValidationError('kind must be text or json', 'change.kind')\n }\n if (obj.kind === 'text') {\n expectOneOf(obj.mode, ['append', 'prepend', 'replace'] as const, 'change.mode')\n expectString(obj.value, 'change.value')\n if (obj.mode === 'replace') expectString(obj.find, 'change.find')\n return\n }\n expectOneOf(obj.mode, ['set', 'merge', 'remove'] as const, 'change.mode')\n expectString(obj.path, 'change.path')\n splitPath(obj.path)\n if (obj.value !== undefined) assertJson(obj.value, 'change.value')\n}\n\nfunction validateExpectedGain(gain: unknown): asserts gain is PolicyEditExpectedGain {\n if (!gain || typeof gain !== 'object')\n throw new PolicyEditValidationError('expected object', 'expectedGain')\n const obj = gain as PolicyEditExpectedGain\n expectString(obj.metric, 'expectedGain.metric')\n expectOneOf(obj.direction, ['increase', 'decrease'] as const, 'expectedGain.direction')\n if (!Number.isFinite(obj.amount) || obj.amount <= 0) {\n throw new PolicyEditValidationError(\n 'amount must be a positive finite number',\n 'expectedGain.amount',\n )\n }\n if (obj.unit !== undefined) {\n expectOneOf(\n obj.unit,\n ['absolute', 'relative', 'percent', 'score'] as const,\n 'expectedGain.unit',\n )\n }\n if (obj.rationale !== undefined) expectString(obj.rationale, 'expectedGain.rationale')\n}\n\nfunction validateSource(source: unknown): asserts source is PolicyEditSource {\n if (!source || typeof source !== 'object')\n throw new PolicyEditValidationError('expected object', 'source')\n const obj = source as PolicyEditSource\n expectNonEmptyStringArray(obj.findingIds, 'source.findingIds')\n expectNonEmptyStringArray(obj.analystIds, 'source.analystIds')\n if (!Array.isArray(obj.evidenceRefs)) {\n throw new PolicyEditValidationError('expected array', 'source.evidenceRefs')\n }\n for (const [i, ref] of obj.evidenceRefs.entries())\n validateEvidenceRef(ref, `source.evidenceRefs.${i}`)\n if (obj.derivedFromJudge !== undefined && typeof obj.derivedFromJudge !== 'boolean') {\n throw new PolicyEditValidationError('expected boolean', 'source.derivedFromJudge')\n }\n}\n\nfunction validateEvidenceRef(ref: unknown, path: string): asserts ref is EvidenceRef {\n if (!ref || typeof ref !== 'object') throw new PolicyEditValidationError('expected object', path)\n const obj = ref as EvidenceRef\n expectOneOf(obj.kind, ['span', 'event', 'artifact', 'finding', 'metric'] as const, `${path}.kind`)\n expectString(obj.uri, `${path}.uri`)\n if (obj.excerpt !== undefined) expectString(obj.excerpt, `${path}.excerpt`)\n}\n\nfunction assertJson(value: unknown, path: string): asserts value is AgentProfileJson {\n if (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value))\n ) {\n return\n }\n if (Array.isArray(value)) {\n for (const [i, item] of value.entries()) assertJson(item, `${path}.${i}`)\n return\n }\n if (typeof value === 'object') {\n for (const [key, item] of Object.entries(value)) {\n if (!key) throw new PolicyEditValidationError('empty object key', path)\n assertJson(item, `${path}.${key}`)\n }\n return\n }\n throw new PolicyEditValidationError('expected JSON-compatible value', path)\n}\n\nfunction targetSpecificityScore(edit: PolicyEdit): number {\n let score = 0.4\n if (edit.target.path) score += 0.25\n if (edit.target.agentProfileCell) score += 0.15\n if (edit.change.kind === 'json' || edit.change.mode === 'replace') score += 0.2\n else if (edit.change.value.length > 0) score += 0.1\n return clamp01(score)\n}\n\n// Assigning through these keys on a plain object mutates the prototype chain\n// instead of writing an own property: the edit silently no-ops after\n// JSON.stringify, or crashes the canonical hasher. Edits are analyst- and\n// LLM-authored input, so the refusal is loud, at parse time.\nconst FORBIDDEN_PATH_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\nfunction splitPath(path: string): string[] {\n const parts = path\n .split('.')\n .map((p) => p.trim())\n .filter(Boolean)\n if (parts.length === 0)\n throw new PolicyEditValidationError('path must not be empty', 'change.path')\n for (const part of parts) {\n if (FORBIDDEN_PATH_KEYS.has(part)) {\n throw new PolicyEditValidationError(\n `path segment \"${part}\" would write through the prototype chain`,\n 'change.path',\n )\n }\n }\n return parts\n}\n\nfunction expectLiteral<T extends string>(\n value: unknown,\n expected: T,\n path: string,\n): asserts value is T {\n if (value !== expected) throw new PolicyEditValidationError(`expected ${expected}`, path)\n}\n\nfunction expectString(value: unknown, path: string): asserts value is string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new PolicyEditValidationError('expected non-empty string', path)\n }\n}\n\nfunction expectNonEmpty(value: unknown, path: string): string {\n expectString(value, path)\n return value\n}\n\nfunction expectConfidence(value: unknown, path: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {\n throw new PolicyEditValidationError('expected finite number in [0,1]', path)\n }\n}\n\nfunction hasExactTextBlock(surface: string, value: string): boolean {\n const needle = normalizeTextBlock(value)\n const normalizedSurface = surface.replace(/\\r\\n/g, '\\n')\n return [...normalizedSurface.split(/\\n{2,}/), ...normalizedSurface.split('\\n')].some(\n (block) => normalizeTextBlock(block) === needle,\n )\n}\n\nfunction normalizeTextBlock(value: string): string {\n return value.replace(/\\r\\n/g, '\\n').trim()\n}\n\nfunction expectOneOf<const T extends readonly string[]>(\n value: unknown,\n allowed: T,\n path: string,\n): asserts value is T[number] {\n if (typeof value !== 'string' || !allowed.includes(value)) {\n throw new PolicyEditValidationError(`expected one of ${allowed.join(', ')}`, path)\n }\n}\n\nfunction expectStringArray(value: unknown, path: string): asserts value is string[] {\n if (!Array.isArray(value)) throw new PolicyEditValidationError('expected array', path)\n for (const [i, item] of value.entries()) expectString(item, `${path}.${i}`)\n}\n\nfunction expectNonEmptyStringArray(value: unknown, path: string): asserts value is string[] {\n expectStringArray(value, path)\n if (value.length === 0) throw new PolicyEditValidationError('expected non-empty array', path)\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return [...new Set(values)].sort()\n}\n\nfunction clamp01(n: number): number {\n if (!Number.isFinite(n)) return 0\n if (n < 0) return 0\n if (n > 1) return 1\n return n\n}\n","/**\n * Capability-headroom gate — \"can this task set even SEE the capability\n * you're about to A/B?\"\n *\n * A capability A/B (grant one arm a tool, a skill, extra context — anything)\n * can only detect the capability on tasks the capability-ABSENT baseline\n * FAILS. A task the baseline already passes is saturated: the treatment arm\n * has no headroom to demonstrate anything, and averaging saturated tasks into\n * the comparison dilutes a real effect toward a false null. Calibrate before\n * measuring: run the baseline arm first, classify every task's headroom, and\n * refuse to run the comparison when no task has a gap.\n *\n * Fail-closed on unknown outcomes: a baseline run whose outcome could not be\n * determined (infra loss, unverified, missing) NEVER counts as a failure —\n * treating \"couldn't tell\" as \"failed\" would manufacture headroom out of\n * telemetry gaps and launder infra noise into a treatment effect.\n *\n * Domain-free by construction: the capability under test never appears here.\n * Callers decide what the baseline arm lacks; this module only classifies\n * baseline outcomes per task.\n */\n\nimport { ValidationError } from './errors'\n\n/** One baseline-arm (capability-absent) observation of one task. */\nexport interface HeadroomInput {\n /** Stable task identity; multiple rows per task are multiple baseline reps. */\n taskId: string\n /** Baseline outcome. 'unknown' = the outcome could not be determined —\n * distinct from 'fail' and never counted as one. */\n baselineOutcome: 'pass' | 'fail' | 'unknown'\n}\n\n/** Headroom classification for one task.\n * - 'gap': the baseline fails it — the comparison can see the capability here.\n * - 'saturated': the baseline already passes it — no headroom.\n * - 'unknown': every baseline outcome is unknown — fail-closed, not a gap. */\nexport type HeadroomClass = 'gap' | 'saturated' | 'unknown'\n\nexport interface TaskHeadroom {\n taskId: string\n /** Total baseline observations for this task (known + unknown). */\n n: number\n /** Observations with a known ('pass' | 'fail') outcome — the evidence the\n * classification actually rests on. A large `n` with a small `nKnown`\n * means the headroom verdict is thin, not well-replicated. */\n nKnown: number\n /** Pass rate over KNOWN outcomes only; NaN when every outcome is unknown\n * (no data ≠ measured zero). */\n baselinePassRate: number\n headroom: HeadroomClass\n}\n\nexport interface CapabilityHeadroomOptions {\n /** A task counts as 'gap' when its baseline pass rate is ≤ this. Default 0\n * (the baseline must fail every known rep). Must be in [0, 1) — a\n * threshold of 1 would classify a fully-saturated task as a gap. */\n keepThreshold?: number\n}\n\nexport interface CapabilityHeadroomResult {\n /** Per-task classification, sorted by `taskId`. */\n tasks: TaskHeadroom[]\n summary: {\n tasksWithGap: number\n tasksSaturated: number\n tasksUnknown: number\n /** Total unknown-outcome reps across ALL tasks (including tasks that\n * still classified via their known reps) — the size of the telemetry\n * hole behind the classifications. */\n repsUnknown: number\n }\n}\n\n/**\n * Classify every task's baseline headroom from capability-absent baseline\n * outcomes.\n *\n * A task is 'gap' when it has ≥ 1 known outcome and its pass rate over known\n * outcomes is ≤ `keepThreshold`; 'saturated' when the rate exceeds the\n * threshold; 'unknown' when every outcome is unknown. Unknown reps never\n * count toward the rate in either direction (fail-closed — see the module\n * doc), and evidence strength stays visible: each task reports `nKnown`\n * alongside `n`, and the summary totals the unknown reps in `repsUnknown`.\n * Throws on empty input, an out-of-range `keepThreshold`, or an\n * unrecognized outcome value (rows are often projected from untyped records).\n */\nexport function capabilityHeadroom(\n rows: readonly HeadroomInput[],\n opts: CapabilityHeadroomOptions = {},\n): CapabilityHeadroomResult {\n const keepThreshold = opts.keepThreshold ?? 0\n if (!Number.isFinite(keepThreshold) || keepThreshold < 0 || keepThreshold >= 1) {\n throw new ValidationError(\n `capabilityHeadroom: keepThreshold must be in [0, 1), got ${keepThreshold}`,\n )\n }\n if (rows.length === 0) {\n throw new ValidationError(\n 'capabilityHeadroom: no baseline rows supplied — run the capability-absent baseline arm first',\n )\n }\n\n // taskId → { n, passes, known }\n const byTask = new Map<string, { n: number; passes: number; known: number }>()\n for (const row of rows) {\n if (\n row.baselineOutcome !== 'pass' &&\n row.baselineOutcome !== 'fail' &&\n row.baselineOutcome !== 'unknown'\n ) {\n throw new ValidationError(\n `capabilityHeadroom: unrecognized baselineOutcome '${row.baselineOutcome}' for task '${row.taskId}' (expected 'pass' | 'fail' | 'unknown')`,\n )\n }\n const agg = byTask.get(row.taskId) ?? { n: 0, passes: 0, known: 0 }\n agg.n++\n if (row.baselineOutcome !== 'unknown') {\n agg.known++\n if (row.baselineOutcome === 'pass') agg.passes++\n }\n byTask.set(row.taskId, agg)\n }\n\n const tasks: TaskHeadroom[] = [...byTask.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([taskId, agg]) => {\n if (agg.known === 0) {\n return {\n taskId,\n n: agg.n,\n nKnown: 0,\n baselinePassRate: Number.NaN,\n headroom: 'unknown' as const,\n }\n }\n const baselinePassRate = agg.passes / agg.known\n return {\n taskId,\n n: agg.n,\n nKnown: agg.known,\n baselinePassRate,\n headroom: baselinePassRate <= keepThreshold ? ('gap' as const) : ('saturated' as const),\n }\n })\n\n const summary = {\n tasksWithGap: tasks.filter((t) => t.headroom === 'gap').length,\n tasksSaturated: tasks.filter((t) => t.headroom === 'saturated').length,\n tasksUnknown: tasks.filter((t) => t.headroom === 'unknown').length,\n repsUnknown: tasks.reduce((sum, t) => sum + (t.n - t.nKnown), 0),\n }\n return { tasks, summary }\n}\n\nexport interface AssertCapabilityHeadroomOptions {\n /** Minimum tasks classified 'gap' for the comparison to proceed. Default 1. */\n minTasksWithGap?: number\n}\n\n/**\n * The go/no-go guard: throws when fewer than `minTasksWithGap` tasks have\n * baseline headroom — i.e. the benchmark cannot see the capability, so any\n * comparison run on it would measure noise. Call between the baseline\n * calibration run and the treatment run.\n */\nexport function assertCapabilityHeadroom(\n result: CapabilityHeadroomResult,\n opts: AssertCapabilityHeadroomOptions = {},\n): void {\n const minTasksWithGap = opts.minTasksWithGap ?? 1\n if (!Number.isInteger(minTasksWithGap) || minTasksWithGap < 1) {\n throw new ValidationError(\n `assertCapabilityHeadroom: minTasksWithGap must be an integer ≥ 1, got ${minTasksWithGap}`,\n )\n }\n const { tasksWithGap, tasksSaturated, tasksUnknown } = result.summary\n if (tasksWithGap < minTasksWithGap) {\n const total = result.tasks.length\n throw new ValidationError(\n `assertCapabilityHeadroom: only ${tasksWithGap} of ${total} task(s) have baseline headroom ` +\n `(need ≥ ${minTasksWithGap}). ${tasksSaturated} saturated (baseline already passes), ` +\n `${tasksUnknown} unknown (no determinable baseline outcome). A capability A/B on this ` +\n `task set cannot detect the capability — add tasks the baseline fails, or fix baseline ` +\n `outcome capture, before measuring.`,\n )\n }\n}\n","/**\n * Cost tracker — token + USD accounting per scenario and per run.\n *\n * Adapted from generic usage-event accounting. Every\n * optimizer needs to know \"is the quality gain worth the cost delta?\",\n * and every dashboard needs dollars-per-completed-task. MODEL_PRICING\n * from metrics.ts stays authoritative for estimate math; this module\n * adds the aggregation + per-scenario roll-up that was duplicated\n * across 4 verticals.\n */\n\nimport { estimateCost } from './metrics'\n\nexport interface TokenSpec {\n inputTokens: number\n outputTokens: number\n cachedTokens?: number\n reasoningTokens?: number\n}\n\nexport interface CostEntry extends TokenSpec {\n scenarioId: string\n model: string\n /** Override estimate with an observed cost (e.g. from provider response). */\n actualCostUsd?: number\n timestamp: number\n /** Free-form tags (variant id, round #, etc.). */\n tags?: Record<string, string>\n}\n\nexport interface ScenarioCost {\n scenarioId: string\n entries: CostEntry[]\n totalInputTokens: number\n totalOutputTokens: number\n totalCachedTokens: number\n totalCostUsd: number\n /** Pass flag — set by consumer via markOutcome; used for cost-per-completed-task. */\n completed?: boolean\n}\n\nexport class CostTracker {\n private byScenario = new Map<string, ScenarioCost>()\n\n record(entry: Omit<CostEntry, 'timestamp'> & { timestamp?: number }): CostEntry {\n const full: CostEntry = { timestamp: entry.timestamp ?? Date.now(), ...entry }\n assertNonNegative(full.inputTokens, 'inputTokens')\n assertNonNegative(full.outputTokens, 'outputTokens')\n let bucket = this.byScenario.get(full.scenarioId)\n if (!bucket) {\n bucket = {\n scenarioId: full.scenarioId,\n entries: [],\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCachedTokens: 0,\n totalCostUsd: 0,\n }\n this.byScenario.set(full.scenarioId, bucket)\n }\n bucket.entries.push(full)\n bucket.totalInputTokens += full.inputTokens\n bucket.totalOutputTokens += full.outputTokens\n bucket.totalCachedTokens += full.cachedTokens ?? 0\n bucket.totalCostUsd += costFor(full)\n return full\n }\n\n markOutcome(scenarioId: string, completed: boolean): void {\n const bucket = this.byScenario.get(scenarioId)\n if (!bucket) throw new Error(`CostTracker.markOutcome: unknown scenario \"${scenarioId}\"`)\n bucket.completed = completed\n }\n\n /**\n * Convenience: record + markOutcome in one call from a\n * `{ usage, verdict }`-shaped response (starter-foundry's\n * `invokeMetaJudge` returns this shape; consumers that wrap any\n * judge/critic can follow the same convention).\n *\n * `usage.model` must be present in `MODEL_PRICING` for cost math to\n * populate; otherwise totalCostUsd stays at 0 for the entry but\n * tokens still aggregate.\n */\n recordVerdict(\n verdict: {\n usage?: {\n inputTokens: number\n outputTokens: number\n model: string\n cachedTokens?: number\n reasoningTokens?: number\n }\n verdict?: 'pass' | 'fail' | 'borderline' | string\n },\n scenarioId: string,\n tags?: Record<string, string>,\n ): CostEntry | null {\n if (!verdict.usage) return null\n const entry = this.record({\n scenarioId,\n model: verdict.usage.model,\n inputTokens: verdict.usage.inputTokens,\n outputTokens: verdict.usage.outputTokens,\n cachedTokens: verdict.usage.cachedTokens,\n reasoningTokens: verdict.usage.reasoningTokens,\n tags,\n })\n this.markOutcome(scenarioId, verdict.verdict === 'pass')\n return entry\n }\n\n get(scenarioId: string): ScenarioCost | undefined {\n return this.byScenario.get(scenarioId)\n }\n\n list(): ScenarioCost[] {\n return [...this.byScenario.values()]\n }\n\n summary(): CostSummary {\n const scenarios = this.list()\n const completed = scenarios.filter((s) => s.completed === true)\n const totalCost = scenarios.reduce((a, s) => a + s.totalCostUsd, 0)\n const totalInput = scenarios.reduce((a, s) => a + s.totalInputTokens, 0)\n const totalOutput = scenarios.reduce((a, s) => a + s.totalOutputTokens, 0)\n const totalCompletedCost = completed.reduce((a, s) => a + s.totalCostUsd, 0)\n return {\n scenarioCount: scenarios.length,\n completedCount: completed.length,\n totalInputTokens: totalInput,\n totalOutputTokens: totalOutput,\n totalCostUsd: totalCost,\n avgCostPerScenarioUsd: scenarios.length ? totalCost / scenarios.length : 0,\n costPerCompletedTaskUsd: completed.length ? totalCompletedCost / completed.length : null,\n }\n }\n}\n\nexport interface CostSummary {\n scenarioCount: number\n completedCount: number\n totalInputTokens: number\n totalOutputTokens: number\n totalCostUsd: number\n avgCostPerScenarioUsd: number\n /** Total USD / completed scenarios — null when nothing completed. */\n costPerCompletedTaskUsd: number | null\n}\n\nfunction costFor(entry: CostEntry): number {\n if (typeof entry.actualCostUsd === 'number' && Number.isFinite(entry.actualCostUsd)) {\n return entry.actualCostUsd\n }\n return estimateCost(entry.inputTokens, entry.outputTokens, entry.model)\n}\n\nfunction assertNonNegative(n: number, name: string): void {\n if (!Number.isFinite(n) || n < 0) {\n throw new Error(`CostTracker: ${name} must be a non-negative finite number, got ${n}`)\n }\n}\n","/**\n * Toolchain error-count extractor.\n *\n * Given stderr/stdout from a compiler or test runner, count the number\n * of reported errors/failures. Patterns are deliberately narrow —\n * unknown stderr returns `null` rather than zero so callers can\n * distinguish \"no errors\" from \"different toolchain, couldn't parse\".\n *\n * All patterns are anchored to the start of a line and use bounded\n * character classes to avoid catastrophic backtracking on pathological\n * inputs.\n *\n * Add new toolchains by appending to {@link ERROR_COUNT_PATTERNS};\n * order matters only in the sense that the first matching pattern wins.\n */\n\nexport interface ErrorCountPattern {\n /** Stable identifier for logging + tests. */\n name: string\n /** Must be global (`g` flag) — the extractor counts matches. */\n regex: RegExp\n /** Optional post-processing to extract a count from a single captured match. */\n transform?: (match: RegExpMatchArray) => number\n}\n\nexport const ERROR_COUNT_PATTERNS: ErrorCountPattern[] = [\n {\n // tsc / ts-node: `src/foo.ts(12,3): error TS1234: ...`\n name: 'typescript-tsc',\n regex: /[\\w./-]+\\(\\d+,\\d+\\): error TS\\d+:/g,\n },\n {\n // pytest: `FAILED tests/test_foo.py::test_bar`\n name: 'pytest-failed',\n regex: /^FAILED\\s+\\S+/gm,\n },\n {\n // rustc: `error[E0308]: ...` or `error: ...`\n name: 'rustc',\n regex: /^error(?:\\[[A-Z]\\d+\\])?:/gm,\n },\n {\n // go build: `./foo.go:12:3: ...` — any file:line:col: is an error line\n name: 'golang',\n regex: /^\\.\\/[\\w./-]+\\.go:\\d+:\\d+:/gm,\n },\n {\n // eslint default formatter per-line: ` 12:34 error message rule-id`\n name: 'eslint',\n regex: /^\\s+\\d+:\\d+\\s+error\\s+/gm,\n },\n {\n // eslint summary line: `✖ 17 problems (12 errors, 5 warnings)`\n // Use this only when the per-line formatter isn't present; transform\n // reads the errors count directly.\n name: 'eslint-summary',\n regex: /✖\\s+\\d+\\s+problems?\\s+\\((\\d+)\\s+errors?/gm,\n transform: (m) => Number(m[1] ?? 0),\n },\n]\n\nexport interface ExtractOptions {\n /** Restrict to named patterns — default: all patterns. */\n only?: string[]\n /** Additional patterns to consider BEFORE the built-in list. */\n extra?: ErrorCountPattern[]\n}\n\nexport interface ExtractResult {\n /** Total count of matched errors, or null when no pattern matched. */\n count: number | null\n /** Name of the pattern that matched, or null. */\n matched: string | null\n /** Original matches for callers that want to surface specifics. */\n samples: string[]\n}\n\n/**\n * Try each pattern in order; return the first with matches.\n *\n * Returning `null` (instead of zero) on no-match is deliberate — a\n * callsite that greps for \"typescript errors\" on cargo output should\n * NOT treat that as \"zero TS errors\" because the toolchain is wrong.\n */\nexport function extractErrorCount(text: string, opts: ExtractOptions = {}): ExtractResult {\n if (!text) return { count: null, matched: null, samples: [] }\n\n const patterns = [...(opts.extra ?? []), ...ERROR_COUNT_PATTERNS].filter(\n (p) => !opts.only || opts.only.includes(p.name),\n )\n\n for (const p of patterns) {\n const matches = Array.from(text.matchAll(p.regex))\n if (matches.length === 0) continue\n\n const count = p.transform\n ? matches.reduce((sum, m) => sum + p.transform!(m), 0)\n : matches.length\n\n return {\n count,\n matched: p.name,\n samples: matches.slice(0, 5).map((m) => m[0]),\n }\n }\n\n return { count: null, matched: null, samples: [] }\n}\n","import { type ControlEvalResult, objectiveEval } from '../control-runtime'\nimport type { TraceEmitter } from '../trace/emitter'\nimport type {\n DataAcquisitionPlan,\n KnowledgeAcquisitionMode,\n KnowledgeBundle,\n KnowledgeImportance,\n KnowledgeReadinessReport,\n KnowledgeRecommendedAction,\n KnowledgeRequirement,\n UserQuestion,\n} from './types'\n\nexport interface ScoreKnowledgeReadinessOptions {\n taskId: string\n requirements: KnowledgeRequirement[]\n evidenceIds?: string[]\n claimIds?: string[]\n wikiPageIds?: string[]\n userAnswers?: Record<string, string>\n metadata?: Record<string, unknown>\n now?: Date\n}\n\nexport function scoreKnowledgeReadiness(\n options: ScoreKnowledgeReadinessOptions,\n): KnowledgeReadinessReport {\n const now = options.now ?? new Date()\n const requirements = options.requirements.map(normalizeRequirement)\n const missing = requirements.filter((requirement) => isRequirementMissing(requirement, now))\n const blockingMissingRequirements = missing.filter(isBlockingGap)\n const nonBlockingGaps = missing.filter((requirement) => !isBlockingGap(requirement))\n const readinessScore = weightedReadinessAt(requirements, now)\n const bundle: KnowledgeBundle = {\n taskId: options.taskId,\n requirements,\n evidenceIds: unique([\n ...(options.evidenceIds ?? []),\n ...requirements.flatMap((r) => r.evidenceIds),\n ]),\n claimIds: unique(options.claimIds ?? []),\n wikiPageIds: unique(options.wikiPageIds ?? []),\n userAnswers: options.userAnswers ?? {},\n missing,\n readinessScore,\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n }\n const recommendedAction = chooseRecommendedAction(blockingMissingRequirements, nonBlockingGaps)\n const severity =\n blockingMissingRequirements.length > 0\n ? 'critical'\n : nonBlockingGaps.some((gap) => gap.importance === 'high')\n ? 'warning'\n : 'info'\n const reason =\n blockingMissingRequirements.length > 0\n ? `${blockingMissingRequirements.length} blocking knowledge requirement(s) are missing.`\n : nonBlockingGaps.length > 0\n ? `${nonBlockingGaps.length} non-blocking knowledge gap(s) remain.`\n : 'All declared knowledge requirements are ready.'\n\n return {\n taskId: options.taskId,\n readinessScore,\n blockingMissingRequirements,\n nonBlockingGaps,\n recommendedAction,\n bundle,\n severity,\n reason,\n }\n}\n\nexport function blockingKnowledgeEval(\n report: KnowledgeReadinessReport,\n options: { id?: string; minimumScore?: number; emitter?: TraceEmitter } = {},\n): ControlEvalResult {\n const minimumScore = options.minimumScore ?? 0.7\n const passed =\n report.blockingMissingRequirements.length === 0 && report.readinessScore >= minimumScore\n if (options.emitter) {\n void options.emitter\n .emit({\n kind: 'custom',\n payload: knowledgeReadinessTracePayload(report, { passed, minimumScore }),\n })\n .catch(() => undefined)\n }\n return objectiveEval({\n id: options.id ?? 'knowledge-ready',\n passed,\n score: report.readinessScore,\n severity: passed ? 'info' : report.severity,\n detail: report.reason,\n evidence: report.blockingMissingRequirements.map((r) => r.id).join(', ') || undefined,\n metadata: { knowledgeReadiness: report },\n })\n}\n\nexport function knowledgeReadinessTracePayload(\n report: KnowledgeReadinessReport,\n options: { passed?: boolean; minimumScore?: number } = {},\n): Record<string, unknown> {\n return {\n kind: 'readiness_scored',\n taskId: report.taskId,\n passed: options.passed ?? report.blockingMissingRequirements.length === 0,\n readinessScore: report.readinessScore,\n minimumScore: options.minimumScore,\n blockingRequirementIds: report.blockingMissingRequirements.map((r) => r.id),\n nonBlockingRequirementIds: report.nonBlockingGaps.map((r) => r.id),\n recommendedAction: report.recommendedAction,\n severity: report.severity,\n reason: report.reason,\n }\n}\n\nexport function userQuestionsForKnowledgeGaps(gaps: KnowledgeRequirement[]): UserQuestion[] {\n return gaps\n .filter((gap) => gap.acquisitionMode === 'ask_user' || gap.fallbackPolicy === 'ask')\n .map((gap) => ({\n id: `question_${gap.id}`,\n question: `Please provide: ${gap.description}`,\n reason: `Required for ${gap.requiredFor.join(', ') || 'the task'}.`,\n requirementId: gap.id,\n importance: gap.importance,\n answerType: gap.sensitivity === 'secret' ? 'credential' : 'free_text',\n impactIfUnknown: impactFor(gap),\n }))\n}\n\nexport function acquisitionPlansForKnowledgeGaps(\n gaps: KnowledgeRequirement[],\n): DataAcquisitionPlan[] {\n const byMode = new Map<string, KnowledgeRequirement[]>()\n for (const gap of gaps) {\n const mode = planMode(gap.acquisitionMode)\n if (!mode) continue\n const bucket = byMode.get(mode) ?? []\n bucket.push(gap)\n byMode.set(mode, bucket)\n }\n return [...byMode.entries()].map(([mode, requirements]) => ({\n id: `acquire_${mode}`,\n requirementIds: requirements.map((r) => r.id),\n mode: mode as DataAcquisitionPlan['mode'],\n description: descriptionForPlan(mode as DataAcquisitionPlan['mode'], requirements),\n priority: maxImportance(requirements.map((r) => r.importance)),\n ...(mode === 'ask_user' ? { questions: userQuestionsForKnowledgeGaps(requirements) } : {}),\n }))\n}\n\nfunction normalizeRequirement(requirement: KnowledgeRequirement): KnowledgeRequirement {\n return {\n ...requirement,\n confidenceNeeded: clamp01(requirement.confidenceNeeded),\n currentConfidence: clamp01(requirement.currentConfidence),\n evidenceIds: unique(requirement.evidenceIds),\n }\n}\n\nfunction weightedReadinessAt(requirements: KnowledgeRequirement[], now: Date): number {\n if (requirements.length === 0) return 1\n let weightSum = 0\n let scoreSum = 0\n for (const requirement of requirements) {\n const weight = importanceWeight(requirement.importance)\n const score = isExpired(requirement, now)\n ? 0\n : requirement.confidenceNeeded <= 0\n ? 1\n : Math.min(1, requirement.currentConfidence / requirement.confidenceNeeded)\n weightSum += weight\n scoreSum += weight * score\n }\n return clamp01(scoreSum / weightSum)\n}\n\nfunction isRequirementMissing(requirement: KnowledgeRequirement, now: Date): boolean {\n return isExpired(requirement, now) || requirement.currentConfidence < requirement.confidenceNeeded\n}\n\nfunction isExpired(requirement: KnowledgeRequirement, now: Date): boolean {\n if (!requirement.validUntil) return false\n const deadline = Date.parse(requirement.validUntil)\n if (!Number.isFinite(deadline)) return true\n return deadline <= now.getTime()\n}\n\nfunction isBlockingGap(requirement: KnowledgeRequirement): boolean {\n return (\n requirement.importance === 'blocking' ||\n requirement.fallbackPolicy === 'block' ||\n requirement.sensitivity === 'secret'\n )\n}\n\nfunction chooseRecommendedAction(\n blocking: KnowledgeRequirement[],\n nonBlocking: KnowledgeRequirement[],\n): KnowledgeRecommendedAction {\n const gaps = blocking.length > 0 ? blocking : nonBlocking\n if (gaps.length === 0) return 'run_agent'\n if (gaps.some((gap) => gap.acquisitionMode === 'ask_user' || gap.fallbackPolicy === 'ask'))\n return 'ask_user'\n if (gaps.some((gap) => gap.acquisitionMode === 'query_connector')) return 'query_connectors'\n if (\n gaps.some(\n (gap) => gap.acquisitionMode === 'inspect_repo' || gap.acquisitionMode === 'run_command',\n )\n )\n return 'inspect_repo'\n if (gaps.some((gap) => gap.acquisitionMode === 'search_web')) return 'collect_web_data'\n if (gaps.some((gap) => gap.acquisitionMode === 'not_available')) return 'abort_or_rescope'\n if (nonBlocking.some((gap) => gap.importance === 'high')) return 'build_domain_wiki'\n return 'continue_with_caveat'\n}\n\nfunction planMode(mode: KnowledgeAcquisitionMode): DataAcquisitionPlan['mode'] | null {\n if (mode === 'infer_low_confidence' || mode === 'not_available') return null\n return mode\n}\n\nfunction descriptionForPlan(\n mode: DataAcquisitionPlan['mode'],\n requirements: KnowledgeRequirement[],\n): string {\n const labels = requirements.map((r) => r.description).join('; ')\n if (mode === 'ask_user') return `Ask the user for: ${labels}`\n if (mode === 'search_web') return `Search web or documentation sources for: ${labels}`\n if (mode === 'query_connector') return `Query configured connectors for: ${labels}`\n if (mode === 'inspect_repo') return `Inspect repository context for: ${labels}`\n if (mode === 'run_command') return `Run local commands to collect: ${labels}`\n return `Build domain wiki evidence for: ${labels}`\n}\n\nfunction impactFor(requirement: KnowledgeRequirement): string {\n if (requirement.fallbackPolicy === 'block') return 'The agent should not run until this is known.'\n if (requirement.fallbackPolicy === 'continue_with_caveat')\n return 'The agent may continue, but must disclose uncertainty.'\n if (requirement.fallbackPolicy === 'use_default')\n return 'The agent will use the configured default if skipped.'\n return 'The agent should ask before continuing.'\n}\n\nfunction maxImportance(values: KnowledgeImportance[]): KnowledgeImportance {\n const order: KnowledgeImportance[] = ['blocking', 'high', 'medium', 'low']\n return order.find((value) => values.includes(value)) ?? 'low'\n}\n\nfunction importanceWeight(importance: KnowledgeImportance): number {\n if (importance === 'blocking') return 8\n if (importance === 'high') return 4\n if (importance === 'medium') return 2\n return 1\n}\n\nfunction clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n\nfunction unique<T>(items: T[]): T[] {\n return [...new Set(items)]\n}\n","/**\n * Cross-profile leaderboard — rank agent profiles (or any grouping) over a corpus\n * of RunRecords on pass-rate with a Wilson CI, joined with the cost / token /\n * latency rollup every benchmark wants next to the score.\n *\n * This is substrate, not benchmark-specific: any consumer of agent-eval gets a\n * cross-harness × model leaderboard without re-implementing grouping, binomial\n * CIs, or the observability join. The benchmark supplies only what \"passed\"\n * means; everything else composes existing primitives (`wilson`, the RunRecord\n * cost/token/wall fields, the AgentProfileCell grouping key).\n */\nimport type { RunRecord } from './run-record'\nimport { wilson } from './statistics'\n\nexport interface LeaderboardRow {\n /** Group key — the agent-profile cellId by default, else a caller dimension. */\n key: string\n /** Display label: `harness · model` when the profile carries them, else the key. */\n label: string\n harness?: string\n model?: string\n rank: number\n /** Measured runs in this group. */\n n: number\n passRate: number\n passRateCi95: [number, number]\n /** Observability rollup — means over the group; null when no run reported it. */\n meanCostUsd: number | null\n meanTokensIn: number | null\n meanTokensOut: number | null\n meanWallMs: number | null\n}\n\nexport interface LeaderboardOptions {\n /** Per-run pass predicate — the benchmark defines what \"passed\" means (real-build\n * hit-rate, test-pass, etc.). The leaderboard owns only the grouping + stats. */\n passed: (record: RunRecord) => boolean\n /** Group key. Default: the agent-profile cellId (harness × model × dimensions),\n * so persona/harness/model sweeps separate without parsing labels. */\n groupBy?: (record: RunRecord) => string\n}\n\nfunction mean(xs: number[]): number | null {\n return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : null\n}\n\n/**\n * Group `records`, compute pass-rate + Wilson CI + cost/token/latency means per\n * group, and rank by pass-rate (cost as the tiebreaker — cheaper wins a tie).\n * Pure projection: no I/O, deterministic, safe to call on any RunRecord[].\n */\nexport function leaderboard(records: RunRecord[], opts: LeaderboardOptions): LeaderboardRow[] {\n const keyOf = opts.groupBy ?? ((r: RunRecord) => r.agentProfile?.cellId ?? 'ungrouped')\n const groups = new Map<string, RunRecord[]>()\n for (const r of records) {\n const k = keyOf(r)\n const g = groups.get(k)\n if (g) g.push(r)\n else groups.set(k, [r])\n }\n\n const rows: LeaderboardRow[] = [...groups.entries()].map(([key, rs]) => {\n const passes = rs.filter((r) => opts.passed(r)).length\n const ci = wilson(passes, rs.length)\n const profile = rs[0]!.agentProfile\n const harness = profile?.harness?.id\n const model = profile?.model\n const knownCosts = rs.map((r) => r.costUsd).filter(isFiniteNumber)\n return {\n key,\n label: harness && model ? `${harness} · ${model}` : key,\n ...(harness ? { harness } : {}),\n ...(model ? { model } : {}),\n rank: 0,\n n: rs.length,\n passRate: ci.estimate,\n passRateCi95: [ci.lower, ci.upper],\n meanCostUsd: knownCosts.length === rs.length ? mean(knownCosts) : null,\n meanTokensIn: mean(rs.map((r) => r.tokenUsage.input)),\n meanTokensOut: mean(rs.map((r) => r.tokenUsage.output)),\n meanWallMs: mean(rs.map((r) => r.wallMs)),\n }\n })\n\n rows.sort(\n (a, b) => b.passRate - a.passRate || (a.meanCostUsd ?? Infinity) - (b.meanCostUsd ?? Infinity),\n )\n rows.forEach((row, i) => {\n row.rank = i + 1\n })\n return rows\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n","/**\n * Deterministic held-out partitioning over stable ids.\n *\n * A promotion gate's paired-delta math needs a fixed partition: the same\n * scenario id lands in the same bucket forever, regardless of when it ran or\n * which loop emitted the record — otherwise the gate has nothing paired to\n * compare against. Picking one global split per run is wrong: every run then\n * stamps either ALL search or ALL holdout, and no id is ever observed on both\n * sides. Per-id deterministic hashing fixes that.\n *\n * Two consumers hand-roll this (agent-builder's `deterministicSplit` and the\n * frontier persona-splitter). The substrate already has a 3-way benchmark\n * `deterministicSplit` in `./benchmarks`; this is the generic, validated batch\n * partitioner: it takes a list of ids, splits them by a stable FNV-1a hash, and\n * fails loud when the inputs can't support a trustworthy held-out comparison\n * (duplicate ids, or a holdout set below the significance floor).\n */\n\nimport { ValidationError } from './errors'\n\n/** 32-bit FNV-1a over UTF-16 code units masked to a byte. Stable,\n * allocation-free, deterministic across runtimes — the same id+seed maps to\n * the same bucket on every machine and process.\n *\n * Frozen: this value picks the held-out bucket, so changing the masking or\n * the accumulator re-partitions every split already decided under it and\n * silently invalidates the comparisons made against them. The other FNV-1a\n * loops in this package mask differently and are not interchangeable with\n * this one. */\nexport function fnv1a32(input: string): number {\n let h = 0x811c9dc5\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i) & 0xff\n h = Math.imul(h, 0x01000193)\n }\n return h >>> 0\n}\n\n/** Map an id+seed to the half-open unit interval [0, 1) deterministically. */\nexport function hashToUnit(id: string, seed: string): number {\n // Newline separator: 'ab' + '\\n' + 'c' can't collide with 'a' + '\\n' + 'bc'.\n return fnv1a32(`${id}\\n${seed}`) / 0x1_0000_0000\n}\n\nexport interface PartitionHeldOutOptions {\n /** Partition seed. Bumping it reshuffles every assignment — do that only when\n * the corpus/policy changes meaningfully so old and new records can't pair.\n * Default 'held-out-v1'. */\n seed?: string\n /** Fraction routed to the held-out bucket, in (0, 1). Default 0.5. */\n holdoutFraction?: number\n /**\n * Minimum held-out ids required for the split to be admissible. Below this,\n * a paired comparison has too few observations to be significant, so the\n * partition throws rather than hand back an underpowered holdout. Default 1\n * (only the empty-holdout degenerate case is rejected). Raise it to enforce\n * real statistical power. */\n minHoldout?: number\n /** Same floor for the search side. Default 1. */\n minSearch?: number\n}\n\nexport interface HeldOutPartition {\n /** Ids the optimizer is allowed to read/optimize against. */\n search: string[]\n /** Ids reserved for gated, held-out evaluation. */\n holdout: string[]\n seed: string\n holdoutFraction: number\n}\n\n/**\n * Assign a single id to `'search'` or `'holdout'` deterministically. Same\n * `(id, seed)` always returns the same tag — the invariant the gate relies on.\n * Use this in a `splitTag:` field literal when stamping records one at a time;\n * use `partitionHeldOut` when you have the whole id list up front and want the\n * validated disjoint split.\n */\nexport function assignHeldOutTag(\n id: string,\n options: { seed?: string; holdoutFraction?: number } = {},\n): 'search' | 'holdout' {\n const seed = options.seed ?? 'held-out-v1'\n const holdoutFraction = options.holdoutFraction ?? 0.5\n assertFraction(holdoutFraction)\n return hashToUnit(id, seed) < holdoutFraction ? 'holdout' : 'search'\n}\n\n/**\n * Partition a list of stable ids into disjoint `search` / `holdout` sets by a\n * deterministic hash. Fail-loud:\n * - empty input throws,\n * - duplicate ids throw (a dup would be observed on both sides, double-counting),\n * - a holdout (or search) set below its floor throws (underpowered comparison).\n *\n * Order within each bucket follows the input order, so the result is stable and\n * reproducible.\n */\nexport function partitionHeldOut(\n ids: string[],\n options: PartitionHeldOutOptions = {},\n): HeldOutPartition {\n const seed = options.seed ?? 'held-out-v1'\n const holdoutFraction = options.holdoutFraction ?? 0.5\n const minHoldout = options.minHoldout ?? 1\n const minSearch = options.minSearch ?? 1\n assertFraction(holdoutFraction)\n if (ids.length === 0) {\n throw new ValidationError('partitionHeldOut: no ids supplied')\n }\n\n const seen = new Set<string>()\n const search: string[] = []\n const holdout: string[] = []\n for (const id of ids) {\n if (typeof id !== 'string' || id.length === 0) {\n throw new ValidationError(\n `partitionHeldOut: ids must be non-empty strings, got ${JSON.stringify(id)}`,\n )\n }\n if (seen.has(id)) {\n throw new ValidationError(\n `partitionHeldOut: duplicate id \"${id}\" — a paired comparison must not double-count`,\n )\n }\n seen.add(id)\n if (hashToUnit(id, seed) < holdoutFraction) holdout.push(id)\n else search.push(id)\n }\n\n if (holdout.length < minHoldout) {\n throw new ValidationError(\n `partitionHeldOut: holdout set has ${holdout.length} id(s), below the floor of ${minHoldout} ` +\n `(n=${ids.length}, holdoutFraction=${holdoutFraction}) — too few for a significant comparison`,\n )\n }\n if (search.length < minSearch) {\n throw new ValidationError(\n `partitionHeldOut: search set has ${search.length} id(s), below the floor of ${minSearch} ` +\n `(n=${ids.length}, holdoutFraction=${holdoutFraction})`,\n )\n }\n\n return { search, holdout, seed, holdoutFraction }\n}\n\nfunction assertFraction(f: number): void {\n if (!Number.isFinite(f) || f <= 0 || f >= 1) {\n throw new ValidationError(`partitionHeldOut: holdoutFraction must be in (0, 1), got ${f}`)\n }\n}\n","/**\n * Export side of the product benchmark bundle contract: convert product\n * eval run directories (`records.jsonl` of `RunRecord` rows + trace/raw\n * artifacts) into a portable `product-benchmark-manifest.json` +\n * `product-benchmark-records.jsonl` bundle that\n * `validateProductBenchmarkRun` accepts.\n *\n * Product-specific policy (safety-split detection, tool-call recovery,\n * profile id fallback, artifact materialization) enters through explicit\n * options; everything else is the shared union of the tax/legal/creative\n * exporters. Scenario catalogs, smoke runners, and CLIs stay in the\n * products.\n *\n * Input rows are checked structurally, not with `validateRunRecord`:\n * product harnesses record bare model aliases and partial provenance, and\n * the bundle contract's own validators re-check every field that matters\n * on the way out.\n */\n\nimport { spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { ValidationError } from '../errors'\nimport { type RunRecord, runTaskScore } from '../run-record'\nimport type {\n ProductBenchmarkManifest,\n ProductBenchmarkRecord,\n ProductBenchmarkSplit,\n RuntimeResolution,\n} from './index'\nimport { validateProductBenchmarkManifest, validateProductBenchmarkRecord } from './index'\n\n/** Full mutable-surface superset a product arm may declare. */\nexport const productBenchmarkMutableSurfaces = [\n 'prompt',\n 'resources.files',\n 'tools',\n 'mcp',\n 'hooks',\n 'subagents',\n] as const\n\nexport interface ProductBenchmarkExportOptions {\n /** Source eval run directories, each containing a `records.jsonl` of RunRecord rows. */\n readonly runDirs: readonly string[]\n /** Destination directory for the bundle (manifest + records + materialized source runs). */\n readonly outDir: string\n readonly projectId: string\n readonly benchmarkId: string\n /** Repo-relative path of the product's canonical agent profile source. */\n readonly agentProfilePath: string\n /** Pass threshold applied when a row carries no explicit `outcome.raw.pass`. Default 0.7. */\n readonly passThreshold?: number\n /**\n * First scenario tag. Defaults to `projectId` with a trailing `-agent`\n * stripped (`tax-agent` → `tax`), matching the product exporters.\n */\n readonly scenarioTagPrefix?: string\n /** Profile id used when a row has no `agentProfile.profileId`. Defaults to the row's arm id. */\n readonly fallbackProfileId?: string\n /** Arm mutable surfaces recorded in the manifest. Defaults to the full superset. */\n readonly mutableSurfaces?: readonly string[]\n /**\n * Copy each run dir into `<outDir>/source-runs/` and record\n * bundle-relative artifact paths (portable, self-contained). When false,\n * artifacts keep absolute paths into the original run dirs. Default true.\n */\n readonly materializeSourceRuns?: boolean\n /**\n * Override split classification for a row. Return undefined to fall back\n * to the default (`outcome.raw.safety === 1` → safety, then splitTag).\n */\n readonly classifySplit?: (record: RunRecord) => ProductBenchmarkSplit | undefined\n /** Recovers a tool-call count when the row's raw bag carries none (e.g. from turn artifacts). */\n readonly toolCallFallback?: (record: RunRecord, runDir: string) => number\n /** Backend version recorded per row. Defaults to the cwd package.json's `@tangle-network/sandbox` range. */\n readonly backendVersion?: string\n /**\n * Explicit substrate versions for the manifest, merged over what the cwd\n * package.json / node_modules resolve. Use when a substrate package is not\n * installed where the export runs — the validator refuses an `'unknown'`\n * version, so provide the real one rather than shipping the sentinel.\n */\n readonly substrate?: Partial<ProductBenchmarkManifest['substrate']>\n}\n\nexport interface ProductBenchmarkSingleRunExportOptions\n extends Omit<ProductBenchmarkExportOptions, 'runDirs'> {\n readonly runDir: string\n}\n\nexport interface ProductBenchmarkExportResult {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly records: number\n}\n\ninterface ResolvedExportOptions {\n readonly projectId: string\n readonly benchmarkId: string\n readonly agentProfilePath: string\n readonly passThreshold: number\n readonly scenarioTagPrefix: string\n readonly fallbackProfileId?: string\n readonly mutableSurfaces: readonly string[]\n readonly classifySplit?: (record: RunRecord) => ProductBenchmarkSplit | undefined\n readonly toolCallFallback?: (record: RunRecord, runDir: string) => number\n readonly backendVersion: string\n}\n\n// ── Provenance helpers ───────────────────────────────────────────────\n\nfunction sha256(value: string): string {\n return `sha256:${createHash('sha256').update(value).digest('hex')}`\n}\n\nfunction safePathPart(value: string): string {\n return (\n value\n .replace(/[^a-zA-Z0-9_.-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80) || 'artifact'\n )\n}\n\nfunction git(args: readonly string[], fallback: string): string {\n const res = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8' })\n const value = res.status === 0 ? res.stdout.trim() : ''\n return value.length > 0 ? value : fallback\n}\n\nfunction knownEnv(name: string): string | undefined {\n const value = process.env[name]?.trim()\n return value && value !== 'unknown' ? value : undefined\n}\n\nfunction ciBranchName(): string | undefined {\n const direct =\n knownEnv('GITHUB_HEAD_REF') ?? knownEnv('GITHUB_REF_NAME') ?? knownEnv('VERCEL_GIT_COMMIT_REF')\n if (direct) return direct\n const ref = knownEnv('GITHUB_REF')\n return ref?.startsWith('refs/heads/') ? ref.slice('refs/heads/'.length) : undefined\n}\n\nfunction repoBranch(): string {\n const ci = ciBranchName()\n if (ci) return ci\n const branch = git(['branch', '--show-current'], '')\n if (branch) return branch\n const name = git(['name-rev', '--name-only', '--exclude=tags/*', 'HEAD'], '')\n if (name && name !== 'undefined') return name\n return `detached:${git(['rev-parse', '--short', 'HEAD'], 'unknown')}`\n}\n\n/** Repo identity from the exporting process's cwd. `'unknown'` values are flagged by `validateProductBenchmarkRun`. */\nexport function productBenchmarkRepoIdentity(): ProductBenchmarkManifest['repo'] {\n return {\n url: git(['config', '--get', 'remote.origin.url'], 'unknown'),\n commit: git(['rev-parse', 'HEAD'], 'unknown'),\n branch: repoBranch(),\n }\n}\n\n/** The declared range from the cwd package.json when present, else the\n * INSTALLED version read from node_modules (covers transitive installs —\n * a product that gets sandbox via agent-runtime still records real\n * provenance), else the `'unknown'` sentinel the validator refuses. */\nfunction packageVersion(name: string): string {\n const pkg = JSON.parse(readFileSync(resolve('package.json'), 'utf8')) as {\n name?: string\n version?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n if (pkg.name === name && pkg.version) return pkg.version\n const declared = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]\n if (declared) return declared\n const installed = resolve('node_modules', name, 'package.json')\n if (existsSync(installed)) {\n const installedPkg = JSON.parse(readFileSync(installed, 'utf8')) as { version?: string }\n if (installedPkg.version) return installedPkg.version\n }\n return 'unknown'\n}\n\n// ── Run record ingestion ─────────────────────────────────────────────\n\nfunction readRunRecords(path: string): RunRecord[] {\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n return lines.map((line, index) => {\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch (err) {\n throw new ValidationError(\n `${path}:${index + 1}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n )\n }\n return expectRunRecordShape(parsed, `${path}:${index + 1}`)\n })\n}\n\nfunction expectRunRecordShape(value: unknown, path: string): RunRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new ValidationError(`${path}: run record must be an object`)\n }\n const obj = value as Record<string, unknown>\n for (const key of ['runId', 'model'] as const) {\n if (typeof obj[key] !== 'string' || obj[key].length === 0) {\n throw new ValidationError(`${path}: run record ${key} must be a non-empty string`)\n }\n }\n for (const key of ['costUsd', 'wallMs'] as const) {\n if (typeof obj[key] !== 'number' || !Number.isFinite(obj[key])) {\n throw new ValidationError(`${path}: run record ${key} must be a finite number`)\n }\n }\n const tokenUsage = obj.tokenUsage as Record<string, unknown> | undefined\n if (\n !tokenUsage ||\n typeof tokenUsage.input !== 'number' ||\n typeof tokenUsage.output !== 'number'\n ) {\n throw new ValidationError(`${path}: run record tokenUsage.input/output must be numbers`)\n }\n const outcome = obj.outcome as Record<string, unknown> | undefined\n if (!outcome?.raw || typeof outcome.raw !== 'object') {\n throw new ValidationError(`${path}: run record outcome.raw must be an object`)\n }\n return value as RunRecord\n}\n\n// ── Row mapping ──────────────────────────────────────────────────────\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value))\n}\n\nfunction splitOf(record: RunRecord, opts: ResolvedExportOptions): ProductBenchmarkSplit {\n const custom = opts.classifySplit?.(record)\n if (custom) return custom\n if ((record.outcome.raw as Record<string, number>).safety === 1) return 'safety'\n if (record.splitTag === 'holdout') return 'holdout'\n if (record.splitTag === 'dev') return 'dev'\n return 'practice'\n}\n\n/** Ungated: a published benchmark record is audit evidence, so the score must\n * stay the measured one. KNOWN HOLE: a realness-gated run still publishes with\n * `pass: true`. The fix mirrors `RolloutLine` — carry the gate as a field on\n * `ProductBenchmarkRecord` and force `pass: false` — which is a schema change,\n * not a call swap, and is tracked separately from this correctness fix. */\nfunction scoreOf(record: RunRecord): number {\n const score = runTaskScore(record)\n if (score !== undefined) return clamp01(score)\n if (\n (record.outcome.judgeScores?.failedJudges?.length ?? 0) > 0 ||\n (record.outcome.raw.judge_error_count ?? 0) > 0\n ) {\n throw new ValidationError(\n `Run ${record.runId} has incomplete judge evidence; product benchmark rows require a complete task score`,\n )\n }\n throw new ValidationError(\n `Run ${record.runId} has no task score; product benchmark rows require an explicit score`,\n )\n}\n\nfunction rawPassOf(record: RunRecord): boolean | null {\n const rawPass = (record.outcome.raw as Record<string, unknown>).pass\n if (typeof rawPass === 'boolean') return rawPass\n if (typeof rawPass === 'number' && Number.isFinite(rawPass)) return rawPass >= 1\n return null\n}\n\nfunction passOf(record: RunRecord, score: number, threshold: number): boolean {\n const rawPass = rawPassOf(record)\n const hasTaskFailure = record.failureClass !== undefined && record.failureClass !== 'success'\n if (rawPass !== null) return rawPass && !hasTaskFailure\n return score >= threshold && !hasTaskFailure\n}\n\nfunction failureOf(\n record: RunRecord,\n score: number,\n threshold: number,\n): Pick<ProductBenchmarkRecord['outcome'], 'failureClass' | 'failureDetail'> {\n if (record.failureClass !== undefined && record.failureClass !== 'success') {\n return {\n failureClass: record.failureClass,\n failureDetail: record.failureMode ?? null,\n }\n }\n const belowThreshold = `quality-below-threshold: ${Math.round(score * 100)}% < ${Math.round(threshold * 100)}%`\n if (rawPassOf(record) === false) {\n return {\n failureClass: 'unknown',\n failureDetail: score < threshold ? belowThreshold : 'product-pass-failed',\n }\n }\n if (passOf(record, score, threshold)) {\n return { failureClass: null, failureDetail: null }\n }\n return { failureClass: 'unknown', failureDetail: belowThreshold }\n}\n\nfunction numericDimensions(record: RunRecord): Record<string, number> {\n const dimensions: Record<string, number> = {}\n for (const [key, value] of Object.entries(record.outcome.raw ?? {})) {\n if (typeof value === 'number' && Number.isFinite(value)) dimensions[key] = value\n }\n if (Object.keys(dimensions).length === 0) dimensions.score = scoreOf(record)\n return dimensions\n}\n\nfunction armIdOf(record: RunRecord): string {\n if (record.candidateId) return record.candidateId\n const variant = record.agentProfile?.dimensions?.variant\n if (typeof variant === 'string' && variant.length > 0) return variant\n const variantId = record.agentProfile?.dimensions?.variantId\n if (typeof variantId === 'string' && variantId.length > 0) return variantId\n return 'production-profile'\n}\n\nfunction backendOf(record: RunRecord): string {\n const backend = record.agentProfile?.dimensions?.backend\n return typeof backend === 'string' && backend.length > 0 ? backend : 'unknown'\n}\n\nfunction modelProvider(record: RunRecord): string {\n const backend = backendOf(record)\n if (backend === 'cli-bridge') return 'cli-bridge'\n if (backend === 'sandbox') return 'router'\n if (record.model.startsWith('router/')) return 'router'\n return backend === 'unknown' ? 'router' : backend\n}\n\nfunction runtimeResolution(record: RunRecord, opts: ResolvedExportOptions): RuntimeResolution {\n const reasoningEffort = record.agentProfile?.dimensions?.reasoningLevel\n return {\n model: record.agentProfile?.model ?? record.model,\n harness: record.agentProfile?.harness?.id ?? `${opts.projectId}-canonical-eval`,\n backend: backendOf(record),\n ...(typeof reasoningEffort === 'string' && reasoningEffort.length > 0\n ? { reasoningEffort }\n : {}),\n }\n}\n\nfunction sourceProfileHash(record: RunRecord): string {\n return (\n record.agentProfile?.sourceProfile?.hash ??\n record.agentProfile?.cellId ??\n sha256(\n JSON.stringify({\n candidateId: record.candidateId,\n promptHash: record.promptHash,\n configHash: record.configHash,\n }),\n )\n )\n}\n\nfunction materializedProfileHash(record: RunRecord, runtime: RuntimeResolution): string {\n return sha256(\n JSON.stringify({ sourceProfileHash: sourceProfileHash(record), model: runtime.model }),\n )\n}\n\nfunction profileIdOf(\n record: RunRecord,\n armId: string,\n runtime: RuntimeResolution,\n opts: ResolvedExportOptions,\n): string {\n const base = record.agentProfile?.profileId ?? opts.fallbackProfileId ?? armId\n const withArm = base.endsWith(`:${armId}`) ? base : `${base}:${armId}`\n return `${withArm}:${runtime.model}`\n}\n\nfunction toolCallsOf(record: RunRecord, runDir: string, opts: ResolvedExportOptions): number {\n const raw = record.outcome.raw as Record<string, unknown>\n const primary = Number(raw.tool_call_count ?? raw.tool_calls ?? raw.toolCalls ?? 0)\n if (Number.isFinite(primary) && primary > 0) return primary\n const fallback = opts.toolCallFallback?.(record, runDir)\n if (fallback !== undefined && Number.isFinite(fallback) && fallback > 0) return fallback\n return Number.isFinite(primary) ? primary : 0\n}\n\n// ── Artifact layout ──────────────────────────────────────────────────\n\nconst TRACE_CANDIDATES = ['traces.jsonl', 'traces', 'trace', 'trace-store'] as const\nconst RAW_CANDIDATES = ['raws.jsonl', 'raw-events'] as const\nconst SCORE_CANDIDATES = ['scores.json', 'manifest.json'] as const\n\nfunction firstExisting(runDir: string, candidates: readonly string[]): string {\n return candidates.find((candidate) => existsSync(join(runDir, candidate))) ?? candidates[0]!\n}\n\nfunction relativeArtifacts(runDir: string): ProductBenchmarkRecord['artifacts'] {\n return {\n records: 'records.jsonl',\n traces: firstExisting(runDir, TRACE_CANDIDATES),\n raws: firstExisting(runDir, RAW_CANDIDATES),\n scores: firstExisting(runDir, SCORE_CANDIDATES),\n workspace: existsSync(join(runDir, 'workspace')) ? 'workspace' : '.',\n }\n}\n\nfunction absoluteArtifacts(runDir: string): ProductBenchmarkRecord['artifacts'] {\n const rel = relativeArtifacts(runDir)\n return {\n records: resolve(runDir, rel.records),\n traces: resolve(runDir, rel.traces),\n raws: resolve(runDir, rel.raws),\n scores: resolve(runDir, rel.scores),\n workspace: resolve(runDir, rel.workspace),\n }\n}\n\nfunction materializeRunArtifacts(\n runDir: string,\n outDir: string,\n index: number,\n): ProductBenchmarkRecord['artifacts'] {\n if (resolve(runDir) === resolve(outDir)) return relativeArtifacts(runDir)\n const rel = relative(runDir, outDir)\n if (rel && !rel.startsWith('..') && !isAbsolute(rel)) {\n throw new ValidationError(`outDir must not be nested inside runDir: ${outDir}`)\n }\n const id = `${String(index + 1).padStart(2, '0')}-${safePathPart(basename(runDir))}-${sha256(runDir).slice(7, 19)}`\n const destRel = join('source-runs', id)\n const destAbs = join(outDir, destRel)\n mkdirSync(dirname(destAbs), { recursive: true })\n cpSync(runDir, destAbs, { recursive: true, force: true })\n const source = relativeArtifacts(runDir)\n return {\n records: join(destRel, source.records),\n traces: join(destRel, source.traces),\n raws: join(destRel, source.raws),\n scores: join(destRel, source.scores),\n workspace: source.workspace === '.' ? destRel : join(destRel, source.workspace),\n }\n}\n\nfunction existsArtifact(artifactRoot: string, value: string): boolean {\n return existsSync(resolve(artifactRoot, value))\n}\n\n// ── Record + manifest construction ───────────────────────────────────\n\n/** Map one RunRecord row to a validated product benchmark record. */\nexport function runRecordToProductBenchmarkRecord(\n record: RunRecord,\n runDir: string,\n artifactRoot: string,\n artifacts: ProductBenchmarkRecord['artifacts'],\n options: ProductBenchmarkExportOptions | ProductBenchmarkSingleRunExportOptions,\n): ProductBenchmarkRecord {\n const opts = resolveOptions(options)\n const runtime = runtimeResolution(record, opts)\n const score = scoreOf(record)\n const failure = failureOf(record, score, opts.passThreshold)\n const armId = armIdOf(record)\n const inputTokens = record.tokenUsage.input\n const outputTokens = record.tokenUsage.output\n const toolCallCount = toolCallsOf(record, runDir, opts)\n const dimensions = numericDimensions(record)\n if (record.costUsd === null) {\n throw new ValidationError(\n `run '${record.runId}' has no USD cost; product benchmark exports require priced runs`,\n )\n }\n const costUsd = record.costUsd\n if (!('tool_calls' in dimensions)) dimensions.tool_calls = toolCallCount\n const product: ProductBenchmarkRecord = {\n schemaVersion: 1,\n projectId: opts.projectId,\n benchmarkId: opts.benchmarkId,\n runId: record.runId,\n scenarioId: record.scenarioId,\n split: splitOf(record, opts),\n armId,\n rep: Number(record.seed ?? 0) + 1,\n agentProfile: {\n id: profileIdOf(record, armId, runtime, opts),\n hash: materializedProfileHash(record, runtime),\n path: opts.agentProfilePath,\n declared: runtime,\n resolved: runtime,\n },\n model: { provider: modelProvider(record), id: record.model },\n backend: { kind: backendOf(record), version: opts.backendVersion },\n outcome: {\n pass: passOf(record, score, opts.passThreshold),\n score,\n dimensions,\n ...failure,\n },\n usage: {\n inputTokens,\n outputTokens,\n costUsd,\n // Rounded: the bundle contract requires integer milliseconds.\n wallMs: Math.round(record.wallMs),\n toolCalls: toolCallCount,\n },\n integrity: {\n realBackend: inputTokens + outputTokens > 0,\n rawCapture: existsArtifact(artifactRoot, artifacts.raws),\n traceCapture: existsArtifact(artifactRoot, artifacts.traces),\n noStubRows: inputTokens + outputTokens > 0,\n priced: costUsd > 0,\n profileMaterialized: Boolean(record.agentProfile?.cellId),\n },\n artifacts,\n }\n return validateProductBenchmarkRecord(product)\n}\n\n/** One record per arm id, failing loud when records sharing an arm id\n * disagree on any attribute the manifest arm carries (profile, model,\n * backend, harness, reasoning effort) — an id-only dedup would silently\n * keep one policy and misrepresent the rest. */\nfunction uniqueArmRecords(records: readonly ProductBenchmarkRecord[]): ProductBenchmarkRecord[] {\n const byArm = new Map<string, ProductBenchmarkRecord>()\n for (const record of records) {\n const prior = byArm.get(record.armId)\n if (!prior) {\n byArm.set(record.armId, record)\n continue\n }\n const fields = [\n ['profileId', prior.agentProfile.id, record.agentProfile.id],\n ['model', prior.agentProfile.resolved.model, record.agentProfile.resolved.model],\n ['backend', prior.agentProfile.resolved.backend, record.agentProfile.resolved.backend],\n ['harness', prior.agentProfile.resolved.harness, record.agentProfile.resolved.harness],\n [\n 'reasoningEffort',\n prior.agentProfile.resolved.reasoningEffort,\n record.agentProfile.resolved.reasoningEffort,\n ],\n ] as const\n for (const [name, a, b] of fields) {\n if (a !== b) {\n throw new ValidationError(\n `records for arm '${record.armId}' disagree on ${name} (${String(a)} vs ${String(b)}) — one arm id must map to one policy`,\n )\n }\n }\n }\n return [...byArm.values()]\n}\n\n/** One record per scenario id, failing loud on a divergent split — the\n * manifest scenario carries one split, so two records disagreeing would be\n * silently misfiled. */\nfunction uniqueScenarioRecords(\n records: readonly ProductBenchmarkRecord[],\n): ProductBenchmarkRecord[] {\n const byScenario = new Map<string, ProductBenchmarkRecord>()\n for (const record of records) {\n const prior = byScenario.get(record.scenarioId)\n if (!prior) {\n byScenario.set(record.scenarioId, record)\n continue\n }\n if (prior.split !== record.split) {\n throw new ValidationError(\n `records for scenario '${record.scenarioId}' disagree on split (${prior.split} vs ${record.split})`,\n )\n }\n }\n return [...byScenario.values()]\n}\n\n/** Derive the bundle manifest from already-normalized records. */\nexport function buildProductBenchmarkManifest(\n records: readonly ProductBenchmarkRecord[],\n options: Pick<\n ProductBenchmarkExportOptions,\n 'outDir' | 'projectId' | 'benchmarkId' | 'scenarioTagPrefix' | 'mutableSurfaces' | 'substrate'\n >,\n): ProductBenchmarkManifest {\n if (records.length === 0) {\n throw new ValidationError('cannot build a product benchmark manifest from zero records')\n }\n const scenarioTagPrefix = options.scenarioTagPrefix ?? defaultScenarioTagPrefix(options.projectId)\n const mutableSurfaces = options.mutableSurfaces ?? productBenchmarkMutableSurfaces\n const byProfile = new Map<string, ProductBenchmarkManifest['profiles'][number]>()\n for (const record of records) {\n byProfile.set(record.agentProfile.id, {\n id: record.agentProfile.id,\n profileHash: record.agentProfile.hash,\n agentProfilePath: record.agentProfile.path,\n })\n }\n const manifest: ProductBenchmarkManifest = {\n schemaVersion: 1,\n projectId: options.projectId,\n benchmarkId: options.benchmarkId,\n repo: productBenchmarkRepoIdentity(),\n substrate: {\n agentEval: packageVersion('@tangle-network/agent-eval'),\n agentRuntime: packageVersion('@tangle-network/agent-runtime'),\n agentInterface: packageVersion('@tangle-network/agent-interface'),\n sandbox: packageVersion('@tangle-network/sandbox'),\n ...options.substrate,\n },\n profiles: [...byProfile.values()],\n arms: uniqueArmRecords(records).map((record) => ({\n id: record.armId,\n profileId: record.agentProfile.id,\n mutableSurfaces: [...mutableSurfaces],\n policyAxes: {\n carrier: record.armId.includes('policy') ? 'resource-file' : 'profile',\n model: record.agentProfile.resolved.model,\n backend: record.agentProfile.resolved.backend,\n harness: record.agentProfile.resolved.harness,\n ...(record.agentProfile.resolved.reasoningEffort !== undefined\n ? { reasoningEffort: record.agentProfile.resolved.reasoningEffort }\n : {}),\n },\n })),\n scenarios: uniqueScenarioRecords(records).map((record) => ({\n id: record.scenarioId,\n split: record.split,\n tags: [scenarioTagPrefix, options.benchmarkId, record.split],\n sourceAllowedForSynthesis: false,\n })),\n budgets: {\n maxUsd: records.reduce((sum, record) => sum + record.usage.costUsd, 0),\n maxCells: records.length,\n maxWallMs: records.reduce((sum, record) => sum + record.usage.wallMs, 0),\n },\n expectedArtifactDir: resolve(options.outDir),\n }\n return validateProductBenchmarkManifest(manifest)\n}\n\n// ── Entry points ─────────────────────────────────────────────────────\n\n/** Single-run convenience wrapper over `exportProductBenchmarkRuns`. */\nexport function exportProductBenchmark(\n options: ProductBenchmarkSingleRunExportOptions,\n): ProductBenchmarkExportResult {\n const { runDir, ...rest } = options\n return exportProductBenchmarkRuns({ ...rest, runDirs: [runDir] })\n}\n\n/**\n * Export one or more product eval run dirs into a validated product\n * benchmark bundle at `outDir`. Both the manifest and every record are\n * run through the contract validators before anything is written.\n */\nexport function exportProductBenchmarkRuns(\n options: ProductBenchmarkExportOptions,\n): ProductBenchmarkExportResult {\n const opts = resolveOptions(options)\n const outDir = resolve(options.outDir)\n const runDirs = options.runDirs.map((runDir) => resolve(runDir))\n if (runDirs.length === 0) throw new ValidationError('export requires at least one run directory')\n const materialize = options.materializeSourceRuns !== false\n const rows = runDirs.flatMap((runDir) => {\n const sourceRecordsPath = join(runDir, 'records.jsonl')\n if (!existsSync(sourceRecordsPath)) throw new ValidationError(`missing ${sourceRecordsPath}`)\n const records = readRunRecords(sourceRecordsPath)\n if (records.length === 0) throw new ValidationError(`${sourceRecordsPath} is empty`)\n return records.map((record) => ({ record, runDir }))\n })\n mkdirSync(outDir, { recursive: true })\n const artifactsByRunDir = new Map<string, ProductBenchmarkRecord['artifacts']>()\n for (const [index, runDir] of runDirs.entries()) {\n artifactsByRunDir.set(\n runDir,\n materialize ? materializeRunArtifacts(runDir, outDir, index) : absoluteArtifacts(runDir),\n )\n }\n const artifactRoot = materialize ? outDir : '/'\n const normalized = rows.map(({ record, runDir }) =>\n runRecordToProductBenchmarkRecord(\n record,\n runDir,\n artifactRoot,\n artifactsByRunDir.get(runDir)!,\n { ...options, runDirs, backendVersion: opts.backendVersion },\n ),\n )\n const manifest = buildProductBenchmarkManifest(normalized, {\n outDir,\n projectId: opts.projectId,\n benchmarkId: opts.benchmarkId,\n scenarioTagPrefix: opts.scenarioTagPrefix,\n mutableSurfaces: opts.mutableSurfaces,\n ...(options.substrate !== undefined ? { substrate: options.substrate } : {}),\n })\n const manifestPath = join(outDir, 'product-benchmark-manifest.json')\n const recordsPath = join(outDir, 'product-benchmark-records.jsonl')\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n writeFileSync(recordsPath, `${normalized.map((record) => JSON.stringify(record)).join('\\n')}\\n`)\n return { manifestPath, recordsPath, records: normalized.length }\n}\n\nfunction defaultScenarioTagPrefix(projectId: string): string {\n return projectId.replace(/-agent$/, '') || projectId\n}\n\nfunction resolveOptions(\n options: ProductBenchmarkExportOptions | ProductBenchmarkSingleRunExportOptions,\n): ResolvedExportOptions {\n return {\n projectId: options.projectId,\n benchmarkId: options.benchmarkId,\n agentProfilePath: options.agentProfilePath,\n passThreshold: options.passThreshold ?? 0.7,\n scenarioTagPrefix: options.scenarioTagPrefix ?? defaultScenarioTagPrefix(options.projectId),\n ...(options.fallbackProfileId !== undefined\n ? { fallbackProfileId: options.fallbackProfileId }\n : {}),\n mutableSurfaces: options.mutableSurfaces ?? productBenchmarkMutableSurfaces,\n ...(options.classifySplit !== undefined ? { classifySplit: options.classifySplit } : {}),\n ...(options.toolCallFallback !== undefined\n ? { toolCallFallback: options.toolCallFallback }\n : {}),\n backendVersion: options.backendVersion ?? packageVersion('@tangle-network/sandbox'),\n }\n}\n","import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { ValidationError } from '../errors'\nimport { FAILURE_CLASSES, type FailureClass } from '../trace/schema'\n\nexport const productBenchmarkSplits = ['practice', 'dev', 'holdout', 'safety', 'sentinel'] as const\n\nexport type ProductBenchmarkSplit = (typeof productBenchmarkSplits)[number]\n\nexport interface ProductBenchmarkRepoRef {\n readonly url: string\n readonly commit: string\n readonly branch: string\n}\n\nexport interface ProductBenchmarkSubstrateVersions {\n readonly agentEval: string\n readonly agentRuntime: string\n readonly agentInterface: string\n readonly sandbox: string\n readonly agentBench?: string\n}\n\nexport interface ProductBenchmarkProfileRef {\n readonly id: string\n readonly profileHash: string\n readonly agentProfilePath: string\n}\n\nexport interface ProductBenchmarkArm {\n readonly id: string\n readonly profileId: string\n readonly mutableSurfaces: readonly string[]\n readonly policyAxes: Record<string, unknown>\n}\n\nexport interface ProductBenchmarkScenario {\n readonly id: string\n readonly split: ProductBenchmarkSplit\n readonly tags: readonly string[]\n readonly sourceAllowedForSynthesis: boolean\n}\n\nexport interface ProductBenchmarkBudgets {\n readonly maxUsd: number\n readonly maxCells: number\n readonly maxWallMs: number\n}\n\nexport interface ProductBenchmarkManifest {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly repo: ProductBenchmarkRepoRef\n readonly substrate: ProductBenchmarkSubstrateVersions\n readonly profiles: readonly ProductBenchmarkProfileRef[]\n readonly arms: readonly ProductBenchmarkArm[]\n readonly scenarios: readonly ProductBenchmarkScenario[]\n readonly budgets: ProductBenchmarkBudgets\n readonly expectedArtifactDir: string\n}\n\nexport interface AgentProfileRuntimeReceipt {\n readonly model: string\n readonly harness: string\n readonly backend: string\n readonly reasoningEffort?: string\n}\n\nexport type RuntimeResolution = AgentProfileRuntimeReceipt\n\nexport interface ProductBenchmarkRecord {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly runId: string\n readonly scenarioId: string\n readonly split: ProductBenchmarkSplit\n readonly armId: string\n readonly rep: number\n readonly agentProfile: {\n readonly id: string\n readonly hash: string\n readonly path: string\n readonly declared: RuntimeResolution\n readonly resolved: RuntimeResolution\n }\n readonly model: {\n readonly provider: string\n readonly id: string\n }\n readonly backend: {\n readonly kind: string\n readonly version: string\n }\n readonly outcome: {\n readonly pass: boolean\n readonly score: number\n readonly dimensions: Record<string, number>\n readonly failureClass: Exclude<FailureClass, 'success'> | null\n readonly failureDetail: string | null\n }\n readonly usage: {\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly toolCalls: number\n }\n readonly integrity: {\n readonly realBackend: boolean\n readonly rawCapture: boolean\n readonly traceCapture: boolean\n readonly noStubRows: boolean\n readonly priced: boolean\n readonly profileMaterialized: boolean\n }\n readonly artifacts: {\n readonly records: string\n readonly traces: string\n readonly raws: string\n readonly scores: string\n readonly workspace: string\n }\n}\n\nexport interface ProductBenchmarkRunInput {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly artifactRoot?: string\n readonly checkArtifacts?: boolean\n}\n\nexport interface ProductBenchmarkValidationReport {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly records: number\n /** Manifest repo fields that are empty or the `'unknown'` export sentinel. */\n readonly repoFailures: readonly string[]\n /** Manifest substrate versions that are empty or the `'unknown'` export\n * sentinel — a bundle without substrate identity is not reproducible. */\n readonly substrateFailures: readonly string[]\n readonly projects: readonly string[]\n readonly benchmarks: readonly string[]\n readonly arms: readonly string[]\n readonly scenarios: readonly string[]\n readonly passed: number\n readonly failed: number\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly integrityFailures: readonly string[]\n readonly missingArtifacts: readonly string[]\n}\n\nexport interface ProductBenchmarkArtifactPaths {\n readonly manifestPath: string\n readonly recordsPath: string\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction fail(path: string, message: string): never {\n throw new ValidationError(`${path}: ${message}`)\n}\n\nfunction wrapValidationError(path: string, err: unknown): never {\n if (err instanceof ValidationError) {\n throw new ValidationError(`${path}: ${err.message}`, { cause: err })\n }\n throw new ValidationError(`${path}: ${err instanceof Error ? err.message : String(err)}`, {\n cause: err,\n })\n}\n\nfunction expectObject(value: unknown, path: string): Record<string, unknown> {\n if (!isObject(value)) fail(path, 'must be an object')\n return value\n}\n\nfunction expectString(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.trim().length === 0)\n fail(path, 'must be a non-empty string')\n return value\n}\n\nfunction expectFailureClass(value: unknown, path: string): Exclude<FailureClass, 'success'> {\n const parsed = expectString(value, path)\n if (parsed === 'success' || !FAILURE_CLASSES.includes(parsed as FailureClass)) {\n fail(path, `expected a non-success FailureClass, received ${JSON.stringify(parsed)}`)\n }\n return parsed as Exclude<FailureClass, 'success'>\n}\n\nfunction expectBoolean(value: unknown, path: string): boolean {\n if (typeof value !== 'boolean') fail(path, 'must be a boolean')\n return value\n}\n\nfunction expectNumber(\n value: unknown,\n path: string,\n opts: { readonly min?: number; readonly max?: number; readonly integer?: boolean } = {},\n): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) fail(path, 'must be a finite number')\n if (opts.integer && !Number.isInteger(value)) fail(path, 'must be an integer')\n if (opts.min !== undefined && value < opts.min) fail(path, `must be >= ${opts.min}`)\n if (opts.max !== undefined && value > opts.max) fail(path, `must be <= ${opts.max}`)\n return value\n}\n\nfunction expectStringArray(value: unknown, path: string): string[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectString(entry, `${path}[${index}]`))\n}\n\nfunction expectObjectArray(value: unknown, path: string): Record<string, unknown>[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectObject(entry, `${path}[${index}]`))\n}\n\nfunction expectSplit(value: unknown, path: string): ProductBenchmarkSplit {\n const split = expectString(value, path)\n if (!productBenchmarkSplits.includes(split as ProductBenchmarkSplit)) {\n fail(path, `must be one of ${productBenchmarkSplits.join(', ')}`)\n }\n return split as ProductBenchmarkSplit\n}\n\nfunction optionalString(value: unknown, path: string): string | undefined {\n if (value === undefined) return undefined\n return expectString(value, path)\n}\n\nfunction expectDimensions(value: unknown, path: string): Record<string, number> {\n const obj = expectObject(value, path)\n const out: Record<string, number> = {}\n for (const [key, raw] of Object.entries(obj)) out[key] = expectNumber(raw, `${path}.${key}`)\n return out\n}\n\nfunction expectRuntimeResolution(value: unknown, path: string): RuntimeResolution {\n const obj = expectObject(value, path)\n return {\n model: expectString(obj.model, `${path}.model`),\n harness: expectString(obj.harness, `${path}.harness`),\n backend: expectString(obj.backend, `${path}.backend`),\n ...(obj.reasoningEffort !== undefined\n ? { reasoningEffort: optionalString(obj.reasoningEffort, `${path}.reasoningEffort`) }\n : {}),\n }\n}\n\nexport function validateProductBenchmarkManifest(value: unknown): ProductBenchmarkManifest {\n const obj = expectObject(value, 'manifest')\n if (obj.schemaVersion !== 1) fail('manifest.schemaVersion', 'must be 1')\n const repo = expectObject(obj.repo, 'manifest.repo')\n const substrate = expectObject(obj.substrate, 'manifest.substrate')\n const profiles = expectObjectArray(obj.profiles, 'manifest.profiles').map((profile, index) => ({\n id: expectString(profile.id, `manifest.profiles[${index}].id`),\n profileHash: expectString(profile.profileHash, `manifest.profiles[${index}].profileHash`),\n agentProfilePath: expectString(\n profile.agentProfilePath,\n `manifest.profiles[${index}].agentProfilePath`,\n ),\n }))\n const arms = expectObjectArray(obj.arms, 'manifest.arms').map((arm, index) => ({\n id: expectString(arm.id, `manifest.arms[${index}].id`),\n profileId: expectString(arm.profileId, `manifest.arms[${index}].profileId`),\n mutableSurfaces: expectStringArray(\n arm.mutableSurfaces,\n `manifest.arms[${index}].mutableSurfaces`,\n ),\n policyAxes: expectObject(arm.policyAxes, `manifest.arms[${index}].policyAxes`),\n }))\n const scenarios = expectObjectArray(obj.scenarios, 'manifest.scenarios').map(\n (scenario, index) => ({\n id: expectString(scenario.id, `manifest.scenarios[${index}].id`),\n split: expectSplit(scenario.split, `manifest.scenarios[${index}].split`),\n tags: expectStringArray(scenario.tags, `manifest.scenarios[${index}].tags`),\n sourceAllowedForSynthesis: expectBoolean(\n scenario.sourceAllowedForSynthesis,\n `manifest.scenarios[${index}].sourceAllowedForSynthesis`,\n ),\n }),\n )\n const budgets = expectObject(obj.budgets, 'manifest.budgets')\n if (profiles.length === 0) fail('manifest.profiles', 'must contain at least one profile')\n if (arms.length === 0) fail('manifest.arms', 'must contain at least one arm')\n if (scenarios.length === 0) fail('manifest.scenarios', 'must contain at least one scenario')\n assertUnique(\n profiles.map((profile) => profile.id),\n 'manifest.profiles.id',\n )\n assertUnique(\n arms.map((arm) => arm.id),\n 'manifest.arms.id',\n )\n assertUnique(\n scenarios.map((scenario) => scenario.id),\n 'manifest.scenarios.id',\n )\n const profileIds = new Set(profiles.map((profile) => profile.id))\n for (const arm of arms) {\n if (!profileIds.has(arm.profileId))\n fail(`manifest.arms.${arm.id}.profileId`, `unknown profile ${arm.profileId}`)\n }\n return {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'manifest.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'manifest.benchmarkId'),\n repo: {\n url: expectString(repo.url, 'manifest.repo.url'),\n commit: expectString(repo.commit, 'manifest.repo.commit'),\n branch: expectString(repo.branch, 'manifest.repo.branch'),\n },\n substrate: {\n agentEval: expectString(substrate.agentEval, 'manifest.substrate.agentEval'),\n agentRuntime: expectString(substrate.agentRuntime, 'manifest.substrate.agentRuntime'),\n agentInterface: expectString(substrate.agentInterface, 'manifest.substrate.agentInterface'),\n sandbox: expectString(substrate.sandbox, 'manifest.substrate.sandbox'),\n ...(substrate.agentBench !== undefined\n ? { agentBench: expectString(substrate.agentBench, 'manifest.substrate.agentBench') }\n : {}),\n },\n profiles,\n arms,\n scenarios,\n budgets: {\n maxUsd: expectNumber(budgets.maxUsd, 'manifest.budgets.maxUsd', { min: 0 }),\n maxCells: expectNumber(budgets.maxCells, 'manifest.budgets.maxCells', {\n min: 0,\n integer: true,\n }),\n maxWallMs: expectNumber(budgets.maxWallMs, 'manifest.budgets.maxWallMs', {\n min: 0,\n integer: true,\n }),\n },\n expectedArtifactDir: expectString(obj.expectedArtifactDir, 'manifest.expectedArtifactDir'),\n }\n}\n\nexport function validateProductBenchmarkRecord(value: unknown): ProductBenchmarkRecord {\n const obj = expectObject(value, 'record')\n if (obj.schemaVersion !== 1) fail('record.schemaVersion', 'must be 1')\n const agentProfile = expectObject(obj.agentProfile, 'record.agentProfile')\n const model = expectObject(obj.model, 'record.model')\n const backend = expectObject(obj.backend, 'record.backend')\n const outcome = expectObject(obj.outcome, 'record.outcome')\n const usage = expectObject(obj.usage, 'record.usage')\n const integrity = expectObject(obj.integrity, 'record.integrity')\n const artifacts = expectObject(obj.artifacts, 'record.artifacts')\n const outcomePass = expectBoolean(outcome.pass, 'record.outcome.pass')\n const failureClass =\n outcome.failureClass === null\n ? null\n : expectFailureClass(outcome.failureClass, 'record.outcome.failureClass')\n const failureDetail =\n outcome.failureDetail === null\n ? null\n : expectString(outcome.failureDetail, 'record.outcome.failureDetail')\n if (outcomePass && (failureClass !== null || failureDetail !== null)) {\n fail('record.outcome', 'a passing row cannot carry failure evidence')\n }\n if (!outcomePass && failureClass === null) {\n fail('record.outcome.failureClass', 'a failed row requires a failure class')\n }\n if (failureClass === null && failureDetail !== null) {\n fail('record.outcome.failureDetail', 'failure detail requires a failure class')\n }\n const record: ProductBenchmarkRecord = {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'record.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'record.benchmarkId'),\n runId: expectString(obj.runId, 'record.runId'),\n scenarioId: expectString(obj.scenarioId, 'record.scenarioId'),\n split: expectSplit(obj.split, 'record.split'),\n armId: expectString(obj.armId, 'record.armId'),\n rep: expectNumber(obj.rep, 'record.rep', { min: 1, integer: true }),\n agentProfile: {\n id: expectString(agentProfile.id, 'record.agentProfile.id'),\n hash: expectString(agentProfile.hash, 'record.agentProfile.hash'),\n path: expectString(agentProfile.path, 'record.agentProfile.path'),\n declared: expectRuntimeResolution(agentProfile.declared, 'record.agentProfile.declared'),\n resolved: expectRuntimeResolution(agentProfile.resolved, 'record.agentProfile.resolved'),\n },\n model: {\n provider: expectString(model.provider, 'record.model.provider'),\n id: expectString(model.id, 'record.model.id'),\n },\n backend: {\n kind: expectString(backend.kind, 'record.backend.kind'),\n version: expectString(backend.version, 'record.backend.version'),\n },\n outcome: {\n pass: outcomePass,\n score: expectNumber(outcome.score, 'record.outcome.score', { min: 0, max: 1 }),\n dimensions: expectDimensions(outcome.dimensions, 'record.outcome.dimensions'),\n failureClass,\n failureDetail,\n },\n usage: {\n inputTokens: expectNumber(usage.inputTokens, 'record.usage.inputTokens', {\n min: 0,\n integer: true,\n }),\n outputTokens: expectNumber(usage.outputTokens, 'record.usage.outputTokens', {\n min: 0,\n integer: true,\n }),\n costUsd: expectNumber(usage.costUsd, 'record.usage.costUsd', { min: 0 }),\n wallMs: expectNumber(usage.wallMs, 'record.usage.wallMs', { min: 0, integer: true }),\n toolCalls: expectNumber(usage.toolCalls, 'record.usage.toolCalls', { min: 0, integer: true }),\n },\n integrity: {\n realBackend: expectBoolean(integrity.realBackend, 'record.integrity.realBackend'),\n rawCapture: expectBoolean(integrity.rawCapture, 'record.integrity.rawCapture'),\n traceCapture: expectBoolean(integrity.traceCapture, 'record.integrity.traceCapture'),\n noStubRows: expectBoolean(integrity.noStubRows, 'record.integrity.noStubRows'),\n priced: expectBoolean(integrity.priced, 'record.integrity.priced'),\n profileMaterialized: expectBoolean(\n integrity.profileMaterialized,\n 'record.integrity.profileMaterialized',\n ),\n },\n artifacts: {\n records: expectString(artifacts.records, 'record.artifacts.records'),\n traces: expectString(artifacts.traces, 'record.artifacts.traces'),\n raws: expectString(artifacts.raws, 'record.artifacts.raws'),\n scores: expectString(artifacts.scores, 'record.artifacts.scores'),\n workspace: expectString(artifacts.workspace, 'record.artifacts.workspace'),\n },\n }\n if (record.integrity.realBackend && record.usage.inputTokens + record.usage.outputTokens === 0) {\n fail('record.usage', 'realBackend rows must carry non-zero token usage')\n }\n return record\n}\n\nexport function productBenchmarkIntegrityFailures(record: ProductBenchmarkRecord): string[] {\n const failures: string[] = []\n for (const [key, value] of Object.entries(record.integrity)) {\n if (!value) failures.push(`${record.runId}:${key}=false`)\n }\n return failures\n}\n\nexport function readProductBenchmarkRecords(path: string): ProductBenchmarkRecord[] {\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n const records: ProductBenchmarkRecord[] = []\n for (const [index, line] of lines.entries()) {\n try {\n records.push(validateProductBenchmarkRecord(JSON.parse(line)))\n } catch (err) {\n wrapValidationError(`${path}:${index + 1}`, err)\n }\n }\n return records\n}\n\nexport function readProductBenchmarkManifest(path: string): ProductBenchmarkManifest {\n try {\n return validateProductBenchmarkManifest(JSON.parse(readFileSync(path, 'utf8')))\n } catch (err) {\n wrapValidationError(path, err)\n }\n}\n\nexport function validateProductBenchmarkRun(\n input: ProductBenchmarkRunInput,\n): ProductBenchmarkValidationReport {\n const manifest = readProductBenchmarkManifest(input.manifestPath)\n const records = readProductBenchmarkRecords(input.recordsPath)\n const manifestProjectBench = `${manifest.projectId}/${manifest.benchmarkId}`\n const integrityFailures = records.flatMap(productBenchmarkIntegrityFailures)\n const missingArtifacts =\n input.checkArtifacts === false\n ? []\n : records.flatMap((record) =>\n missingArtifactsForRecord(record, input.artifactRoot ?? dirname(input.recordsPath)),\n )\n for (const [index, record] of records.entries()) {\n const recordProjectBench = `${record.projectId}/${record.benchmarkId}`\n if (recordProjectBench !== manifestProjectBench) {\n fail(\n `records[${index}]`,\n `project/benchmark ${recordProjectBench} does not match manifest ${manifestProjectBench}`,\n )\n }\n if (!manifest.arms.some((arm) => arm.id === record.armId))\n fail(`records[${index}].armId`, `unknown arm ${record.armId}`)\n if (!manifest.scenarios.some((scenario) => scenario.id === record.scenarioId)) {\n fail(`records[${index}].scenarioId`, `unknown scenario ${record.scenarioId}`)\n }\n }\n const repoFailures = (['url', 'commit', 'branch'] as const)\n .filter((key) => manifest.repo[key].trim().length === 0 || manifest.repo[key] === 'unknown')\n .map((key) => `manifest.repo.${key}`)\n const substrateFailures = (['agentEval', 'agentRuntime', 'agentInterface', 'sandbox'] as const)\n .filter(\n (key) => manifest.substrate[key].trim().length === 0 || manifest.substrate[key] === 'unknown',\n )\n .map((key) => `manifest.substrate.${key}`)\n return {\n manifestPath: input.manifestPath,\n recordsPath: input.recordsPath,\n records: records.length,\n repoFailures,\n substrateFailures,\n projects: sortedUnique(records.map((record) => record.projectId)),\n benchmarks: sortedUnique(records.map((record) => record.benchmarkId)),\n arms: sortedUnique(records.map((record) => record.armId)),\n scenarios: sortedUnique(records.map((record) => record.scenarioId)),\n passed: records.filter((record) => record.outcome.pass).length,\n failed: records.filter((record) => !record.outcome.pass).length,\n inputTokens: sum(records, (record) => record.usage.inputTokens),\n outputTokens: sum(records, (record) => record.usage.outputTokens),\n costUsd: sum(records, (record) => record.usage.costUsd),\n wallMs: sum(records, (record) => record.usage.wallMs),\n integrityFailures,\n missingArtifacts,\n }\n}\n\nfunction missingArtifactsForRecord(record: ProductBenchmarkRecord, artifactRoot: string): string[] {\n const missing: string[] = []\n for (const [key, value] of Object.entries(record.artifacts)) {\n const path = resolveArtifactPath(value, artifactRoot)\n if (!existsSync(path)) missing.push(`${record.runId}:${key}:${value}`)\n }\n return missing\n}\n\nfunction resolveArtifactPath(value: string, artifactRoot: string): string {\n return value.startsWith('/') ? value : join(artifactRoot, value)\n}\n\nfunction assertUnique(values: readonly string[], path: string): void {\n const seen = new Set<string>()\n for (const value of values) {\n if (seen.has(value)) fail(path, `duplicate ${value}`)\n seen.add(value)\n }\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort()\n}\n\nfunction sum<T>(items: readonly T[], fn: (item: T) => number): number {\n return items.reduce((total, item) => total + fn(item), 0)\n}\n\nexport function findProductBenchmarkArtifacts(\n runDir: string,\n): ProductBenchmarkArtifactPaths | null {\n const manifestPath = join(runDir, 'product-benchmark-manifest.json')\n const recordsPath = join(runDir, 'product-benchmark-records.jsonl')\n if (\n existsSync(manifestPath) &&\n statSync(manifestPath).isFile() &&\n existsSync(recordsPath) &&\n statSync(recordsPath).isFile()\n ) {\n return { manifestPath, recordsPath }\n }\n return null\n}\n\n/**\n * Fail-loud gate over a bundle directory: locates the manifest + records,\n * runs `validateProductBenchmarkRun`, and throws with every repo,\n * integrity, and artifact failure listed. Returns the report when clean.\n */\nexport function assertProductBenchmarkRun(runDir: string): ProductBenchmarkValidationReport {\n const artifacts = findProductBenchmarkArtifacts(runDir)\n if (!artifacts) {\n fail(runDir, 'missing product-benchmark-manifest.json or product-benchmark-records.jsonl')\n }\n const report = validateProductBenchmarkRun({ ...artifacts, artifactRoot: runDir })\n const failures = [\n ...report.repoFailures,\n ...report.substrateFailures,\n ...report.integrityFailures,\n ...report.missingArtifacts,\n ]\n if (failures.length > 0) {\n fail(runDir, `product benchmark validation failed:\\n${failures.join('\\n')}`)\n }\n return report\n}\n\nexport type {\n ProductBenchmarkExportOptions,\n ProductBenchmarkExportResult,\n ProductBenchmarkSingleRunExportOptions,\n} from './export'\nexport {\n buildProductBenchmarkManifest,\n exportProductBenchmark,\n exportProductBenchmarkRuns,\n productBenchmarkMutableSurfaces,\n productBenchmarkRepoIdentity,\n runRecordToProductBenchmarkRecord,\n} from './export'\n","import type { RunSplitTag } from './run-record'\n\nexport interface RuntimeTrajectoryHookEvent {\n id: string\n runId: string\n scenarioId?: string\n target: string\n phase: string\n timestamp: number\n stepIndex?: number\n parentId?: string\n payload?: unknown\n metadata?: Record<string, unknown>\n}\n\nexport interface RuntimeTrajectoryRecord {\n id?: string\n scenarioId?: string\n splitTag?: RunSplitTag\n runtimeEvents?: unknown\n [key: string]: unknown\n}\n\nexport interface RuntimeTrajectoryRunRecord {\n runId: string\n scenarioId?: string\n splitTag: RunSplitTag\n}\n\nexport interface RuntimeTrajectoryEvidenceSummary {\n recordCount: number\n recordWithRuntimeEventsCount: number\n runtimeRunCount: number\n lifecycleEventCount: number\n defaultedSplitCount: number\n}\n\nexport interface RuntimeTrajectoryEvidenceProjection {\n runs: RuntimeTrajectoryRunRecord[]\n events: RuntimeTrajectoryHookEvent[]\n summary: RuntimeTrajectoryEvidenceSummary\n diagnostics: string[]\n}\n\nexport interface ProjectRuntimeTrajectoryEvidenceOptions<\n TRecord extends RuntimeTrajectoryRecord = RuntimeTrajectoryRecord,\n> {\n records: TRecord[]\n defaultSplitTag?: RunSplitTag\n recordIdOf?: (record: TRecord, index: number) => string | undefined\n scenarioIdOf?: (record: TRecord, index: number) => string | undefined\n}\n\nconst DEFAULT_SPLIT_TAG: RunSplitTag = 'search'\n\nexport function projectRuntimeTrajectoryEvidence<TRecord extends RuntimeTrajectoryRecord>(\n options: ProjectRuntimeTrajectoryEvidenceOptions<TRecord>,\n): RuntimeTrajectoryEvidenceProjection {\n const diagnostics: string[] = []\n const runsById = new Map<string, RuntimeTrajectoryRunRecord>()\n const events: RuntimeTrajectoryHookEvent[] = []\n let recordWithRuntimeEventsCount = 0\n let defaultedSplitCount = 0\n\n for (let recordIndex = 0; recordIndex < options.records.length; recordIndex += 1) {\n const record = options.records[recordIndex]!\n const key = runtimeTrajectoryRecordKey(record, recordIndex, options.recordIdOf)\n const splitTag = record.splitTag ?? options.defaultSplitTag ?? DEFAULT_SPLIT_TAG\n if (record.splitTag === undefined) defaultedSplitCount += 1\n\n const rawEvents = record.runtimeEvents\n if (!Array.isArray(rawEvents)) {\n diagnostics.push(\n `${key}: runtimeEvents is not an array; no runtime run join can be extracted`,\n )\n continue\n }\n if (rawEvents.length === 0) {\n diagnostics.push(`${key}: no runtimeEvents; no runtime run join can be extracted`)\n continue\n }\n recordWithRuntimeEventsCount += 1\n\n for (let index = 0; index < rawEvents.length; index += 1) {\n const event = parseRuntimeTrajectoryHookEvent(rawEvents[index])\n if (!event) {\n diagnostics.push(`${key}: runtimeEvents[${index}] is not a RuntimeHookEvent`)\n continue\n }\n events.push(event)\n\n const scenarioId =\n event.scenarioId ??\n stringOrUndefined(options.scenarioIdOf?.(record, recordIndex)) ??\n stringOrUndefined(record.scenarioId)\n const prior = runsById.get(event.runId)\n if (!prior) {\n runsById.set(event.runId, { runId: event.runId, scenarioId, splitTag })\n continue\n }\n if (prior.scenarioId !== scenarioId || prior.splitTag !== splitTag) {\n diagnostics.push(`${key}: runId ${event.runId} has conflicting scenario/split metadata`)\n }\n }\n }\n\n const runs = [...runsById.values()]\n return {\n runs,\n events,\n summary: {\n recordCount: options.records.length,\n recordWithRuntimeEventsCount,\n runtimeRunCount: runs.length,\n lifecycleEventCount: events.length,\n defaultedSplitCount,\n },\n diagnostics,\n }\n}\n\nfunction parseRuntimeTrajectoryHookEvent(input: unknown): RuntimeTrajectoryHookEvent | null {\n if (!isRecord(input)) return null\n if (typeof input.id !== 'string' || input.id.length === 0) return null\n if (typeof input.runId !== 'string' || input.runId.length === 0) return null\n if (typeof input.target !== 'string' || input.target.length === 0) return null\n if (typeof input.phase !== 'string' || input.phase.length === 0) return null\n if (typeof input.timestamp !== 'number' || !Number.isFinite(input.timestamp)) return null\n\n return {\n id: input.id,\n runId: input.runId,\n scenarioId: stringOrUndefined(input.scenarioId),\n target: input.target,\n phase: input.phase,\n timestamp: input.timestamp,\n stepIndex: finiteNumberOrUndefined(input.stepIndex),\n parentId: stringOrUndefined(input.parentId),\n payload: input.payload,\n metadata: isRecord(input.metadata) ? { ...input.metadata } : undefined,\n }\n}\n\nfunction runtimeTrajectoryRecordKey<TRecord extends RuntimeTrajectoryRecord>(\n record: TRecord,\n index: number,\n recordIdOf?: (record: TRecord, index: number) => string | undefined,\n): string {\n return (\n stringOrUndefined(recordIdOf?.(record, index)) ??\n stringOrUndefined(record.id) ??\n `record[${index}]`\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction stringOrUndefined(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction finiteNumberOrUndefined(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n","import type { FeedbackLabel, ProposedSideEffect } from './feedback-trajectory'\n\nexport interface ActionExecutionPolicy {\n allowedTypes?: string[]\n blockedTypes?: string[]\n alwaysRequireApprovalTypes?: string[]\n autoApproveTypes?: string[]\n requireApprovalForExternalSideEffects?: boolean\n requireApprovalAboveCostUsd?: number\n maxActionCostUsd?: number\n remainingBudgetUsd?: number\n expectedOutcomeRequired?: boolean\n killCriteriaRequired?: boolean\n}\n\nexport interface ActionPolicyDecision {\n allowed: boolean\n blocked: boolean\n requiresApproval: boolean\n reasons: string[]\n label?: FeedbackLabel\n}\n\nexport function evaluateActionPolicy(\n action: ProposedSideEffect,\n policy: ActionExecutionPolicy = {},\n options: { createdAt?: string } = {},\n): ActionPolicyDecision {\n const reasons: string[] = []\n let blocked = false\n let requiresApproval = Boolean(action.requiresApproval)\n\n if (policy.allowedTypes?.length && !policy.allowedTypes.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is not allowed`)\n }\n if (policy.blockedTypes?.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is blocked`)\n }\n if (policy.alwaysRequireApprovalTypes?.includes(action.type)) {\n requiresApproval = true\n reasons.push(`action type \"${action.type}\" requires approval`)\n }\n if (policy.requireApprovalForExternalSideEffects && action.externalSideEffect) {\n requiresApproval = true\n reasons.push('external side effect requires approval')\n }\n if (\n policy.requireApprovalAboveCostUsd !== undefined &&\n (action.costUsd ?? 0) > policy.requireApprovalAboveCostUsd\n ) {\n requiresApproval = true\n reasons.push(\n `cost ${action.costUsd} exceeds approval threshold ${policy.requireApprovalAboveCostUsd}`,\n )\n }\n if (policy.maxActionCostUsd !== undefined && (action.costUsd ?? 0) > policy.maxActionCostUsd) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds max action cost ${policy.maxActionCostUsd}`)\n }\n if (\n policy.remainingBudgetUsd !== undefined &&\n (action.costUsd ?? 0) > policy.remainingBudgetUsd\n ) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds remaining budget ${policy.remainingBudgetUsd}`)\n }\n if (policy.expectedOutcomeRequired && !action.metadata?.expectedOutcome) {\n blocked = true\n reasons.push('expected outcome is required')\n }\n if (policy.killCriteriaRequired && !action.metadata?.killCriteria) {\n blocked = true\n reasons.push('kill criteria are required')\n }\n if (policy.autoApproveTypes?.includes(action.type) && requiresApproval) {\n reasons.push(\n `action type \"${action.type}\" is auto-approved only when no approval policy applies`,\n )\n }\n\n if (!reasons.length) reasons.push(requiresApproval ? 'approval required' : 'action allowed')\n\n const label =\n blocked || requiresApproval\n ? {\n source: 'policy' as const,\n kind: blocked ? ('policy_block' as const) : ('comment' as const),\n value: { actionType: action.type, blocked, requiresApproval },\n reason: reasons.join('; '),\n severity: blocked ? ('critical' as const) : ('warning' as const),\n createdAt: options.createdAt ?? new Date().toISOString(),\n metadata: { action, policy },\n }\n : undefined\n\n return {\n allowed: !blocked,\n blocked,\n requiresApproval: !blocked && requiresApproval,\n reasons,\n label,\n }\n}\n","/**\n * Deploy gate layer — would the agent's build actually publish?\n *\n * The product Blueprint Agent fronts promises \"go from idea to live URL.\"\n * Pre-Gen-48 the eval stopped at install/typecheck/build/serve — every\n * one of which can pass while `vite build` (or `next build`, etc) fails\n * on a production-only constraint (env-var requirement, dynamic import\n * not statically resolvable, missing public asset).\n *\n * Deploy gate runs the production build via the supplied {@link DeployRunner}\n * and asserts:\n * - command exited 0\n * - artifact dir contains an entry point (index.html for static SPAs,\n * equivalent per framework family)\n *\n * Ships with a canonical `vite` runner. Additional runners\n * (wrangler-deploy --dry-run, next-build, etc.) plug in as factories.\n */\n\nimport type { Layer, LayerResult } from './multi-layer-verifier'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport type DeployFamily = 'frontend-static' | 'nextjs' | 'remix' | 'fullstack-ts'\n\nexport interface DeployRunResult {\n ok: boolean\n /** Stdout/stderr tail surfaced as evidence. Bounded in caller. */\n output?: string\n /** Wall-clock duration of the build command. */\n durationMs?: number\n /** Path to artifact directory the runner expects (dist/, .next/, build/, etc). */\n artifactDir?: string\n /** True iff artifactDir contains the family's expected entry point. */\n artifactValid?: boolean\n}\n\nexport interface DeployRunner {\n /** Run the production build. The runner owns command + cwd. */\n run(): Promise<DeployRunResult>\n}\n\nexport interface DeployGateLayerInput {\n /** Build the runner per call. */\n runner: () => DeployRunner | Promise<DeployRunner>\n /** Family hint — for logging, surfaced in diagnostics. */\n family?: DeployFamily\n /** Layer name. Default `deploy`. */\n name?: string\n /** Layer dependencies — default `['build']`. */\n dependsOn?: string[]\n /** Weight in blendedScore. Default 1. */\n weight?: number\n /** Cap (ms). Default 120s — prod builds are slower than dev. */\n capMs?: number\n /** When true, treat artifactValid=false as a fail (default true). */\n requireArtifact?: boolean\n}\n\n// ─── Layer factory ──────────────────────────────────────────────────────\n\n/**\n * Build a deploy gate layer that runs the production build and verifies\n * the artifact. Pass: ok && artifactValid. Score: 1.0 (pass) or 0 (fail).\n *\n * For families where artifact-validation isn't applicable (e.g. a\n * server-rendered build that prints a manifest), set `requireArtifact:\n * false` and rely on the runner's own ok signal.\n */\nexport function deployGateLayer<Env = unknown>(input: DeployGateLayerInput): Layer<Env> {\n const requireArtifact = input.requireArtifact ?? true\n return {\n name: input.name ?? 'deploy',\n dependsOn: input.dependsOn ?? ['build'],\n weight: input.weight ?? 1,\n capMs: input.capMs ?? 120_000,\n run: async (ctx) => {\n const start = Date.now()\n let runner: DeployRunner\n try {\n runner = await input.runner()\n } catch (err) {\n return {\n layer: input.name ?? 'deploy',\n status: 'error',\n durationMs: Date.now() - start,\n findings: [\n {\n severity: 'major',\n message: `deploy runner failed to start: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n reason: 'runner-init-failed',\n }\n }\n let result: DeployRunResult\n try {\n result = await runner.run()\n } catch (err) {\n return {\n layer: input.name ?? 'deploy',\n status: 'error',\n durationMs: Date.now() - start,\n findings: [\n {\n severity: 'major',\n message: `deploy command threw: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n reason: 'runner-throw',\n }\n }\n if (ctx.signal.aborted) {\n return {\n layer: input.name ?? 'deploy',\n status: 'timeout',\n durationMs: Date.now() - start,\n findings: [],\n reason: 'aborted by overall cap',\n }\n }\n\n const artifactOk = !requireArtifact || result.artifactValid === true\n const pass = result.ok && artifactOk\n const findings: LayerResult['findings'] = []\n if (!result.ok) {\n findings.push({\n severity: 'critical',\n message: 'deploy build exited non-zero',\n evidence: (result.output ?? '').slice(-1200),\n })\n }\n if (result.ok && requireArtifact && !result.artifactValid) {\n findings.push({\n severity: 'major',\n message: `deploy build succeeded but artifact ${result.artifactDir ?? '(unknown)'} is invalid or empty`,\n })\n }\n return {\n layer: input.name ?? 'deploy',\n status: pass ? 'pass' : 'fail',\n score: pass ? 1 : 0,\n durationMs: Date.now() - start,\n findings,\n reason: pass\n ? `deploy build OK${input.family ? ` (${input.family})` : ''}${result.artifactDir ? ` → ${result.artifactDir}` : ''}`\n : !result.ok\n ? 'build command failed'\n : 'artifact missing or invalid',\n diagnostics: {\n deployBuildOk: result.ok ? 1 : 0,\n deployArtifactOk: result.artifactValid === true ? 1 : 0,\n deployBuildMs: result.durationMs ?? null,\n },\n }\n },\n }\n}\n\n// ─── Canonical vite runner ──────────────────────────────────────────────\n\nexport interface ViteDeployRunnerInput {\n /** Workdir to build. The runner cd's here. */\n workdir: string\n /**\n * Function to run a shell command in `workdir`. Same shape as\n * agent-eval's CommandRunner.run for compositional reuse.\n */\n exec: (\n cmd: string,\n opts?: { cwd?: string; timeoutMs?: number },\n ) => Promise<{ stdout: string; stderr: string; exitCode: number }>\n /**\n * Function to test whether a path exists in the workdir. Inject\n * `(p) => existsSync(join(workdir, p))` for host runs.\n */\n exists: (relativePath: string) => boolean | Promise<boolean>\n /** Build command. Default `npm run build`. */\n buildCommand?: string\n /** Artifact directory to validate. Default `dist`. */\n artifactDir?: string\n /** Entry-point file under artifactDir. Default `index.html`. */\n artifactEntry?: string\n /** Per-build cap (ms). Default 90s. */\n timeoutMs?: number\n}\n\n/**\n * Canonical runner for `frontend-static` family — runs the build script,\n * validates `<artifactDir>/<artifactEntry>` exists. Use as the `runner:`\n * factory for {@link deployGateLayer}.\n */\nexport function viteDeployRunner(input: ViteDeployRunnerInput): DeployRunner {\n return {\n run: async () => {\n const start = Date.now()\n const cmd = input.buildCommand ?? 'npm run build'\n const artifactDir = input.artifactDir ?? 'dist'\n const artifactEntry = input.artifactEntry ?? 'index.html'\n const timeoutMs = input.timeoutMs ?? 90_000\n const result = await input.exec(cmd, { cwd: input.workdir, timeoutMs })\n const ok = result.exitCode === 0\n let artifactValid = false\n try {\n const entryExists = await input.exists(`${artifactDir}/${artifactEntry}`)\n artifactValid = ok && Boolean(entryExists)\n } catch {\n artifactValid = false\n }\n const tail = ((result.stderr || result.stdout) ?? '').slice(-1500)\n return {\n ok,\n output: tail,\n durationMs: Date.now() - start,\n artifactDir,\n artifactValid,\n }\n },\n }\n}\n\n// ─── Canonical wrangler runner ──────────────────────────────────────────\n\nexport interface WranglerDeployRunnerInput {\n workdir: string\n exec: (\n cmd: string,\n opts?: { cwd?: string; timeoutMs?: number },\n ) => Promise<{ stdout: string; stderr: string; exitCode: number }>\n exists: (relativePath: string) => boolean | Promise<boolean>\n /** Build command. Default `npm run build`. */\n buildCommand?: string\n /** Wrangler dry-run command. Default `npx wrangler deploy --dry-run --outdir dist`. */\n dryRunCommand?: string\n /** Per-step cap (ms). Default 120s. */\n timeoutMs?: number\n}\n\n/**\n * Canonical runner for the `fullstack-ts` family on Cloudflare Workers\n * (Remix / React Router v7 / Hono on Workers). Detects wrangler.toml or\n * wrangler.jsonc in the workdir, builds, then `wrangler deploy --dry-run`\n * to catch missing bindings, syntax errors in wrangler config, and\n * import-time crashes that don't surface in `tsc`.\n *\n * No wrangler config = skip with \"no wrangler\" evidence (not a failure\n * — the gate caller decides whether to require deploy validation).\n */\nexport function wranglerDeployRunner(input: WranglerDeployRunnerInput): DeployRunner {\n return {\n run: async () => {\n const start = Date.now()\n const buildCmd = input.buildCommand ?? 'npm run build'\n const dryCmd = input.dryRunCommand ?? 'npx wrangler deploy --dry-run --outdir dist'\n const timeoutMs = input.timeoutMs ?? 120_000\n\n const hasToml = await input.exists('wrangler.toml')\n const hasJsonc = hasToml ? false : await input.exists('wrangler.jsonc')\n if (!hasToml && !hasJsonc) {\n return {\n ok: false,\n output: 'no wrangler config found (wrangler.toml / wrangler.jsonc absent)',\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const build = await input.exec(buildCmd, { cwd: input.workdir, timeoutMs })\n if (build.exitCode !== 0) {\n const tail = ((build.stderr || build.stdout) ?? '').slice(-1500)\n return {\n ok: false,\n output: `build failed: ${tail}`,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const dry = await input.exec(dryCmd, { cwd: input.workdir, timeoutMs })\n if (dry.exitCode !== 0) {\n const tail = ((dry.stderr || dry.stdout) ?? '').slice(-1500)\n return {\n ok: false,\n output: `wrangler dry-run failed: ${tail}`,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: false,\n }\n }\n\n const tail = ((dry.stdout || dry.stderr) ?? '').slice(-1500)\n return {\n ok: true,\n output: tail,\n durationMs: Date.now() - start,\n artifactDir: 'dist',\n artifactValid: true,\n }\n },\n }\n}\n","/**\n * HeldOutGate — first-class held-out paired-delta promotion gate.\n *\n * Encodes the \"honesty override\" pattern that lived inline in\n * `~/webb/redteam/scripts/agent-eval-autoresearch.ts:138–171`.\n * The optimizer's best-guess is one thing; what we should actually\n * ship is another. The gate is the line between them.\n *\n * A candidate is promoted iff ALL FOUR pass:\n *\n * 0. **Coverage**: on BOTH splits, the fraction of DEALT work items that\n * carry a real score on BOTH arms is at least `minCoverage`\n * (default 1 — all of them). See \"Missing scores are missing data\".\n * 1. **Productive runs**: the candidate has at least\n * `minProductiveRuns` paired observations on items where BOTH\n * candidate and baseline produced a real (non-silent) score.\n * 2. **Paired delta**: the lower bound of the CI on the per-item\n * holdout delta (candidate − baseline) is strictly greater than\n * `pairedDeltaThreshold`. WHICH paired statistic carries that CI\n * depends on the outcome's shape — see \"Choosing the statistic\".\n * 3. **Overfit gap**: the candidate's gap between search-split\n * score and holdout-split score is no worse (more positive)\n * than the baseline's gap by more than `overfitGapThreshold`.\n * \"Better on search, worse on holdout\" is the canonical\n * overfit pattern; this catches it.\n *\n * ## Missing scores are missing data\n *\n * Gates 1-3 all read numbers off the items where BOTH arms produced a finite\n * score. Without gate 0 that set is a SILENT FILTER: an item the candidate\n * crashed on, timed out on, or never wrote a row for simply left the\n * comparison, and the verdict was computed over whatever survived. Measured on\n * the pre-0.134 gate: 26 held-out items, a candidate that produced no score at\n * all on 20 of them, promoted at every threshold from −0.05 to +0.30 on the 6\n * it answered (`unpairedBaselineRuns: 20` sat in the evidence, read by\n * nothing); the control — the same 20 failures scored as the 0 they earned —\n * was correctly refused at a mean paired delta of −0.3808. An agent that fails\n * 77% of its tasks was promoted, and every guarantee gates 1-3 provide sat\n * behind that filter.\n *\n * The gate does NOT impute a value for those items. It cannot: it does not know\n * the failure value of the caller's metric (0 on [0,1]? 0 on 0-100? a\n * lower-is-better latency?), and guessing one is exactly the silent assumption\n * this gate exists to remove. A caller who DOES know it writes it onto the\n * record before calling — that is the caller's decision to make and to be\n * accountable for, and it then travels in the run corpus where an auditor can\n * see it. What the gate does instead is REFUSE, and report the full coverage\n * accounting (`GateEvidence.holdoutCoverage` / `searchCoverage`) so the caller\n * can see exactly which items went dark and on which arm.\n *\n * The denominator is MEASURED, never assumed: it is the set of work items the\n * comparison was DEALT, which is what `pairRunRecords` reports when it is given\n * every row of a split rather than only the scored ones. There is no list of\n * \"expected\" scenarios to keep in sync and nothing to trust — an item counts as\n * dealt because a row for it exists on at least one arm.\n *\n * ## Choosing the statistic\n *\n * The median paired delta is the robust default, but it goes BLIND wherever\n * ties dominate: with more than half the pairs tied its sample value is exactly\n * 0 whatever the shift on the rest, and the whole bootstrap CI collapses to\n * [0, 0]. `low > threshold` is then \"no\" forever at a non-negative threshold\n * and \"yes\" forever at a negative one — the gate refuses real gains AND\n * promotes real regressions. Measured: 76 held-out items with 15 candidate\n * wins, 5 candidate losses and 56 ties is a real +13.2pp lift whose median\n * paired delta is 0; the median-CI gate refused it at every non-negative\n * threshold while PROMOTING the mirror-image −13.2pp regression at any\n * negative one.\n *\n * So the statistic is picked by the shape of the data, in three cases:\n *\n * 1. **Two-point (pass/fail) outcomes on ANY encoding** — every value on both\n * arms is either 0 or one common positive level, so {0,1} and {0,100} and\n * {0,5} all qualify (see `pairedBinaryScale`). The estimand is the change in\n * success rate, rescaled into the caller's native units. Two statistics\n * answer about it and BOTH must agree before anything is promoted:\n * `pairedRiskDifferenceScore` (Tango's score interval) supplies the\n * interval, and McNemar's exact test — carried on\n * `pairedRiskDifferenceExact` — holds a veto at any non-negative threshold.\n * The score interval is the one that decides because it is valid at a\n * NONZERO margin, which is the only thing a noninferiority threshold asks\n * about; the exact test's own Clopper-Pearson interval is conditional on the\n * discordant count and is therefore a valid interval only at margin 0.\n * McNemar's b/c/p ship as evidence.\n * 2. **Everything else** — the bootstrap CI of the MEAN paired delta. The mean\n * is the estimator that answers the gate's own question (\"by how much did\n * the score move\") in the caller's units, and it is well defined on every\n * shape the median loses: tie-dominated vectors, low-cardinality lattices\n * (block scores in {⅔, 1} from averaging pass/fail leaves; integer 0-100\n * judge dimensions), and mixed arms. Measured: 26 blocks of 3 pass/fail\n * leaves carrying a real +12.8pp lift, only 23% of pairs tied, give a\n * median CI of [0, 0.333] — a lower bound of exactly 0 refuses a real lift\n * at threshold 0, which is the original bug one lattice over. There is\n * therefore no tie-fraction cutoff: any cutoff leaves the lattice case open\n * on the far side of it. `heldoutSignificance` has defaulted to the mean\n * since #316 for the same reason.\n *\n * Set `deltaStatistic: 'median'` to force the median on every input — the\n * pre-0.134 behaviour, kept for callers who want outlier robustness and accept\n * the blindness that comes with it.\n *\n * ## Fail closed\n *\n * A ZERO-WIDTH CI carries no information about how far the estimate could be\n * wrong, wherever it sits. At [0, 0] it cannot tell a gain from a regression\n * and it clears every negative threshold. Away from zero it fails the opposite\n * way: n identical positive deltas give [g, g], which clears threshold 0 on no\n * spread at all. Both are an absence of evidence, so the gate refuses with\n * `indeterminate_delta` rather than answering \"promote\".\n *\n * The decision carries a machine-readable `rejectionCode` plus an\n * `evidence` block with every number the gate looked at, so the\n * downstream researcher / paper / dashboard can re-derive the\n * verdict without re-running.\n *\n * See also:\n * - `src/statistics.ts` for `pairedBootstrap` + `wilcoxonSignedRank`, and\n * `pairedRiskDifferenceScore` / `pairedRiskDifferenceExact` (+\n * `pairedBinaryScale`) for the binary path\n * - `src/run-record.ts` for the input row schema\n * - `src/reference-replay.ts` for the older, reference-replay-\n * specific promotion path (still useful for replay-style evals).\n */\n\nimport { pairRunRecords } from './paired-arms'\nimport { minimumPairsForPairedDeltaTest } from './paired-delta-test'\nimport {\n decidePairedPromotion,\n type PairedDecisionShape,\n type PairedDecisionStatistic,\n pairedDecisionShape,\n} from './paired-promotion-decision'\nimport { isRealnessGated, observedSplitScore, type ScorePreference } from './rollout/reward'\nimport type { RunRecord } from './run-record'\nimport { wilcoxonSignedRank } from './statistics'\n\nexport type HeldOutGateRejectionCode =\n | 'few_runs'\n | 'incomplete_coverage'\n | 'missing_split_scores'\n | 'missing_cost'\n | 'negative_delta'\n | 'indeterminate_delta'\n | 'overfit_gap'\n | 'cost_ceiling'\n\n/**\n * How much of one split's DEALT work the comparison actually measured.\n *\n * `answered + unscoredPairs + candidateOnly + baselineOnly === dealt` — a\n * complete, mutually exclusive partition of the item slots the split was dealt,\n * so nothing can leave the comparison without appearing in exactly one bucket.\n */\nexport interface SplitCoverage {\n /** Work items the split was dealt: every item with a row on either arm. */\n dealt: number\n /** Dealt items carrying a finite score on BOTH arms — the only ones any\n * paired statistic can read. */\n answered: number\n /** Dealt items with a row on both arms where at least one row carried no\n * finite score: a run happened and produced nothing (crash, timeout, judge\n * failure). Measured absence, not an absent item. */\n unscoredPairs: number\n /** Dealt items only the candidate produced a row for. */\n candidateOnly: number\n /** Dealt items only the baseline produced a row for. */\n baselineOnly: number\n /** `answered / dealt`, or 0 when nothing was dealt. 1 means every dealt item\n * was scored on both arms. */\n coverage: number\n}\n\nexport interface HeldOutGateConfig {\n /** Minimum number of paired (candidate, baseline) holdout observations\n * required before promotion. The exact small-sample test may require more\n * observations at the selected confidence. */\n minProductiveRuns?: number\n /** The CI lower bound on the paired holdout delta must exceed this to\n * promote. Read in the same units as the holdout scores: with binary\n * (0/1) outcomes that is a change in success RATE (0.05 = +5pp).\n * Default 0. */\n pairedDeltaThreshold?: number\n /**\n * Which paired statistic carries the promotion CI.\n *\n * `'auto'` (default) picks by outcome shape — two-point outcomes on the exact\n * paired risk difference, everything else on the mean bootstrap (see the\n * module header). `'median'` forces the median bootstrap on every input,\n * including shapes where it is structurally blind and will refuse a real lift\n * and accept a real regression. Set it for outlier robustness on genuinely\n * continuous outcomes, or to reproduce a pre-0.134 verdict.\n */\n deltaStatistic?: 'auto' | 'median'\n /** Maximum allowed worsening of (search − holdout) gap relative to\n * baseline. Default 0.15 (i.e. candidate may overfit by up to 15\n * absolute score points more than baseline before rejection). */\n overfitGapThreshold?: number\n /** Stable label of the baseline candidate. Required — paper-grade\n * evaluation never compares two unlabelled candidates. */\n baselineKey: string\n /** Confidence level for the bootstrap CI. Default 0.95. */\n confidence?: number\n /** Bootstrap resamples. Default 2000. */\n bootstrapResamples?: number\n /** Optional deterministic seed for the bootstrap. Absent, `pairedBootstrap`\n * derives the seed from the paired observations, so the same holdout\n * reproduces the same interval. */\n seed?: number\n /**\n * Smallest acceptable `answered / dealt` fraction, required on BOTH splits.\n * Default 1: every work item the comparison was dealt must carry a real score\n * on both arms before the gate will decide anything.\n *\n * The default is 1 because a missing score is missing data, and a promotion\n * computed over \"the items that happened to answer\" is a promotion computed\n * over a set the candidate selected by failing (see the module header). One\n * split below `minCoverage` rejects with `incomplete_coverage`.\n *\n * Lowering it is a real, defensible choice for a caller who accepts a known\n * flake rate — but it must be DECLARED, not inherited: the shrunken\n * denominator then still ships in `GateEvidence.holdoutCoverage` /\n * `searchCoverage`, so the verdict can never be read without it. Must be in\n * [0, 1]; anything else throws rather than clamping.\n */\n minCoverage?: number\n /**\n * Hard ceiling on the candidate's median per-task USD cost. When the\n * candidate clears the quality gates (paired-delta + overfit-gap) but\n * its median cost exceeds this number, the gate rejects with\n * `cost_ceiling`. Default `undefined` = no cost ceiling, behaving\n * exactly like the pre-cost gate.\n *\n * This exists because \"we ship the better prompt\" is only an honest\n * pitch when the better prompt also fits a customer-stated budget.\n * Cost is read from `RunRecord.costUsd`; a null amount rejects a\n * configured cost check because the limit cannot be proven.\n */\n costPerTaskCeiling?: number\n}\n\n/** Which paired statistic a `HeldOutGate` verdict was decided on. One\n * definition, shared with every other gate that decides a paired interval. */\nexport type DeltaStatistic = PairedDecisionStatistic\n\nexport interface GateEvidence {\n /** Number of paired (candidate, baseline) holdout observations used. */\n productiveRuns: number\n /** Candidate holdout rows with no baseline row at the same work identity. */\n unpairedCandidateRuns: number\n /** Baseline holdout rows with no candidate row at the same work identity. */\n unpairedBaselineRuns: number\n /**\n * How much of the dealt HOLDOUT work carried a score on both arms — the\n * denominator behind `productiveRuns`, `medianPairedDelta`, `pairedCI` and\n * `holdoutScore`. A `coverage` below 1 means those numbers describe a\n * SUBSET of the items the comparison was dealt, and which items are in that\n * subset was decided by whichever arm went dark.\n */\n holdoutCoverage: SplitCoverage\n /**\n * The same accounting for the SEARCH split — the denominator behind\n * `searchScore`, and therefore behind both overfit gaps.\n */\n searchCoverage: SplitCoverage\n /** Median of paired holdout deltas, or null when there are no pairs.\n * ALWAYS the literal median — a diagnostic, not necessarily the statistic\n * the verdict keyed on (see `deltaStatistic` / `decidingDelta`). On binary\n * outcomes this is normally 0 by construction. */\n medianPairedDelta: number | null\n /** Which paired statistic the promotion CI was computed on, and therefore\n * what `decidingDelta` / `pairedCI` mean. `'median_bootstrap'` = bootstrap\n * CI on the median paired delta (continuous outcomes).\n * `'mean_bootstrap'` = bootstrap CI on the mean paired delta, used when ties\n * dominate and pin the median at 0. `'paired_risk_difference'` = change in\n * success rate on a two-point (pass/fail) outcome, on an EXACT conditional\n * interval dual to McNemar's exact test, rescaled to the outcome's native\n * units (so a 0-100 dimension reports points, not a rate). */\n deltaStatistic: DeltaStatistic\n /** Point estimate of `deltaStatistic` — the number the `pairedDeltaThreshold`\n * check is about. Null when no CI was computed. */\n decidingDelta: number | null\n /** CI on `deltaStatistic`, if computed. The gate promotes iff\n * `pairedCI.low > pairedDeltaThreshold`. */\n pairedCI: { low: number; high: number } | null\n /** Wilcoxon signed-rank p-value, if computed. Always the Wilcoxon, on both\n * paths, so this field never changes meaning. */\n pairedPValue: number | null\n /** McNemar's exact paired-binary test on the holdout pairs, or null when the\n * outcomes were not two-point (or no CI was computed). `b` = candidate-only\n * wins, `c` = baseline-only wins; only these discordant pairs carry signal.\n * When present it is not merely reported: the promotion interval is dual to\n * this p-value, so a promotion at a non-negative threshold implies\n * `pValue < 1 − confidence`. */\n mcnemar: { b: number; c: number; nDiscordant: number; pValue: number } | null\n /** The common positive level of a two-point outcome — 1 for {0,1}, 100 for a\n * 0-100 pass/fail dimension — or null when the outcome is not two-point.\n * Non-null is exactly the condition for the `paired_risk_difference` path,\n * and it is the factor `decidingDelta` / `pairedCI` were rescaled by. */\n binaryScale: number | null\n /** Fraction of paired holdout deltas that are exact ties, or null when there\n * are no pairs. At or above 0.5 the median paired delta is pinned at 0 by\n * construction; this is the diagnostic for why a median-decided verdict\n * (`deltaStatistic: 'median'`) saw nothing. */\n tieFraction: number | null\n /** Mean candidate score on the search split, or null when absent. */\n searchScore: number | null\n /** Mean candidate score on the holdout split, or null when absent. */\n holdoutScore: number | null\n /** Candidate (search − holdout) gap, or null when either side is absent. */\n overfitGap: number | null\n /** Baseline (search − holdout) gap, or null when either side is absent. */\n baselineOverfitGap: number | null\n /** Median per-task USD cost across the candidate's runs. Recorded\n * even when no `costPerTaskCeiling` is configured so downstream\n * dashboards (intelligence.tangle.tools) can render \\$/task per\n * generation regardless of gating policy. */\n medianCandidateCost: number | null\n /** Median per-task USD cost across the baseline runs, for\n * symmetric reporting. */\n medianBaselineCost: number | null\n /**\n * Runs (candidate + baseline) dropped before pairing because the\n * authenticity gate flagged them as gamed. Surfaced rather than silent: a\n * promotion decision computed over a shrunken pool has to say by how much,\n * and a nonzero count here is itself the finding.\n */\n realnessGatedRuns: number\n}\n\nexport interface GateDecision {\n /** Final promote/no-promote verdict. */\n promote: boolean\n /** The candidate that was evaluated. */\n candidateId: string\n /** The baseline it was compared against. */\n baselineId: string\n /** Every number the gate looked at, for audit + paper export. */\n evidence: GateEvidence\n /** Human-readable reason. */\n reason: string\n /** Machine-readable rejection code, or null on promote. */\n rejectionCode: HeldOutGateRejectionCode | null\n}\n\n/**\n * Held-out paired-delta promotion gate. Construct once with config,\n * call `evaluate(candidateRuns, baselineRuns)` per (candidate,\n * baseline) pair. Stateless across calls.\n */\nexport class HeldOutGate {\n private readonly minProductiveRuns: number\n private readonly pairedDeltaThreshold: number\n private readonly overfitGapThreshold: number\n private readonly baselineKey: string\n private readonly confidence: number\n private readonly resamples: number\n private readonly seed?: number\n private readonly costPerTaskCeiling?: number\n private readonly minCoverage: number\n private readonly deltaStatistic: 'auto' | 'median'\n\n constructor(config: HeldOutGateConfig) {\n if (!config.baselineKey) {\n throw new Error('HeldOutGate: baselineKey is required')\n }\n if (\n config.minCoverage !== undefined &&\n !(Number.isFinite(config.minCoverage) && config.minCoverage >= 0 && config.minCoverage <= 1)\n ) {\n throw new Error(\n `HeldOutGate: minCoverage must be a finite fraction in [0, 1], got ${config.minCoverage}`,\n )\n }\n this.minCoverage = config.minCoverage ?? 1\n this.confidence = config.confidence ?? 0.95\n this.minProductiveRuns = Math.max(\n config.minProductiveRuns ?? 3,\n minimumPairsForPairedDeltaTest(this.confidence),\n )\n this.pairedDeltaThreshold = config.pairedDeltaThreshold ?? 0\n this.overfitGapThreshold = config.overfitGapThreshold ?? 0.15\n this.baselineKey = config.baselineKey\n this.resamples = config.bootstrapResamples ?? 2000\n this.seed = config.seed\n this.deltaStatistic = config.deltaStatistic ?? 'auto'\n if (\n config.costPerTaskCeiling !== undefined &&\n !(Number.isFinite(config.costPerTaskCeiling) && config.costPerTaskCeiling > 0)\n ) {\n throw new Error('HeldOutGate: costPerTaskCeiling must be a positive finite number')\n }\n this.costPerTaskCeiling = config.costPerTaskCeiling\n }\n\n /** Decide whether `candidate` should replace `baseline`.\n * Pairing is by `(experimentId, scenarioId, seed)`.\n * Missing or duplicate identities throw instead of comparing by position. */\n evaluate(candidate: RunRecord[], baseline: RunRecord[]): GateDecision {\n const candidateId = inferCandidateId(candidate, this.baselineKey)\n const baselineId = this.baselineKey\n assertScenarioIdentities([...candidate, ...baseline])\n\n // Runs flagged as gamed are dropped from BOTH sides before anything is\n // paired. This is a promotion decision, and the whole point of the\n // authenticity gate is that a faked success must not buy a promotion; the\n // count ships in the evidence so the shrunken pool is never invisible.\n const realnessGatedRuns = [...candidate, ...baseline].filter(isRealnessGated).length\n const honestCandidate = candidate.filter((run) => !isRealnessGated(run))\n const honestBaseline = baseline.filter((run) => !isRealnessGated(run))\n\n const candidateSearch = scoredRuns(honestCandidate, 'search')\n const baselineSearch = scoredRuns(honestBaseline, 'search')\n const candidateHoldout = scoredRuns(honestCandidate, 'holdout')\n const baselineHoldout = scoredRuns(honestBaseline, 'holdout')\n const searchPairing = pairRunRecords(baselineSearch, candidateSearch)\n const holdoutPairing = pairRunRecords(baselineHoldout, candidateHoldout)\n // The DEALT denominators, measured over every row of each split — scored or\n // not — so an item that produced no number is still counted as work the\n // comparison was given. `splitCoverage` re-pairs the unfiltered rows with\n // the same primitive the decision pairs with, which is the only way the\n // \"dealt\" set can be derived rather than assumed.\n const searchCoverage = splitCoverage(honestBaseline, honestCandidate, 'search')\n const holdoutCoverage = splitCoverage(honestBaseline, honestCandidate, 'holdout')\n // `scoredRuns` admits only rows whose split score is a finite number, so\n // the non-null assertion below cannot fire on data the pairing saw.\n const splitScoreOf = (run: RunRecord, split: ScorePreference): number =>\n observedSplitScore(run, split) as number\n const beforeSearch = searchPairing.pairs.map((pair) => splitScoreOf(pair.baseline, 'search'))\n const afterSearch = searchPairing.pairs.map((pair) => splitScoreOf(pair.treatment, 'search'))\n const beforeHoldout = holdoutPairing.pairs.map((pair) => splitScoreOf(pair.baseline, 'holdout'))\n const afterHoldout = holdoutPairing.pairs.map((pair) => splitScoreOf(pair.treatment, 'holdout'))\n\n const productiveRuns = beforeHoldout.length\n\n const candidateSearchMean = meanOrNull(afterSearch)\n const candidateHoldoutMean = meanOrNull(afterHoldout)\n const baselineSearchMean = meanOrNull(beforeSearch)\n const baselineHoldoutMean = meanOrNull(beforeHoldout)\n\n const overfitGap = diffOrNull(candidateSearchMean, candidateHoldoutMean)\n const baselineOverfitGap = diffOrNull(baselineSearchMean, baselineHoldoutMean)\n\n // Cost summary — surfaced in evidence regardless of gating policy so\n // downstream dashboards always know what the candidate cost.\n //\n // The population is the rows that DECIDED this verdict: the matched pairs\n // on both splits, and nothing else. Taking the median over every row the\n // caller happened to pass is a denominator nobody measured, and it is\n // trivially movable — 48 rows tagged `dev` at $0.0001, which the gate never\n // scores and the coverage check never counts, drag a real $5.00/task\n // candidate to a reported $0.0001 and clear a $1.00 ceiling. Deriving the\n // population from the pairing rather than from a list of split tags means\n // there is no tag to sit outside the rule: a row either decided the verdict\n // or it does not describe its cost.\n const medianCandidateCost = completeCostMedian([\n ...searchPairing.pairs.map((pair) => pair.treatment),\n ...holdoutPairing.pairs.map((pair) => pair.treatment),\n ])\n const medianBaselineCost = completeCostMedian([\n ...searchPairing.pairs.map((pair) => pair.baseline),\n ...holdoutPairing.pairs.map((pair) => pair.baseline),\n ])\n const commonEvidence = {\n productiveRuns,\n unpairedCandidateRuns: holdoutPairing.unpairedTreatment.length,\n unpairedBaselineRuns: holdoutPairing.unpairedBaseline.length,\n searchScore: candidateSearchMean,\n holdoutScore: candidateHoldoutMean,\n overfitGap,\n baselineOverfitGap,\n medianCandidateCost,\n medianBaselineCost,\n realnessGatedRuns,\n searchCoverage,\n holdoutCoverage,\n }\n /** Evidence for the early exits, where no CI was computed at all. The\n * statistic that WOULD have decided is still reported so a caller can see\n * which branch their data lands in without producing a verdict. */\n const earlyShape = this.chooseShape(beforeHoldout, afterHoldout)\n const noCiEvidence = {\n ...commonEvidence,\n medianPairedDelta: productiveRuns > 0 ? medianDelta(beforeHoldout, afterHoldout) : null,\n deltaStatistic: earlyShape.statistic,\n decidingDelta: null,\n pairedCI: null,\n pairedPValue: null,\n mcnemar: null,\n binaryScale: earlyShape.binaryScale,\n tieFraction: earlyShape.tieFraction,\n }\n\n const missingSplitScores = [\n candidateSearch.length === 0 ? 'candidate search' : null,\n candidateHoldout.length === 0 ? 'candidate holdout' : null,\n baselineSearch.length === 0 ? 'baseline search' : null,\n baselineHoldout.length === 0 ? 'baseline holdout' : null,\n ].filter((label): label is string => label !== null)\n if (missingSplitScores.length > 0) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason: `missing_split_scores: ${missingSplitScores.join(', ')} score evidence is absent`,\n rejectionCode: 'missing_split_scores',\n }\n }\n\n // COVERAGE — before every statistic, because every statistic below reads\n // only the items that answered. A candidate that went dark on most of its\n // work does not get judged on the remainder; missing scores are missing\n // data, and the gate refuses rather than shrinking the denominator to the\n // subset that happened to answer. Checked ahead of `few_runs` because \"6 of\n // 26 items produced no score\" is the finding, and \"6 paired observations\"\n // is only its shadow.\n const shortfalls = (\n [\n ['holdout', holdoutCoverage],\n ['search', searchCoverage],\n ] as const\n ).filter(([, cov]) => cov.coverage < this.minCoverage)\n if (shortfalls.length > 0) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason:\n `incomplete_coverage: ${shortfalls.map(([split, cov]) => describeCoverage(split, cov)).join('; ')}` +\n ` — required ${fmt(this.minCoverage)} of every dealt item scored on both arms.` +\n ' A missing score is missing data, not an absent item: the gate will not decide on the subset that answered',\n rejectionCode: 'incomplete_coverage',\n }\n }\n\n if (productiveRuns < this.minProductiveRuns) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence: noCiEvidence,\n reason: `few_runs: ${productiveRuns} paired holdout observation(s) < min ${this.minProductiveRuns}`,\n rejectionCode: 'few_runs',\n }\n }\n if (overfitGap === null || baselineOverfitGap === null) {\n throw new Error('HeldOutGate: complete split scores did not produce overfit gaps')\n }\n\n // The paired holdout delta, decided by the one shared rule (see\n // `paired-promotion-decision.ts`): the estimator comes from the outcome's\n // shape, McNemar vetoes at a non-negative threshold, and a zero-width\n // interval is refused. `medianPairedDelta` stays the literal median on\n // EVERY path so the number that made the old gate blind remains visible.\n const decision = decidePairedPromotion(beforeHoldout, afterHoldout, {\n threshold: this.pairedDeltaThreshold,\n confidence: this.confidence,\n resamples: this.resamples,\n seed: this.seed,\n minPairs: this.minProductiveRuns,\n statistic: this.deltaStatistic === 'median' ? 'median' : 'mean',\n })\n const literalMedian = medianDelta(beforeHoldout, afterHoldout)\n const wilcoxon = wilcoxonSignedRank(beforeHoldout, afterHoldout)\n const { delta: decidingDelta, low, high, label: deltaLabel } = decision\n\n const evidence: GateEvidence = {\n ...commonEvidence,\n medianPairedDelta: literalMedian,\n deltaStatistic: decision.statistic,\n decidingDelta,\n pairedCI: { low, high },\n pairedPValue: wilcoxon.p,\n mcnemar: decision.mcnemar,\n binaryScale: decision.binaryScale,\n tieFraction: decision.tieFraction,\n }\n\n // FAIL CLOSED on a ZERO-WIDTH interval, wherever it sits. [0, 0] cannot\n // tell a gain from a regression and clears every negative threshold, which\n // is exactly how a tie-pinned median laundered a −13.2pp regression into a\n // promotion. But the same emptiness away from zero is just as false a\n // certainty and it fails the other way: n identical positive deltas give\n // [g, g], which clears threshold 0 with no spread to support it. Under a\n // bounded asymmetric null whose true mean paired delta is exactly 0 — 2 %\n // of pairs dropping by 1.0, the rest gaining 0.0204 — every sample that\n // misses the drop is exactly that shape, and a `low === 0 && high === 0`\n // test promotes 65.65 % of them at n = 20 against a nominal 5 %.\n if (decision.indeterminate) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `indeterminate_delta: ${decision.indeterminateCause}, so the paired holdout CI is ` +\n `[${fmt(low)}, ${fmt(high)}] and carries no direction — ` +\n `it cannot clear threshold ${fmt(this.pairedDeltaThreshold)} on evidence`,\n rejectionCode: 'indeterminate_delta',\n }\n }\n\n if (!decision.sufficient) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason: `few_runs: ${productiveRuns} paired holdout observations < ${decision.minimumPairs} required for ${deltaLabel} estimation`,\n rejectionCode: 'few_runs',\n }\n }\n\n // The exact test is a VETO on the two-point path. Redundant by construction\n // — `pairedRiskDifferenceExact`'s interval is dual to this p-value, so\n // `low > 0` already implies `pValue < 1 − confidence` (verified over 8108\n // (b, c, ties, confidence) shapes) — and kept anyway so that swapping the\n // estimator for one without that duality (the Wald interval, which\n // undercovers on a handful of discordant pairs) cannot silently reintroduce\n // \"promotes what the exact test refuses\". Only applies at a non-negative\n // threshold: a negative threshold is a non-inferiority question, which\n // McNemar's test of \"no difference\" is not the right test for.\n const exactTestVetoes = decision.exactTestVetoes\n\n // Negative-delta gate (the paired-delta evidence must clear the threshold).\n if (!decision.clearsThreshold || exactTestVetoes) {\n const detail = exactTestVetoes\n ? ` McNemar exact p=${decision.mcnemar?.pValue.toExponential(2)} does not reject at α=${fmt(1 - this.confidence)}.`\n : decision.methodDetail\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `negative_delta: paired holdout ${deltaLabel} Δ=${fmt(decidingDelta)} ` +\n `CI=[${fmt(low)}, ${fmt(high)}] does not clear threshold ${fmt(this.pairedDeltaThreshold)}.${detail}`,\n rejectionCode: 'negative_delta',\n }\n }\n\n // Overfit-gap gate. We allow some absolute slack —\n // candidate.gap ≤ baseline.gap + overfitGapThreshold.\n if (overfitGap > baselineOverfitGap + this.overfitGapThreshold) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `overfit_gap: candidate gap=${fmt(overfitGap)} exceeds baseline gap=${fmt(baselineOverfitGap)} ` +\n `by more than ${fmt(this.overfitGapThreshold)}`,\n rejectionCode: 'overfit_gap',\n }\n }\n\n // Cost-ceiling gate. Runs after quality gates so a cost-driven\n // rejection always carries a \"you cleared quality but blew budget\"\n // story rather than masking a quality failure.\n if (this.costPerTaskCeiling !== undefined && medianCandidateCost === null) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason: 'missing_cost: candidate cost evidence is incomplete',\n rejectionCode: 'missing_cost',\n }\n }\n if (\n this.costPerTaskCeiling !== undefined &&\n medianCandidateCost !== null &&\n medianCandidateCost > this.costPerTaskCeiling\n ) {\n return {\n promote: false,\n candidateId,\n baselineId,\n evidence,\n reason:\n `cost_ceiling: candidate median cost $${fmt(medianCandidateCost)} ` +\n `exceeds ceiling $${fmt(this.costPerTaskCeiling)} (baseline $${fmt(medianBaselineCost)})`,\n rejectionCode: 'cost_ceiling',\n }\n }\n\n return {\n promote: true,\n candidateId,\n baselineId,\n evidence,\n reason:\n `promote: paired holdout ${deltaLabel} Δ=${fmt(decidingDelta)} ` +\n `CI=[${fmt(low)}, ${fmt(high)}] over ${productiveRuns} pairs; ` +\n `overfit gap candidate=${fmt(overfitGap)} vs baseline=${fmt(baselineOverfitGap)}; ` +\n `median cost candidate=$${fmt(medianCandidateCost)} vs baseline=$${fmt(medianBaselineCost)}`,\n rejectionCode: null,\n }\n }\n\n /**\n * Which paired statistic decides this data, and the shape facts behind it —\n * for the early exits, where no interval is computed. Delegates to\n * {@link pairedDecisionShape} so the reported shape can never disagree with\n * the shape the decision actually routes on.\n */\n private chooseShape(before: number[], after: number[]): PairedDecisionShape {\n return pairedDecisionShape(before, after, this.deltaStatistic === 'median' ? 'median' : 'mean')\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction inferCandidateId(candidate: RunRecord[], baselineKey: string): string {\n for (const run of candidate) {\n if (run.candidateId && run.candidateId !== baselineKey) return run.candidateId\n }\n // All candidate rows match the baseline key — caller mistake, but\n // surface the symptom rather than throwing inside the gate.\n return candidate[0]?.candidateId ?? '(unknown candidate)'\n}\n\nfunction assertScenarioIdentities(runs: RunRecord[]): void {\n for (const run of runs) {\n if (typeof run.scenarioId !== 'string' || run.scenarioId.trim() === '') {\n throw new Error(`HeldOutGate: run ${run.runId} is missing scenarioId`)\n }\n }\n}\n\n/**\n * Rows carrying a finite score on one split. RAW (`observedSplitScore`) by\n * choice: the gated runs are already removed by the caller, so applying the\n * gate again here would only zero runs that are no longer in the set, and the\n * reported means must describe the runs that actually decided the promotion.\n */\nfunction scoredRuns(runs: RunRecord[], split: ScorePreference): RunRecord[] {\n return runs.filter((run) => {\n if (run.splitTag !== split) return false\n const v = observedSplitScore(run, split)\n return typeof v === 'number' && Number.isFinite(v)\n })\n}\n\n/** Every row tagged to one split, scored or not — the work the split was\n * DEALT, as opposed to the work it managed to measure. */\nfunction dealtRuns(runs: RunRecord[], split: ScorePreference): RunRecord[] {\n return runs.filter((run) => run.splitTag === split)\n}\n\nfunction hasFiniteScore(run: RunRecord, split: ScorePreference): boolean {\n const v = observedSplitScore(run, split)\n return typeof v === 'number' && Number.isFinite(v)\n}\n\n/**\n * Partition one split's dealt work into answered / unscored / one-armed.\n *\n * Pairs the UNFILTERED rows with the same `pairRunRecords` the decision uses,\n * so the denominator comes out of the same identity rules as the numerator and\n * cannot drift from it. Deliberately a SECOND pairing rather than a widening of\n * the decision's own: the decision keeps pairing exactly the rows it always\n * paired, so this check can only ever add a refusal, never move a verdict that\n * was already being made on a complete set.\n */\nfunction splitCoverage(\n baseline: RunRecord[],\n candidate: RunRecord[],\n split: ScorePreference,\n): SplitCoverage {\n const pairing = pairRunRecords(dealtRuns(baseline, split), dealtRuns(candidate, split))\n let answered = 0\n for (const pair of pairing.pairs) {\n if (hasFiniteScore(pair.baseline, split) && hasFiniteScore(pair.treatment, split)) answered += 1\n }\n const unscoredPairs = pairing.pairs.length - answered\n const candidateOnly = pairing.unpairedTreatment.length\n const baselineOnly = pairing.unpairedBaseline.length\n const dealt = pairing.pairs.length + candidateOnly + baselineOnly\n return {\n dealt,\n answered,\n unscoredPairs,\n candidateOnly,\n baselineOnly,\n coverage: dealt === 0 ? 0 : answered / dealt,\n }\n}\n\nfunction describeCoverage(split: string, cov: SplitCoverage): string {\n const dark = [\n cov.unscoredPairs > 0 ? `${cov.unscoredPairs} ran on both arms but produced no score` : null,\n cov.baselineOnly > 0 ? `${cov.baselineOnly} only the baseline produced a row for` : null,\n cov.candidateOnly > 0 ? `${cov.candidateOnly} only the candidate produced a row for` : null,\n ].filter((part): part is string => part !== null)\n return (\n `${split} scored ${cov.answered} of ${cov.dealt} dealt items (coverage ${fmt(cov.coverage)})` +\n (dark.length > 0 ? ` — ${dark.join(', ')}` : '')\n )\n}\n\nfunction meanOrNull(xs: number[]): number | null {\n if (xs.length === 0) return null\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction diffOrNull(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null\n return a - b\n}\n\nfunction medianDelta(before: number[], after: number[]): number {\n const ds = before.map((b, i) => after[i]! - b).sort((x, y) => x - y)\n if (ds.length === 0) throw new Error('HeldOutGate: median delta requires at least one pair')\n const mid = Math.floor(ds.length / 2)\n return ds.length % 2 === 0 ? (ds[mid - 1]! + ds[mid]!) / 2 : ds[mid]!\n}\n\nfunction medianFinite(xs: number[]): number | null {\n const ys = xs.filter((x) => Number.isFinite(x)).sort((x, y) => x - y)\n if (ys.length === 0) return null\n const mid = Math.floor(ys.length / 2)\n return ys.length % 2 === 0 ? (ys[mid - 1]! + ys[mid]!) / 2 : ys[mid]!\n}\n\nfunction completeCostMedian(runs: RunRecord[]): number | null {\n if (runs.length === 0) return null\n const costs: number[] = []\n for (const run of runs) {\n const provenance = run.costProvenance\n if (provenance.kind === 'uncaptured') return null\n costs.push(provenance.usd)\n }\n return medianFinite(costs)\n}\n\nfunction fmt(x: number | null): string {\n if (x === null) return 'n/a'\n return x.toFixed(4)\n}\n","/**\n * Hidden-criteria grading firewall — grade an agent on criteria it never saw.\n *\n * A trustworthy benchmark splits every scenario's data by WHERE each field is\n * allowed to flow, then proves the held-out / judge-only fields never reach the\n * agent during the run. The coding bench expresses this with four destinations\n * (prompt / develop-against / held-out suite / rubric); this module lifts the\n * domain-FREE core out of it so research, legal, tax, content — any domain —\n * can declare the same routing and get the same firewall enforcement and the\n * same held-out-weighted composite, plugging in its OWN grader.\n *\n * Two reusable pieces, both domain-agnostic:\n *\n * 1. FIELD ROUTING BY DESTINATION. A scenario declares each field's\n * `FieldDestination`; `assertNoHiddenLeak` is a pure checker that throws if\n * a grading-only or judge-only field's value appears in what reaches the\n * agent. The domain decides which fields exist and where they go — the\n * substrate only enforces \"hidden stays hidden\".\n *\n * 2. HIDDEN-CRITERIA GRADING. The domain supplies its own grader\n * `(artifact, hiddenCriteria) => { passRate, total }` — the coding\n * node-test executor is ONE such grader a consumer plugs in; the substrate\n * bakes in NO node/test/TS/exec/regex. `gradeOnHidden` runs that grader\n * behind the firewall and `blendHeldout` composes its pass rate with a\n * judge score into the final number the leaderboard ranks on.\n *\n * Shape mirrors `treatment-gate`/`authenticity`: pure predicates and pure\n * composition over already-computed values, fail-loud, with the\n * \"which field / which weight / which grader\" decisions left as parameters and\n * no domain literal anywhere in the module.\n *\n * Lives next to `test-graded-scenario` and `partition-held-out` — it is a\n * scorecard/grading concept that makes sense without a running agent loop.\n */\n\nimport type { JudgeScore } from './campaign/types'\nimport { ValidationError } from './errors'\n\n// ── 1. field routing by destination ──────────────────────────────────────────\n\n/**\n * Where one scenario field is allowed to flow. The firewall guarantee is keyed\n * on this tag, not on a field name — a domain can have any number of fields per\n * destination.\n *\n * - `agent-visible` reaches the agent's context during the run (the prompt,\n * the task statement — what the agent reads to act).\n * - `develop-against` seeded into the agent's environment during the run so it\n * can iterate (a visible example/test/reference). The\n * agent MAY read it — that is intentional (real TDD). Not\n * a leak: it is example-grade, not the grading criteria.\n * - `grading-only` the hidden criteria. Used ONLY at grading, after the run\n * — the held-out suite / answer key / hidden requirements.\n * Must NEVER reach the agent context. This is what makes a\n * good score un-memorizable.\n * - `judge-only` grading context for the judge only (rubric anchors,\n * design intent). Lives with the judge, never in the agent\n * context.\n */\nexport type FieldDestination = 'agent-visible' | 'develop-against' | 'grading-only' | 'judge-only'\n\n/** The destinations a value must be kept OUT of the agent context for. */\nconst hiddenDestinations: ReadonlySet<FieldDestination> = new Set<FieldDestination>([\n 'grading-only',\n 'judge-only',\n])\n\n/** True for the destinations whose values must never reach the agent context. */\nexport function isHiddenDestination(destination: FieldDestination): boolean {\n return hiddenDestinations.has(destination)\n}\n\n/**\n * A scenario's fields routed by destination. The domain owns the field set\n * (`TFields` — a record of its named fields to their string-renderable values)\n * and declares one `FieldDestination` per field. `routeFields` builds this from\n * a domain's `(value, destination)` map; the firewall reads it.\n */\nexport interface RoutedField {\n /** The field's name — for diagnostics only. */\n name: string\n /** The field's value as it would be rendered into text. The firewall compares\n * this against the agent context, so a domain that ships structured data\n * passes a stable string projection (e.g. JSON) of the hidden value. */\n value: string\n destination: FieldDestination\n}\n\n/**\n * Route a domain's named fields by destination into the firewall's input shape.\n * The `routing` declares each field's destination; the `values` carry each\n * field's renderable string. A field present in `routing` but missing from\n * `values` is an authoring error (fail loud) — every routed field must have a\n * value the firewall can check.\n */\nexport function routeFields<TName extends string>(\n routing: Readonly<Record<TName, FieldDestination>>,\n values: Readonly<Record<TName, string>>,\n): RoutedField[] {\n const out: RoutedField[] = []\n for (const name of Object.keys(routing) as TName[]) {\n const value = values[name]\n if (value === undefined) {\n throw new ValidationError(\n `routed field \"${name}\" has a destination but no value — every routed field must carry its value`,\n )\n }\n out.push({ name, value, destination: routing[name] })\n }\n return out\n}\n\n/** A single detected leak: a hidden field whose value appears in the agent context. */\nexport interface HiddenLeak {\n field: string\n destination: FieldDestination\n}\n\nexport interface NoLeakOptions {\n /** Minimum hidden-value length to check. A hidden value shorter than this is\n * skipped — a one-word or empty hidden field would substring-match innocuous\n * prose and is not meaningful evidence of a leak. Default 12. */\n minMatchLength?: number\n}\n\n/**\n * The FIREWALL. Throws `ValidationError` if any `grading-only`/`judge-only`\n * field's value is found inside `agentContext` — the exact text that reaches the\n * agent during the run (its prompt, its seeded files concatenated, whatever the\n * caller assembled). `agent-visible` and `develop-against` fields are never\n * checked: they are meant to be there.\n *\n * Substring containment is the check: it is domain-free and catches the failure\n * that matters — a hidden answer key, held-out case, or rubric anchor pasted\n * into the prompt. Returns the routed fields on success so a caller can chain.\n */\nexport function assertNoHiddenLeak(\n fields: readonly RoutedField[],\n agentContext: string,\n opts: NoLeakOptions = {},\n): readonly RoutedField[] {\n const minLen = opts.minMatchLength ?? 12\n const leaks: HiddenLeak[] = []\n for (const field of fields) {\n if (!isHiddenDestination(field.destination)) continue\n const needle = field.value.trim()\n if (needle.length < minLen) continue\n if (agentContext.includes(needle)) {\n leaks.push({ field: field.name, destination: field.destination })\n }\n }\n if (leaks.length > 0) {\n const detail = leaks.map((l) => `\"${l.field}\" (${l.destination})`).join(', ')\n throw new ValidationError(\n `hidden-criteria firewall breached: ${leaks.length} hidden field(s) reached the agent context: ${detail}`,\n )\n }\n return fields\n}\n\n/** Collect the values a domain may safely render into the agent context — the\n * `agent-visible` (and, by intent, `develop-against`) fields — so a caller can\n * ASSEMBLE the context from the routing rather than hand-picking fields and\n * risking a slip. `develop-against` is included because it is seeded into the\n * agent's environment during the run on purpose. */\nexport function agentVisibleFields(fields: readonly RoutedField[]): RoutedField[] {\n return fields.filter((f) => !isHiddenDestination(f.destination))\n}\n\n// ── 2. hidden-criteria grading ────────────────────────────────────────────────\n\n/** What a hidden-criteria grader reports. `passRate = passed / total` over the\n * hidden checks; `total === 0` means the criteria never ran (e.g. the artifact\n * did not even load) — an honest zero, never a spurious pass. */\nexport interface HiddenGradeResult {\n /** Hidden checks that passed. */\n passed: number\n /** Total hidden checks attempted. 0 when the criteria could not run at all. */\n total: number\n /** `passed / total`, or 0 when `total === 0`. The PRIMARY correctness score. */\n passRate: number\n /** Free-form provenance the caller may record (runner output, reason for 0). */\n notes?: string\n}\n\n/**\n * The domain's grader: given the agent's artifact and the HIDDEN criteria,\n * return a pass rate. This is the ONE seam a non-coding domain implements — the\n * coding node-test executor is a single implementation of it; a legal grader\n * checks the brief against hidden required holdings, a research grader checks an\n * answer against held-out facts, a tax grader runs hidden return assertions.\n * The substrate calls it ONLY at grading time, behind the firewall.\n *\n * `THidden` is the domain's hidden-criteria payload (the held-out suite, the\n * answer key, the hidden requirements) — opaque to the substrate.\n */\nexport type HiddenCriteriaGrader<TArtifact, THidden> = (\n artifact: TArtifact,\n hiddenCriteria: THidden,\n signal?: AbortSignal,\n) => Promise<HiddenGradeResult> | HiddenGradeResult\n\n/** Normalize a grader's raw `{passed, total}` into a `HiddenGradeResult` with a\n * consistent, fail-loud `passRate` — the canonical \"honest zero on no-run\"\n * rule, single-sourced so every domain grader gets it. */\nexport function hiddenGrade(passed: number, total: number, notes?: string): HiddenGradeResult {\n const p = Number.isFinite(passed) && passed > 0 ? Math.floor(passed) : 0\n const t = Number.isFinite(total) && total > 0 ? Math.floor(total) : 0\n const passRate = t > 0 ? Math.min(1, p / t) : 0\n return { passed: Math.min(p, t > 0 ? t : p), total: t, passRate, notes }\n}\n\n/**\n * Run a domain's hidden-criteria grader behind the firewall. Before grading, it\n * re-asserts the firewall against the agent context the run actually used —\n * proving (at grading time, on real data) that the hidden criteria never\n * reached the agent — then invokes the grader and returns its pass rate. A\n * domain that wants the firewall and the grader wired together in one call uses\n * this; a domain that already asserted the firewall at dispatch time can call\n * its grader directly and feed the result to `blendHeldout`.\n */\nexport async function gradeOnHidden<TArtifact, THidden>(args: {\n artifact: TArtifact\n hiddenCriteria: THidden\n grader: HiddenCriteriaGrader<TArtifact, THidden>\n /** The routed fields + the exact agent context, re-checked before grading. */\n firewall: { fields: readonly RoutedField[]; agentContext: string; options?: NoLeakOptions }\n signal?: AbortSignal\n}): Promise<HiddenGradeResult> {\n assertNoHiddenLeak(args.firewall.fields, args.firewall.agentContext, args.firewall.options)\n const result = await args.grader(args.artifact, args.hiddenCriteria, args.signal)\n return hiddenGrade(result.passed, result.total, result.notes)\n}\n\n// ── the composite: hidden correctness (PRIMARY) + judge quality (secondary) ────\n\n/** Weights for the held-out / judge blend. Must be finite and non-negative;\n * they are renormalized to sum to 1 so a caller can pass any positive ratio. */\nexport interface BlendWeights {\n /** Weight on the hidden-criteria pass rate (the primary, ungameable score). */\n heldout: number\n /** Weight on the judge's quality composite (the secondary style/quality score). */\n judge: number\n}\n\n/** Default blend: 0.7 hidden correctness, 0.3 judge quality. The coding bench's\n * long-standing split — execution truth dominates, style refines. */\nexport const defaultBlendWeights: BlendWeights = { heldout: 0.7, judge: 0.3 }\n\n/** The input shape a judge's `score` receives — exactly `JudgeConfig.score`'s\n * argument: the artifact, plus any scenario/signal fields the judge carries.\n * `withHeldoutBlend` only reads `artifact`; the rest rides through. */\nexport interface JudgeScoreInput<TArtifact> {\n artifact: TArtifact\n /** Pass-through for the judge's extra input fields (scenario, signal). */\n [key: string]: unknown\n}\n\nfunction normalizeWeights(weights: BlendWeights): { heldout: number; judge: number } {\n const h = Number.isFinite(weights.heldout) && weights.heldout >= 0 ? weights.heldout : 0\n const j = Number.isFinite(weights.judge) && weights.judge >= 0 ? weights.judge : 0\n const sum = h + j\n if (sum <= 0) {\n throw new ValidationError(\n 'blend weights must have a positive sum (got heldout+judge <= 0) — cannot weight a composite by zero',\n )\n }\n return { heldout: h / sum, judge: j / sum }\n}\n\n/**\n * Compose the PRIMARY hidden-criteria pass rate with the SECONDARY judge\n * composite into the single score the leaderboard ranks on. Weights are\n * renormalized, so a solution that fails the hidden criteria is capped low no\n * matter how the judge felt about its style, while a stylistically-mediocre but\n * CORRECT solution still earns the bulk of the points. Both inputs are clamped\n * to [0,1] — a judge on a non-unit scale must be normalized by the caller first.\n */\nexport function blendHeldout(\n heldoutPassRate: number,\n judgeScore: number,\n weights: BlendWeights = defaultBlendWeights,\n): number {\n const w = normalizeWeights(weights)\n const heldout = clampUnit(heldoutPassRate)\n const judge = clampUnit(judgeScore)\n return w.heldout * heldout + w.judge * judge\n}\n\n/**\n * Wrap a judge's `score` so the `composite` it REPORTS is the held-out-weighted\n * blend. The judge still scores its quality dimensions (recorded, secondary),\n * but the composite that downstream selection/scorecard reads becomes\n * `blendHeldout(heldoutPassRate(artifact), judgeComposite, weights)`. The held-\n * out pass rate is read off the artifact via `heldoutPassRate` — already\n * computed before the judge runs — so no second grading pass is needed.\n *\n * Generic over the artifact type, inferred from `heldoutPassRate`, so it\n * composes with both a `campaign` `JudgeConfig.score` and a bare scoring\n * function. The input is the judge's `{ artifact, ... }` — any extra fields\n * (`scenario`, `signal`) ride through untouched via the index signature.\n */\nexport function withHeldoutBlend<TArtifact>(\n score: (input: JudgeScoreInput<TArtifact>) => JudgeScore | Promise<JudgeScore>,\n heldoutPassRate: (artifact: TArtifact) => number,\n weights: BlendWeights = defaultBlendWeights,\n): (input: JudgeScoreInput<TArtifact>) => Promise<JudgeScore> {\n return async (input: JudgeScoreInput<TArtifact>): Promise<JudgeScore> => {\n const base = await score(input)\n if (base.failed) return base\n const rate = clampUnit(heldoutPassRate(input.artifact))\n const composite = blendHeldout(rate, base.composite, weights)\n const w = normalizeWeights(weights)\n return {\n ...base,\n composite,\n notes:\n `composite=${composite.toFixed(3)} ` +\n `(held-out ${(rate * 100).toFixed(0)}% × ${w.heldout.toFixed(2)} + ` +\n `quality ${base.composite.toFixed(3)} × ${w.judge.toFixed(2)})` +\n (base.notes ? ` — ${base.notes}` : ''),\n }\n }\n}\n\nfunction clampUnit(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.max(0, Math.min(1, value))\n}\n","/**\n * Single-backend guard: assert the agent and the rubric judge run through the\n * SAME backend config, so the judge can't silently re-route through a\n * different (often paid) backend than the agent.\n *\n * The bug class: a consumer rewires the agent onto one backend but leaves the\n * judge bound to another. Cost is billed against the second backend, the eval\n * reports the first backend's model, and the data is unusable.\n * Four consumers hand-roll this comparison (legal at `canonical.ts:702-795`);\n * this is the one substrate copy.\n *\n * Complements `assertRealBackend` (records → stub vs real) and\n * `assertCrossFamily` (judge-ensemble family diversity): this one compares two\n * backend *configs* before the run.\n */\n\nimport { AgentEvalError } from '../errors'\n\n/**\n * Minimal backend-config shape the assertion reads. Consumers may pass richer\n * types — only these five fields are inspected.\n */\nexport interface BackendDescriptor {\n /** Backend route — e.g. `'tcloud' | 'cli-bridge' | 'sandbox' | 'direct-provider'`;\n * free-form for consumer extensibility. */\n kind: string\n /** Resolved base URL. Compared lexically (trailing slash stripped). */\n baseUrl: string\n /** Model id (with snapshot suffix). Compared lexically. */\n model: string\n /** Optional provider override. Compared when both set; flagged when only\n * one side sets it. */\n provider?: string\n /** Bearer token. Values are NEVER compared (security) — only that EITHER\n * both are set OR both are empty. Mismatched presence is a divergence. */\n apiKey?: string\n}\n\nexport interface AssertSingleBackendOptions {\n /** When true, ANY field divergence fails. When false (default), only\n * `kind` / `baseUrl` / `provider` / `apiKeyPresence` divergence throws —\n * a different judge `model` on the same route is allowed (the legal\n * pattern: a cheaper judge model). */\n strict?: boolean\n agentLabel?: string\n judgeLabel?: string\n}\n\nexport type SingleBackendField = 'kind' | 'baseUrl' | 'model' | 'provider' | 'apiKeyPresence'\n\nexport interface SingleBackendDivergence {\n field: SingleBackendField\n agent: string | undefined\n judge: string | undefined\n}\n\nexport interface SingleBackendReport {\n /** True when agent + judge agree per the configured strictness. */\n ok: boolean\n /** Every divergence detected (includes `model` even when non-blocking). */\n divergences: ReadonlyArray<SingleBackendDivergence>\n}\n\nexport class SingleBackendError extends AgentEvalError {\n constructor(\n message: string,\n public readonly report: SingleBackendReport,\n ) {\n super('backend_integrity', message)\n this.name = 'SingleBackendError'\n }\n}\n\nfunction stripSlash(url: string): string {\n return url.replace(/\\/+$/, '')\n}\n\n/**\n * Throw `SingleBackendError` when the agent and judge backends diverge in a\n * way that would re-route the judge through a different backend than the\n * agent. Returns the report so callers can log it in either case.\n */\nexport function assertSingleBackend(\n agent: BackendDescriptor,\n judge: BackendDescriptor,\n opts: AssertSingleBackendOptions = {},\n): SingleBackendReport {\n const divergences: SingleBackendDivergence[] = []\n\n if (agent.kind !== judge.kind) {\n divergences.push({ field: 'kind', agent: agent.kind, judge: judge.kind })\n }\n if (stripSlash(agent.baseUrl) !== stripSlash(judge.baseUrl)) {\n divergences.push({ field: 'baseUrl', agent: agent.baseUrl, judge: judge.baseUrl })\n }\n if (agent.model !== judge.model) {\n divergences.push({ field: 'model', agent: agent.model, judge: judge.model })\n }\n // provider: compare when both set; flag when exactly one is set.\n if (agent.provider !== judge.provider) {\n divergences.push({ field: 'provider', agent: agent.provider, judge: judge.provider })\n }\n // apiKey: presence only, never the value.\n const agentHasKey = Boolean(agent.apiKey)\n const judgeHasKey = Boolean(judge.apiKey)\n if (agentHasKey !== judgeHasKey) {\n divergences.push({\n field: 'apiKeyPresence',\n agent: agentHasKey ? 'set' : 'empty',\n judge: judgeHasKey ? 'set' : 'empty',\n })\n }\n\n const blocking = opts.strict ? divergences : divergences.filter((d) => d.field !== 'model')\n const ok = blocking.length === 0\n const report: SingleBackendReport = { ok, divergences }\n\n if (!ok) {\n const agentLabel = opts.agentLabel ?? 'agent'\n const judgeLabel = opts.judgeLabel ?? 'judge'\n const detail = blocking\n .map((d) => `${d.field}: ${agentLabel}=${d.agent ?? '∅'} vs ${judgeLabel}=${d.judge ?? '∅'}`)\n .join('; ')\n throw new SingleBackendError(\n `single-backend: ${agentLabel} and ${judgeLabel} backends diverge — the judge would ` +\n `re-route through a different backend than the agent (${detail})`,\n report,\n )\n }\n\n return report\n}\n","/**\n * Intent-match judge — \"did the agent build the right APP, ignoring\n * whether every feature is wired up?\"\n *\n * Distinct from {@link runSemanticConceptJudge} which scores per-concept\n * presence. The semantic judge can return 0/4 concepts present even\n * when the agent built a thoughtful, polished, on-brief app that just\n * lacks one or two features. The semantic judge can also return 4/4\n * present even when the agent shipped the wrong project (keyword-rich\n * stub).\n *\n * Intent-match asks ONE question:\n * \"Looking at the agent's work as a whole — independent of feature\n * coverage — is this an honest attempt at the user's request?\"\n *\n * Returns a 0–1 score and a 1-sentence evidence string. Use as a sanity\n * check on `completenessScore`-style metrics: if intent-match is high\n * and concept count is low, the agent built the right thing but is\n * missing features (ship and iterate). If intent-match is low, the\n * agent built the wrong thing (reject regardless of concept count).\n *\n * Soft-fails on LLM/JSON error (`available: false`) so callers can\n * treat failure as \"judge skipped.\"\n */\n\nimport type { ChatClient } from './analyst/chat-client'\nimport { paidJsonChat } from './chat-json-call'\nimport {\n CostLedger,\n type CostLedgerHandle,\n type CostReceipt,\n type CustomTokenPricing,\n} from './cost-ledger'\nimport type { LlmCallRequest } from './llm-client'\n\nexport const INTENT_MATCH_JUDGE_VERSION = 'intent-match-judge-v1-2026-04-24'\n\nexport interface IntentMatchInput {\n /** The full natural-language prompt the agent was handed. */\n userRequest: string\n /** Top-level source files from the agent's workdir. */\n sourceFiles: Array<{ path: string; content: string }>\n /** Rendered HTML the preview returned, when available. */\n servedHtml?: string\n /** Optional metadata to inject (id, vertical, difficulty). */\n artifactLabel?: string\n artifactDescription?: string\n}\n\nexport interface IntentMatchResult {\n kind: 'intent-match'\n version: string\n /** 0..1 — 1 = unmistakably the right app, 0 = unrelated to the brief. */\n score: number\n /** One-sentence rationale citing concrete evidence (file or HTML). */\n evidence: string\n durationMs: number\n costUsd: number | null\n available: boolean\n error?: string\n}\n\nexport interface IntentMatchOptions {\n /** Caller-owned transport. Required: agent-eval executes no paid model. */\n chat: ChatClient\n model?: string\n timeoutMs?: number\n maxTokens?: number\n maxSourceChars?: number\n maxPerFileChars?: number\n maxHtmlChars?: number\n /** Endpoint rates used when the transport reports no billed amount. */\n pricing?: CustomTokenPricing\n costLedger?: CostLedgerHandle\n costPhase?: string\n costTags?: Record<string, string>\n signal?: AbortSignal\n}\n\nconst DEFAULT_MODEL = 'claude-sonnet-4-6'\nconst DEFAULT_TIMEOUT = 300_000\nconst DEFAULT_MAX_TOKENS = 800\nconst DEFAULT_MAX_SOURCE = 25_000\nconst DEFAULT_MAX_PER_FILE = 12_000\nconst DEFAULT_MAX_HTML = 20_000\n\nconst INTENT_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n required: ['score', 'evidence'],\n properties: {\n score: { type: 'number', minimum: 0, maximum: 1 },\n evidence: { type: 'string', minLength: 10, maxLength: 400 },\n },\n}\n\nfunction truncate(body: string, cap: number, label: string): string {\n if (body.length <= cap) return body\n return `${body.slice(0, cap)}\\n… [truncated ${body.length - cap} chars of ${label}]`\n}\n\nfunction buildPrompt(\n input: IntentMatchInput,\n opts: { maxPerFileChars: number; maxSourceChars: number; maxHtmlChars: number },\n): string {\n const sourceBlob = input.sourceFiles\n .filter((f) => f.content.length <= opts.maxPerFileChars)\n .map((f) => `--- FILE: ${f.path} ---\\n${f.content}`)\n .join('\\n\\n')\n const html = input.servedHtml ?? ''\n\n return `You are evaluating whether an agent built THE RIGHT APP for a user request.\n\nYou are NOT scoring feature coverage. You are NOT scoring code quality.\nYou are answering ONE question: when a person looks at this work, do they\nsee an honest attempt at the user's request — or do they see the wrong\nproject entirely?\n\nUSER REQUEST:\n${input.userRequest}\n\n${input.artifactLabel ? `ARTIFACT METADATA:\\n name: ${input.artifactLabel}\\n description: ${input.artifactDescription ?? ''}\\n\\n` : ''}${html ? `SERVED HTML (what the preview returns):\\n${truncate(html, opts.maxHtmlChars, 'HTML')}\\n\\n` : ''}SOURCE FILES (the agent's workdir):\n${truncate(sourceBlob, opts.maxSourceChars, 'source')}\n\nScore 0–1:\n 1.0 — unmistakably the right app. Even with bugs, gaps, or missing\n features, a reviewer would say \"yes, this is what was asked for.\"\n 0.7 — recognizable. Domain matches; some required surface areas exist.\n A reviewer would say \"right direction, lots of work needed.\"\n 0.4 — partially related. Wrong framing or wrong product entirely but\n with some shared keywords or a tangential overlap.\n 0.0 — wrong project. The agent shipped something unrelated to the\n request (e.g. asked for an NFT mint page, shipped a generic\n landing page with zero NFT-related code).\n\nEvidence: one sentence citing the strongest concrete signal — a file\nname, a route, a rendered headline, a missing core surface. Don't\nrestate the request.\n\nExamples:\n - \"src/App.tsx renders <MintWidget /> with mint-1/mint-5 buttons and\n wagmi imports — clearly the requested NFT mint page.\" → 0.95\n - \"src/App.tsx is the default Vite React template; no\n mint/wallet/contract code in any file under src/.\" → 0.05\n\nReturn STRICT JSON. No prose outside.`\n}\n\n/**\n * Run the intent-match judge. Soft-fails to available=false on error.\n */\nexport async function runIntentMatchJudge(\n input: IntentMatchInput,\n options: IntentMatchOptions,\n): Promise<IntentMatchResult> {\n const start = Date.now()\n const opts = {\n chat: options.chat,\n model: options.model ?? options.chat.defaultModel ?? DEFAULT_MODEL,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT,\n maxTokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,\n maxSourceChars: options.maxSourceChars ?? DEFAULT_MAX_SOURCE,\n maxPerFileChars: options.maxPerFileChars ?? DEFAULT_MAX_PER_FILE,\n maxHtmlChars: options.maxHtmlChars ?? DEFAULT_MAX_HTML,\n ...(options.pricing ? { pricing: options.pricing } : {}),\n costLedger: options.costLedger ?? new CostLedger(),\n costPhase: options.costPhase ?? 'judge.intent-match',\n costTags: options.costTags ?? {},\n signal: options.signal ?? new AbortController().signal,\n }\n\n if (input.sourceFiles.length === 0 && !input.servedHtml) {\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: 0,\n evidence: 'no source files and no served HTML — nothing to evaluate',\n durationMs: 0,\n costUsd: null,\n available: false,\n error: 'no input artifact',\n }\n }\n\n let receipt: CostReceipt | undefined\n try {\n const request = {\n model: opts.model,\n messages: [\n {\n role: 'system' as const,\n content:\n 'You are a holistic code reviewer answering one question: did the agent build the right app for the user. Return strict JSON. No prose outside.',\n },\n { role: 'user' as const, content: buildPrompt(input, opts) },\n ],\n jsonSchema: { name: 'intent_match_judge', schema: INTENT_SCHEMA },\n temperature: 0,\n maxTokens: opts.maxTokens,\n timeoutMs: opts.timeoutMs,\n } satisfies LlmCallRequest\n const paid = await paidJsonChat<{ score: number; evidence: string }>({\n chat: opts.chat,\n request,\n ledger: opts.costLedger,\n channel: 'judge',\n phase: opts.costPhase,\n actor: 'intent-match',\n tags: opts.costTags,\n signal: opts.signal,\n ...(opts.pricing ? { pricing: opts.pricing } : {}),\n })\n receipt = paid.receipt\n if (!paid.succeeded) throw paid.error\n const { value } = paid\n\n const score = Math.max(0, Math.min(1, Number(value?.score ?? 0)))\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: Number(score.toFixed(3)),\n evidence: String(value?.evidence ?? '').slice(0, 400),\n durationMs: Date.now() - start,\n costUsd: paid.receipt.costUnknown ? null : paid.receipt.costUsd,\n available: true,\n }\n } catch (err) {\n return {\n kind: 'intent-match',\n version: INTENT_MATCH_JUDGE_VERSION,\n score: 0,\n evidence: '',\n durationMs: Date.now() - start,\n costUsd: receipt && !receipt.costUnknown ? receipt.costUsd : null,\n available: false,\n error: err instanceof Error ? err.message : String(err),\n }\n }\n}\n\n/**\n * Factory: pin the transport and options once, return a closure.\n */\nexport function createIntentMatchJudge(\n options: IntentMatchOptions,\n): (input: IntentMatchInput) => Promise<IntentMatchResult> {\n return (input) => runIntentMatchJudge(input, options)\n}\n","/**\n * Judge-ensemble reducer — folds N independent judge verdicts on the same\n * artifact into one aggregate score.\n *\n * The pattern every multi-model judge re-implements: run K uncorrelated judges\n * (different model families remove within-family bias), then reduce their\n * per-dimension verdicts to a single composite + an inter-rater disagreement\n * signal. This is the pure reduction — no LLM, no I/O — so a lift it produces\n * is attributable to the scores, not to where they came from.\n *\n * Fail-loud: a judge that errored or returned malformed output is recorded in\n * `failedJudges` with `perDimension: null`, never folded into a zero. If EVERY\n * judge failed the reducer throws — a silent zero here would corrupt the result.\n */\n\nimport type { LlmUsage } from './llm-client'\nimport { clamp01 } from './run-score'\nimport { weightedComposite } from './statistics'\n\n/** One judge's verdict. `perDimension: null` ⇒ that judge call failed (threw or\n * returned malformed output) — recorded, never folded into a zero. */\nexport interface JudgeVerdict<D extends string = string> {\n /** Judge identity (typically the model id) — the `perJudge` / `failedJudges` key. */\n model: string\n /** Per-dimension scores, or `null` when the judge failed. */\n perDimension: Record<D, number> | null\n /** Optional one-line rationale; the first non-empty one becomes the aggregate's. */\n rationale?: string\n /** Optional reported cost, committed by the caller's CostLedger. */\n costUsd?: number\n /** Optional provider usage, committed by the caller's CostLedger. */\n usage?: LlmUsage\n /** Optional per-dimension reasoning/evidence. Carried through to\n * `EnsembleAggregate.verdicts` verbatim — never folded into the math. */\n detail?: Partial<Record<D, { reasoning?: string; evidence?: string }>>\n}\n\n/** The aggregated ensemble result. */\nexport interface EnsembleAggregate<D extends string = string> {\n /** Mean over SURVIVING judges, per dimension (absent-everywhere ⇒ 0). */\n perDimension: Record<D, number>\n /** Weighted mean of `perDimension` (uniform unless `weights` given). */\n composite: number\n /** Each surviving judge's clamped per-dimension scores, for trace drill-down. */\n perJudge: Record<string, Record<D, number>>\n /** Max over dimensions of (max − min) across survivors — the inter-rater signal. */\n maxDisagreement: number\n /** Models whose verdict was null (failed). */\n failedJudges: string[]\n /** First non-empty survivor rationale, or `'llm-judge'`. */\n rationale: string\n /** The input verdicts, verbatim — drill-down to raw scores, `detail`\n * reasoning/evidence, and per-verdict cost without re-running judges. */\n verdicts: JudgeVerdict<D>[]\n}\n\n/**\n * Reduce per-judge verdicts to one aggregate. Generic over the rubric: pass the\n * stable-ordered `dimensionKeys` the judges scored.\n *\n * - Per-dimension score = mean over surviving judges (out-of-range clamped to [0,1]).\n * - `composite` = `weightedComposite` of `perDimension`. No `weights` ⇒ uniform\n * over every dimension. A partial `weights` map selects AND weights exactly the\n * named dimensions (others excluded from the composite) — the substrate's\n * sum-normalized weighting, not re-implemented here.\n * - Throws if `verdicts` or `dimensionKeys` is empty, or if every judge failed.\n */\nexport function aggregateJudgeVerdicts<D extends string>(\n verdicts: readonly JudgeVerdict<D>[],\n dimensionKeys: readonly D[],\n weights?: Partial<Record<D, number>>,\n): EnsembleAggregate<D> {\n if (verdicts.length === 0) {\n throw new Error('aggregateJudgeVerdicts: no verdicts to aggregate')\n }\n if (dimensionKeys.length === 0) {\n throw new Error('aggregateJudgeVerdicts: dimensionKeys is empty')\n }\n\n const perJudge: Record<string, Record<D, number>> = {}\n const failedJudges: string[] = []\n const dimAcc = {} as Record<D, number[]>\n for (const d of dimensionKeys) dimAcc[d] = []\n let rationale = ''\n\n // Same model sampled k times (best-of-N judging) gets keys 'm', 'm#2',\n // 'm#3'… so repeat votes land as distinct perJudge/failedJudges entries\n // instead of overwriting each other.\n const seenCount = new Map<string, number>()\n const keyFor = (model: string): string => {\n const n = (seenCount.get(model) ?? 0) + 1\n seenCount.set(model, n)\n return n === 1 ? model : `${model}#${n}`\n }\n\n for (const v of verdicts) {\n const key = keyFor(v.model)\n if (!v.perDimension) {\n failedJudges.push(key)\n continue\n }\n const dims = {} as Record<D, number>\n for (const d of dimensionKeys) dims[d] = clamp01(Number(v.perDimension[d]))\n perJudge[key] = dims\n for (const d of dimensionKeys) dimAcc[d].push(dims[d])\n if (!rationale && typeof v.rationale === 'string' && v.rationale) rationale = v.rationale\n }\n\n if (failedJudges.length === verdicts.length) {\n throw new Error(`aggregateJudgeVerdicts: all ${verdicts.length} judges failed`)\n }\n\n const perDimension = {} as Record<D, number>\n for (const d of dimensionKeys) {\n const vals = dimAcc[d]\n perDimension[d] = vals.length === 0 ? 0 : vals.reduce((s, x) => s + x, 0) / vals.length\n }\n\n let maxDisagreement = 0\n for (const d of dimensionKeys) {\n const vals = dimAcc[d]\n if (vals.length < 2) continue\n const spread = Math.max(...vals) - Math.min(...vals)\n if (spread > maxDisagreement) maxDisagreement = spread\n }\n\n const w: Record<string, number> = {}\n if (weights) {\n for (const [d, weight] of Object.entries(weights)) {\n if (weight !== undefined) w[d] = weight as number\n }\n } else {\n for (const d of dimensionKeys) w[d] = 1 / dimensionKeys.length\n }\n const composite = weightedComposite({ dims: perDimension, weights: w }).composite\n\n return {\n perDimension,\n composite,\n perJudge,\n maxDisagreement,\n failedJudges,\n rationale: rationale || 'llm-judge',\n verdicts: [...verdicts],\n }\n}\n","/**\n * Wrap a single judge LLM call with retry, optional fallback-model\n * rotation, exponential backoff, and a typed `JudgeRetryOutcome`. Callers\n * MUST inspect `succeeded` before using `value`; on failure the library\n * returns `value: null` rather than substituting a default, so a judge\n * abort cannot silently corrupt a downstream composite.\n *\n * Reporting contract: callers ship `TrialResult.judgeSucceeded = succeeded`\n * and `TrialResult.judgeAttempts = attempts` so `aggregateTrialsByMode`\n * with `mode: 'exclude-failed'` drops the trial.\n */\n\nimport { backoffMs, isTransientLlmError } from './llm-client'\n\n/** Retry policy for judge LLM calls. */\nexport interface JudgeRetryPolicy {\n /** Max attempts per model. Default 3 (one initial + two retries). */\n maxAttempts?: number\n /** Per-attempt timeout in ms. Default 300_000. */\n timeoutMs?: number\n /**\n * Models to try, in order. The first model is the primary; subsequent\n * models are fallbacks invoked only when ALL retries on the previous\n * model have been exhausted. Example: `['claude-code/sonnet', 'kimi-code/k2p6']`\n * runs claude-code up to maxAttempts times, then falls back to kimi.\n * If omitted, the caller's judge function controls model selection and\n * the retries apply to that single model.\n */\n models?: readonly string[]\n /** Exponential backoff function, default `attempt → min(500 * 2^attempt, 16_000)`. */\n backoffMs?: (attempt: number) => number\n /**\n * Predicate deciding whether an error should trigger a retry. Defaults to\n * `isTransientLlmError` — the package-wide classifier shared with\n * `callLlm` — which retries aborts/timeouts, network faults, HTTP/2\n * transport faults, and any `LlmCallError` with status in {429,502,503,504}.\n * JSON-parse and schema-rejection errors are NOT retriable (the model\n * needs prompt adjustment, not another shot).\n */\n isRetryable?: (err: unknown) => boolean\n}\n\n/** Outcome of a wrapped judge invocation. */\nexport interface JudgeRetryOutcome<T> {\n /** The judge's returned value when `succeeded === true`. */\n value: T | null\n /** True iff one of the attempts completed without throwing. */\n succeeded: boolean\n /** Total attempts made across all models. */\n attempts: number\n /** Which model the successful attempt used (when succeeded). */\n modelUsed?: string\n /** Last error captured when `succeeded === false`. */\n error?: Error\n /** Per-attempt error log for forensics. */\n attemptErrors: Array<{ attempt: number; model: string; error: string }>\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 3\nconst DEFAULT_TIMEOUT_MS = 300_000\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Wrap a judge call with retry + fallback-model + typed outcome semantics.\n *\n * The `judgeFn` signature is `(model: string, signal: AbortSignal) => Promise<T>`.\n * The signal will be aborted at `timeoutMs`. Callers should pass the signal\n * to their underlying fetch/SDK call so the abort actually fires.\n *\n * Returns a typed outcome — callers MUST inspect `succeeded` before using\n * `value`. The library refuses to default to a silent zero score because a\n * synthetic zero is indistinguishable from a real low score downstream.\n */\nexport async function withJudgeRetry<T>(\n judgeFn: (model: string, signal: AbortSignal) => Promise<T>,\n policy: JudgeRetryPolicy = {},\n): Promise<JudgeRetryOutcome<T>> {\n const maxAttempts = policy.maxAttempts ?? DEFAULT_MAX_ATTEMPTS\n const timeoutMs = policy.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const backoff = policy.backoffMs ?? backoffMs\n const isRetryable = policy.isRetryable ?? isTransientLlmError\n const models =\n policy.models && policy.models.length > 0 ? policy.models : [undefined as unknown as string]\n\n let totalAttempts = 0\n const attemptErrors: JudgeRetryOutcome<T>['attemptErrors'] = []\n let lastError: Error | undefined\n\n for (const model of models) {\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n totalAttempts += 1\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(new Error('TimeoutError')), timeoutMs)\n try {\n const value = await judgeFn(model as string, controller.signal)\n clearTimeout(timer)\n return {\n value,\n succeeded: true,\n attempts: totalAttempts,\n modelUsed: model,\n attemptErrors,\n }\n } catch (err) {\n clearTimeout(timer)\n const errObj = err instanceof Error ? err : new Error(String(err))\n lastError = errObj\n attemptErrors.push({\n attempt: totalAttempts,\n model: model ?? '(default)',\n error: errObj.message,\n })\n if (!isRetryable(errObj)) {\n // Non-retriable (e.g., JSON parse, schema rejection): break out of\n // attempts on this model AND skip the fallback rotation — a\n // permanent error here will be permanent on the fallback too.\n return {\n value: null,\n succeeded: false,\n attempts: totalAttempts,\n error: errObj,\n attemptErrors,\n }\n }\n if (attempt < maxAttempts - 1) {\n await sleep(backoff(attempt))\n }\n }\n }\n // Exhausted attempts on this model — fall through to next model in the\n // rotation (if any). The backoff between MODEL rotations is the same\n // as the last per-attempt backoff (already slept above).\n }\n\n return {\n value: null,\n succeeded: false,\n attempts: totalAttempts,\n error: lastError,\n attemptErrors,\n }\n}\n","/**\n * Multi-model judge panel — `ensembleJudge` builds a campaign `JudgeConfig`\n * that fans one artifact out to K judge models and reduces their verdicts\n * through `aggregateJudgeVerdicts` (src/judge-ensemble.ts).\n *\n * The panel is the fail-loud composition of the substrate's existing judge\n * primitives:\n * - `assertCrossFamily` (construction-time) — a single-family panel is\n * correlated bias, not independent signal.\n * - `withJudgeRetry` (per model, opt-in) — transient-fault retry with a\n * typed outcome; a judge that exhausts retries is recorded as failed,\n * never folded into a zero.\n * - `aggregateJudgeVerdicts` — the pure reducer; throws when EVERY judge\n * failed so a silent zero can't reach the gate.\n *\n * The returned `JudgeScore` is on the campaign [0,1] scale and carries the\n * ensemble extras (`maxDisagreement`, `failedJudges`, `perJudge`) declared\n * on the canonical `JudgeScore` in src/campaign/types.ts.\n */\n\nimport type { JudgeConfig, JudgeScore } from './campaign/types'\nimport {\n CostLedger,\n type CostLedgerHandle,\n type CostReceiptInput,\n type MaximumCharge,\n} from './cost-ledger'\nimport { aggregateJudgeVerdicts, type JudgeVerdict } from './judge-ensemble'\nimport { assertCrossFamily } from './judge-families'\nimport { type JudgeRetryPolicy, withJudgeRetry } from './judge-retry'\nimport { contentHash } from './verdict-cache'\n\nexport interface EnsembleJudgeOptions<D extends string> {\n /** Judge name — becomes the returned `JudgeConfig.name`. */\n name: string\n /** Rubric dimensions every model scores. Keys of the verdict's `perDimension`. */\n dimensions: D[]\n /** Judge model ids — one `scoreWith` call per entry. List a model twice to\n * sample it twice (votes are suffix-keyed `model#2` so none overwrite). */\n models: string[]\n /** Explicit scoring revision for closure state not visible in the static panel config. */\n judgeVersion?: string\n /**\n * Score the artifact with one model. Throw (or reject) on failure — the\n * panel records that model as a failed judge; it is never folded into a\n * zero. Verdict scores are clamped to [0,1] by the reducer.\n */\n scoreWith: (\n model: string,\n input: { artifact: unknown; scenario?: unknown; signal: AbortSignal },\n ) => Promise<JudgeVerdict<D>>\n /** Recover usage from a failed provider response when its error retains one. */\n receiptFromError?: (error: Error, model: string) => CostReceiptInput | undefined\n /** Used by direct score calls; campaigns supply their run ledger in score(). */\n costLedger?: CostLedgerHandle\n /** Required per model when the shared ledger has a dollar cap. */\n maximumCharge?: MaximumCharge | ((model: string) => MaximumCharge)\n /**\n * Per-model retry policy, applied via `withJudgeRetry`. The panel's\n * `models` list drives the fan-out, so `retry.models` (the fallback\n * rotation) is overridden to each panel model in turn.\n */\n retry?: JudgeRetryPolicy\n /** Enforce `assertCrossFamily` over `models` at construction. Default true.\n * Opt out only for deliberate single-family panels (e.g. self-consistency\n * sampling of one model).\n *\n * Construction-time only, over the REQUESTED ids: it cannot see a gateway\n * that answers several ids from one provider. `scoreWith` owns the served\n * side — check the id the provider echoed with `assertServedModel`\n * (./integrity/served-model) inside your judge call. */\n crossFamily?: boolean\n /** Composite weights forwarded to `aggregateJudgeVerdicts`: a partial map\n * selects AND weights exactly the named dimensions. Omit for uniform. */\n weights?: Partial<Record<D, number>>\n}\n\n/**\n * Build a campaign-shaped `JudgeConfig` whose `score()` runs every panel\n * model in parallel and reduces the surviving verdicts to one canonical\n * `JudgeScore` in [0,1].\n *\n * Failure semantics: a model whose `scoreWith` throws (or exhausts `retry`)\n * lands in `failedJudges` and is excluded from the means. When EVERY model\n * fails, `aggregateJudgeVerdicts` throws — the campaign engine records a\n * failed cell instead of averaging a fabricated zero.\n */\nexport function ensembleJudge<D extends string>(\n opts: EnsembleJudgeOptions<D>,\n): JudgeConfig<unknown> {\n if (opts.models.length === 0) {\n throw new Error(`ensembleJudge '${opts.name}': models is empty — nothing to score with`)\n }\n if (opts.dimensions.length === 0) {\n throw new Error(`ensembleJudge '${opts.name}': dimensions is empty — nothing to score`)\n }\n if (opts.crossFamily !== false) {\n assertCrossFamily(opts.models)\n }\n const declaredJudgeVersion = opts.judgeVersion?.trim()\n if (opts.judgeVersion !== undefined && !declaredJudgeVersion) {\n throw new Error(`ensembleJudge '${opts.name}': judgeVersion must be non-empty when provided`)\n }\n const judgeVersion =\n declaredJudgeVersion ??\n contentHash({\n kind: 'ensembleJudge',\n models: opts.models,\n dimensions: opts.dimensions,\n weights: opts.weights ?? null,\n crossFamily: opts.crossFamily ?? true,\n maximumCharge:\n typeof opts.maximumCharge === 'function'\n ? opts.maximumCharge.toString()\n : (opts.maximumCharge ?? null),\n retry: opts.retry\n ? {\n maxAttempts: opts.retry.maxAttempts ?? null,\n timeoutMs: opts.retry.timeoutMs ?? null,\n models: opts.retry.models ?? null,\n backoffMs: opts.retry.backoffMs?.toString() ?? null,\n isRetryable: opts.retry.isRetryable?.toString() ?? null,\n }\n : null,\n scoreWith: opts.scoreWith.toString(),\n })\n const directCostLedger = opts.costLedger ?? new CostLedger()\n\n const scoreOne = async (args: {\n model: string\n artifact: unknown\n scenario?: unknown\n signal: AbortSignal\n costLedger: CostLedgerHandle\n costPhase: string\n costTags?: Record<string, string>\n }): Promise<JudgeVerdict<D>> => {\n const outcome = await withJudgeRetry(\n async (model, retrySignal) => {\n const paid = await args.costLedger.runPaidCall({\n channel: 'judge',\n phase: args.costPhase,\n actor: `${opts.name}.${model}`,\n model,\n maximumCharge:\n typeof opts.maximumCharge === 'function'\n ? opts.maximumCharge(model)\n : opts.maximumCharge,\n tags: args.costTags,\n signal: AbortSignal.any([args.signal, retrySignal]),\n execute: (signal) =>\n opts.scoreWith(model, { artifact: args.artifact, scenario: args.scenario, signal }),\n receipt: (verdict) => {\n const cachedTokens = verdict.usage?.cachedPromptTokens ?? 0\n const usageUnknown = !verdict.usage || verdict.usage.captured === false\n return {\n model: verdict.model,\n inputTokens: Math.max(0, (verdict.usage?.promptTokens ?? 0) - cachedTokens),\n outputTokens: verdict.usage?.completionTokens ?? 0,\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\n usageUnknown,\n ...(verdict.costUsd === undefined ? {} : { actualCostUsd: verdict.costUsd }),\n }\n },\n receiptFromError: (error) => opts.receiptFromError?.(error, model),\n })\n if (!paid.succeeded) throw paid.error\n return paid.value\n },\n opts.retry\n ? { ...opts.retry, models: [args.model] }\n : { maxAttempts: 1, models: [args.model], isRetryable: () => false },\n )\n if (!outcome.succeeded || outcome.value === null) {\n return {\n model: args.model,\n perDimension: null,\n rationale: outcome.error?.message ?? 'judge failed',\n }\n }\n return outcome.value\n }\n\n return {\n name: opts.name,\n dimensions: opts.dimensions.map((d) => ({ key: d, description: d })),\n judgeVersion,\n async score({\n artifact,\n scenario,\n signal,\n costLedger,\n costPhase,\n costTags,\n }): Promise<JudgeScore> {\n const verdicts = await Promise.all(\n opts.models.map((model) =>\n scoreOne({\n model,\n artifact,\n scenario,\n signal,\n costLedger: costLedger ?? directCostLedger,\n costPhase: costPhase ?? 'judge',\n costTags,\n }),\n ),\n )\n // All-failed throws here — propagate so the engine records a failed cell.\n const agg = aggregateJudgeVerdicts(verdicts, opts.dimensions, opts.weights)\n const score: JudgeScore = {\n dimensions: agg.perDimension,\n composite: agg.composite,\n notes: agg.rationale,\n maxDisagreement: agg.maxDisagreement,\n perJudge: agg.perJudge,\n }\n if (agg.failedJudges.length > 0) score.failedJudges = agg.failedJudges\n return score\n },\n }\n}\n","/**\n * Keyword-coverage judge — baseline complement to the semantic concept\n * judge.\n *\n * Where {@link runSemanticConceptJudge} uses an LLM to read source code\n * and decide whether a concept is REALLY implemented (not just\n * keyword-mentioned), this judge does the cheap, deterministic version:\n * fetch the served preview, concatenate every linked CSS/JS asset, and\n * substring-match each expected concept's keywords against the\n * concatenated haystack. Optional `requiredElement` selector adds a\n * structural gate so \"supply counter\" can require an actual `<input>` or\n * `<table>`, not just a comment containing the word.\n *\n * Use both judges. Keyword coverage is a fast 0-cost gate — a stub page\n * with the right keywords passes here, fails the semantic judge. Score\n * divergence between the two is itself a signal: high keyword coverage\n * + low semantic = \"the agent slapped the right words on the right\n * scaffold but didn't wire any of it up.\"\n *\n * Pure functions, soft-fail on fetch error, no LLM dependency.\n */\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface KeywordConceptSpec {\n name: string\n keywords: string[]\n /**\n * Optional CSS selector that must match in the HTML for the concept\n * to count as present. Tiny subset:\n * - `tag` (e.g. `form`)\n * - `tag[attr=\"value\"]` (e.g. `input[type=\"number\"]`)\n * - `tag[attr]` (presence only)\n * Anything more complex is rejected with `null` (treated as\n * \"unenforced\", not \"failed\").\n */\n requiredElement?: string\n}\n\nexport interface KeywordCoverageFinding {\n concept: string\n found: boolean\n matchedKeywords: string[]\n /** True iff the optional requiredElement selector matched; null when no selector. */\n requiredElementPresent: boolean | null\n}\n\nexport interface KeywordCoverageResult {\n /** 0..1 share of concepts satisfied. */\n score: number\n presentCount: number\n totalCount: number\n findings: KeywordCoverageFinding[]\n durationMs: number\n /** Total bytes assembled across html + linked assets. */\n totalAssembledBytes: number\n /** Soft-failure reason if the audit couldn't run. */\n error?: string\n}\n\nexport interface KeywordCoverageOptions {\n /** Override fetch implementation — for tests. */\n fetch?: typeof fetch\n /** Per-asset fetch timeout (default 3s). */\n assetTimeoutMs?: number\n /** Initial-HTML fetch timeout (default 5s). */\n htmlTimeoutMs?: number\n}\n\n// ─── Selector matcher ──────────────────────────────────────────────────\n\n/**\n * Element-presence check using a tiny CSS-selector subset. Returns\n * null when the selector isn't supported — caller treats that as\n * \"unenforced\" rather than \"failed.\"\n */\nexport function htmlContainsElement(html: string, selector: string): boolean | null {\n const tagOnly = /^([a-zA-Z][\\w-]*)$/.exec(selector)\n if (tagOnly) {\n const re = new RegExp(`<${tagOnly[1]}\\\\b`, 'i')\n return re.test(html)\n }\n const tagAttrEq = /^([a-zA-Z][\\w-]*)\\[([\\w-]+)\\s*=\\s*[\"']?([^\"'\\]]+)[\"']?\\]$/.exec(selector)\n if (tagAttrEq) {\n const [, tag, attr, value] = tagAttrEq\n const re = new RegExp(\n `<${tag}\\\\b[^>]*\\\\b${attr}\\\\s*=\\\\s*[\"']${value!.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\"']`,\n 'i',\n )\n return re.test(html)\n }\n const tagAttrPresence = /^([a-zA-Z][\\w-]*)\\[([\\w-]+)\\]$/.exec(selector)\n if (tagAttrPresence) {\n const [, tag, attr] = tagAttrPresence\n const re = new RegExp(`<${tag}\\\\b[^>]*\\\\b${attr}\\\\b`, 'i')\n return re.test(html)\n }\n return null\n}\n\n// ─── Asset extraction ─────────────────────────────────────────────────\n\n/**\n * Pull every `<link rel=stylesheet href>` and `<script src>` from a\n * raw HTML body. Returns absolute URLs resolved against `baseUrl`.\n * Permissive regex — agent-authored markup doesn't always quote\n * attributes the same way.\n */\nexport function extractAssetUrls(html: string, baseUrl: string): string[] {\n const urls = new Set<string>()\n const linkRe = /<link\\b[^>]*\\bhref\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi\n const scriptRe = /<script\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi\n for (const re of [linkRe, scriptRe]) {\n let match: RegExpExecArray | null = re.exec(html)\n while (match !== null) {\n const raw = match[1]!\n try {\n urls.add(new URL(raw, baseUrl).toString())\n } catch {\n // unresolvable refs (e.g. data: URLs) — skip\n }\n match = re.exec(html)\n }\n }\n return Array.from(urls)\n}\n\n// ─── Coverage scorer ──────────────────────────────────────────────────\n\n/**\n * Score expected concepts against an already-fetched HTML payload + any\n * pre-fetched CSS/JS assets. Use when the runner has the bytes in hand\n * and doesn't want a fresh HTTP round-trip — e.g. sandbox runtime where\n * the preview content was fetched via curl from inside the container.\n */\nexport function runKeywordCoverageJudge(\n html: string,\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n assets: ReadonlyArray<string> = [],\n): KeywordCoverageResult {\n const start = Date.now()\n if (expectedConcepts.length === 0) {\n return {\n score: 0,\n presentCount: 0,\n totalCount: 0,\n findings: [],\n durationMs: 0,\n totalAssembledBytes: 0,\n }\n }\n const haystack = `${html}\\n${assets.join('\\n')}`.toLowerCase()\n const findings: KeywordCoverageFinding[] = expectedConcepts.map((concept) => {\n const matchedKeywords: string[] = []\n for (const kw of concept.keywords) {\n if (haystack.includes(kw.toLowerCase())) matchedKeywords.push(kw)\n }\n const requiredElementPresent = concept.requiredElement\n ? htmlContainsElement(html, concept.requiredElement)\n : null\n const passesElementGate = requiredElementPresent === null || requiredElementPresent === true\n const found = matchedKeywords.length > 0 && passesElementGate\n return { concept: concept.name, found, matchedKeywords, requiredElementPresent }\n })\n const presentCount = findings.filter((f) => f.found).length\n return {\n score: presentCount / expectedConcepts.length,\n presentCount,\n totalCount: expectedConcepts.length,\n findings,\n durationMs: Date.now() - start,\n totalAssembledBytes: haystack.length,\n }\n}\n\n/**\n * URL-fetch flavor — GET the preview, parallel-fetch every linked\n * stylesheet + script (with bounded timeouts, soft-fail individually),\n * then score via {@link runKeywordCoverageJudge}.\n */\nexport async function runKeywordCoverageJudgeUrl(\n previewUrl: string,\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n options: KeywordCoverageOptions = {},\n): Promise<KeywordCoverageResult> {\n const start = Date.now()\n const fetchFn = options.fetch ?? globalThis.fetch\n const htmlTimeout = options.htmlTimeoutMs ?? 5_000\n const assetTimeout = options.assetTimeoutMs ?? 3_000\n\n if (expectedConcepts.length === 0) {\n return {\n score: 0,\n presentCount: 0,\n totalCount: 0,\n findings: [],\n durationMs: 0,\n totalAssembledBytes: 0,\n }\n }\n\n let html = ''\n try {\n const resp = await fetchFn(previewUrl, {\n redirect: 'follow',\n signal: AbortSignal.timeout(htmlTimeout),\n })\n if (!resp.ok) {\n return softFail(expectedConcepts, start, `preview HTTP ${resp.status}`)\n }\n html = await resp.text()\n } catch (err) {\n return softFail(expectedConcepts, start, err instanceof Error ? err.message : String(err))\n }\n\n const assetUrls = extractAssetUrls(html, previewUrl)\n const assetBodies = await Promise.all(\n assetUrls.map(async (u) => {\n try {\n const r = await fetchFn(u, {\n redirect: 'follow',\n signal: AbortSignal.timeout(assetTimeout),\n })\n if (!r.ok) return ''\n return await r.text()\n } catch {\n return ''\n }\n }),\n )\n\n return runKeywordCoverageJudge(html, expectedConcepts, assetBodies)\n}\n\nfunction softFail(\n expectedConcepts: ReadonlyArray<KeywordConceptSpec>,\n start: number,\n error: string,\n): KeywordCoverageResult {\n return {\n score: 0,\n presentCount: 0,\n totalCount: expectedConcepts.length,\n findings: expectedConcepts.map((c) => ({\n concept: c.name,\n found: false,\n matchedKeywords: [],\n requiredElementPresent: null,\n })),\n durationMs: Date.now() - start,\n totalAssembledBytes: 0,\n error,\n }\n}\n","/**\n * Multi-layer verifier — ordered pipeline of verification layers.\n *\n * A DAG of layers (install → typecheck → build → lint → serve → semantic → …)\n * with dependency-based skip, per-layer findings, soft-fail semantics, and an\n * aggregated `blendedScore` across all passed layers.\n *\n * Use when you want:\n * - ordered stages where a failing upstream stage skips downstream ones\n * - each stage produces rich `findings` (severity + message + evidence)\n * - a single composite score across stages with per-stage weights\n * - soft-fail stages whose failure doesn't abort the pipeline\n *\n * A layer body is an arbitrary async function, so independent checks that need\n * no ordering run as one layer that resolves them in parallel.\n */\n\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport type LayerStatus = 'pass' | 'fail' | 'skipped' | 'error' | 'timeout'\n\nexport type Severity = 'critical' | 'major' | 'minor' | 'info'\n\nexport interface Finding {\n severity: Severity\n message: string\n evidence?: string\n /** Optional layer name the finding belongs to (set by the verifier if omitted). */\n layer?: string\n /**\n * Free-form structured payload — a layer attaches its toolchain\n * (`{ adapter: 'pnpm' }`), a judge attaches evidence pointers, etc.\n * Renderers MAY interrogate; agent-eval primitives never assume shape.\n */\n detail?: Record<string, unknown>\n}\n\nexport interface LayerResult {\n layer: string\n status: LayerStatus\n /** Origin of an `error` or `timeout`. Defaults to `execution`. */\n errorSource?: 'execution' | 'judge'\n /** 0..1 score, optional — layers that don't produce a numeric score omit. */\n score?: number\n durationMs: number\n findings: Finding[]\n /** Short human-readable summary (one line). */\n reason?: string\n /**\n * Numeric layer-level diagnostics: error counts, warning counts,\n * cyclomatic complexity, total adapter wall-time, etc. Keyed by\n * diagnostic name; null = \"diagnostic not applicable / not measured.\"\n * Renderers that know the keys can display them; ones that don't,\n * ignore. Free-form on purpose — consumers type the value shape in\n * their own namespace.\n */\n diagnostics?: Record<string, number | null>\n /** Any rich per-layer detail — rendered as-is by consumers that know the layer. */\n detail?: Record<string, unknown>\n}\n\nexport interface VerifyContext<Env = unknown> {\n /** Per-run opaque context the caller provides. Layers destructure what they need. */\n env: Env\n /** Previously-computed results from layers that already ran. */\n prior: Record<string, LayerResult>\n /** Signal — if aborted, layers MUST bail within reasonable wall. */\n signal: AbortSignal\n}\n\nexport interface Layer<Env = unknown> {\n name: string\n /** Origin assigned when this layer errors or times out. Defaults to `execution`. */\n errorSource?: 'execution' | 'judge'\n /** Stages that must have `status: 'pass'` before this layer runs. */\n dependsOn?: string[]\n /**\n * Weight in the composite `blendedScore`. Default 1.0. Layers with weight 0\n * contribute findings but not score.\n */\n weight?: number\n /**\n * If true, a `fail` status contributes to `blendedScore` (as 0) instead of\n * being dropped — use for layers whose failure is a real signal. Default:\n * fail drops from numerator + denominator, matching VB's existing semantics.\n */\n failContributesToScore?: boolean\n /** Optional per-layer wall-cap in ms. Honored by the verifier (AbortSignal). */\n capMs?: number\n run: (ctx: VerifyContext<Env>) => Promise<LayerResult> | LayerResult\n}\n\nexport interface VerifyOptions<Env = unknown> {\n env: Env\n /**\n * Overall wall cap. Default: sum of layer capMs, or Infinity if any layer\n * omits a cap. The verifier short-circuits remaining layers on overall cap.\n */\n overallCapMs?: number\n /** Called with each layer result as it completes. */\n onLayer?: (result: LayerResult) => void\n}\n\n/** Extends the substrate verdict spine: `valid` = `allPass`; `score` is the\n * complete task score or 0 when the configured scoring panel was incomplete. */\nexport interface VerificationReport extends DefaultVerdict {\n layers: LayerResult[]\n passCount: number\n failCount: number\n skippedCount: number\n errorCount: number\n /** True iff the configured scoring panel completed and every layer passed. */\n allPass: boolean\n /**\n * Diagnostic weighted mean across contributing layers. This may represent a\n * partial panel. It is 0 when no layer contributed.\n */\n blendedScore: number\n /**\n * Complete task-quality measurement.\n * Present when at least one layer produced a valid score, every other layer\n * completed successfully or contributed an explicit scored failure, and no\n * result is missing because of a failure, skip, error, or timeout.\n * Use this field, not `blendedScore`, when creating task labels.\n */\n taskScore?: number\n durationMs: number\n startedAt: string\n finishedAt: string\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────\n\n/**\n * Grade a semantic-concept-style judge result into a single layer status.\n *\n * Pass when overall score >= threshold AND no critical-severity concept gap.\n * Fail otherwise. Use inside a `Layer.run` when wrapping a concept judge.\n *\n * Generalized from VerticalBench H3 fix: `failingConcepts.length === 0` was\n * too strict — a single concept at 6/10 failed the entire layer despite\n * overall score being >= 0.7. Now we trust the judge's own `severity` field:\n * `critical` findings veto; `major`/`minor` reduce the score but don't veto.\n */\nexport function gradeSemanticStatus(input: {\n score: number\n findings: Array<{ severity: Severity; present?: boolean; score?: number }>\n available: boolean\n threshold?: number\n}): LayerStatus {\n if (!input.available) return 'error'\n const threshold = input.threshold ?? 0.7\n const criticalGaps = input.findings.filter(\n (f) => f.severity === 'critical' && (f.present === false || (f.score ?? 0) < 7),\n )\n return input.score >= threshold && criticalGaps.length === 0 ? 'pass' : 'fail'\n}\n\n// ─── Verifier ───────────────────────────────────────────────────────────\n\n/**\n * Ordered DAG of verification layers with dependency-based skipping, per-layer findings, soft-fail semantics, and a blended composite score across all passed layers.\n */\nexport class MultiLayerVerifier<Env = unknown> {\n constructor(private readonly layers: Layer<Env>[]) {\n const seen = new Set<string>()\n for (const l of layers) {\n if (seen.has(l.name)) throw new Error(`MultiLayerVerifier: duplicate layer name \"${l.name}\"`)\n seen.add(l.name)\n }\n for (const l of layers) {\n for (const dep of l.dependsOn ?? []) {\n if (!seen.has(dep)) {\n throw new Error(\n `MultiLayerVerifier: layer \"${l.name}\" depends on \"${dep}\" which is not registered`,\n )\n }\n }\n }\n }\n\n async run(opts: VerifyOptions<Env>): Promise<VerificationReport> {\n const startedAtMs = Date.now()\n const startedAt = new Date(startedAtMs).toISOString()\n const controller = new AbortController()\n const overallCap = opts.overallCapMs\n const overallTimer =\n overallCap != null\n ? setTimeout(() => controller.abort(new Error('overall cap exceeded')), overallCap)\n : null\n\n const results: LayerResult[] = []\n const byName: Record<string, LayerResult> = {}\n\n try {\n for (const layer of this.layers) {\n // Skip if any dependency didn't pass.\n const unmet = (layer.dependsOn ?? []).filter((d) => byName[d]?.status !== 'pass')\n if (unmet.length > 0) {\n const skipped: LayerResult = {\n layer: layer.name,\n status: 'skipped',\n durationMs: 0,\n findings: [],\n reason: `skipped — upstream not passing: ${unmet.join(', ')}`,\n }\n results.push(skipped)\n byName[layer.name] = skipped\n opts.onLayer?.(skipped)\n continue\n }\n\n // Per-layer cap — compose with overall signal.\n const perLayerController = new AbortController()\n const mergedSignal = mergeSignals(controller.signal, perLayerController.signal)\n const layerTimer =\n layer.capMs != null\n ? setTimeout(\n () => perLayerController.abort(new Error(`layer ${layer.name} cap`)),\n layer.capMs,\n )\n : null\n\n const layerStart = Date.now()\n let result: LayerResult\n let rejectOnAbort: (() => void) | undefined\n const abortPromise = new Promise<never>((_resolve, reject) => {\n const rejectWithReason = (): void => {\n const reason = mergedSignal.reason\n reject(reason instanceof Error ? reason : new Error(String(reason ?? 'aborted')))\n }\n if (mergedSignal.aborted) {\n rejectWithReason()\n return\n }\n mergedSignal.addEventListener('abort', rejectWithReason, { once: true })\n rejectOnAbort = () => mergedSignal.removeEventListener('abort', rejectWithReason)\n })\n try {\n result = await Promise.race([\n Promise.resolve(\n layer.run({ env: opts.env, prior: { ...byName }, signal: mergedSignal }),\n ),\n abortPromise,\n ])\n } catch (err) {\n const aborted = mergedSignal.aborted\n result = {\n layer: layer.name,\n status: aborted ? 'timeout' : 'error',\n errorSource: layer.errorSource ?? 'execution',\n durationMs: Date.now() - layerStart,\n findings: [\n {\n severity: 'major',\n message: err instanceof Error ? err.message : String(err),\n layer: layer.name,\n },\n ],\n reason: err instanceof Error ? err.message : String(err),\n }\n } finally {\n rejectOnAbort?.()\n if (layerTimer) clearTimeout(layerTimer)\n }\n\n if (result.status === 'error' || result.status === 'timeout') {\n result.errorSource ??= layer.errorSource ?? 'execution'\n }\n\n // Normalize findings to attach layer name if omitted.\n result.findings = result.findings.map((f) => ({ ...f, layer: f.layer ?? layer.name }))\n results.push(result)\n byName[layer.name] = result\n opts.onLayer?.(result)\n\n if (controller.signal.aborted) break\n }\n\n const report = aggregate(this.layers, results, startedAt, startedAtMs)\n return report\n } finally {\n if (overallTimer) clearTimeout(overallTimer)\n }\n }\n}\n\nfunction aggregate<Env>(\n layers: Layer<Env>[],\n results: LayerResult[],\n startedAt: string,\n startedAtMs: number,\n): VerificationReport {\n const weightByName = new Map<string, number>()\n const failContribByName = new Map<string, boolean>()\n for (const l of layers) {\n weightByName.set(l.name, l.weight ?? 1)\n failContribByName.set(l.name, l.failContributesToScore ?? false)\n }\n\n let passCount = 0\n let failCount = 0\n let skippedCount = 0\n let errorCount = 0\n let scoredWeightSum = 0\n let scoredWeightedTotal = 0\n\n for (const r of results) {\n const weight = weightByName.get(r.layer) ?? 1\n const failContrib = failContribByName.get(r.layer) ?? false\n if (r.status === 'pass') passCount++\n else if (r.status === 'fail') failCount++\n else if (r.status === 'skipped') skippedCount++\n else errorCount++\n\n if (isValidTaskMeasurement(r) && weight > 0) {\n if (r.status === 'pass') {\n scoredWeightSum += weight\n scoredWeightedTotal += weight * r.score\n } else if (r.status === 'fail') {\n if (failContrib) {\n scoredWeightSum += weight\n scoredWeightedTotal += weight * r.score\n }\n }\n // skipped / error / timeout layers don't contribute\n }\n }\n\n const finishedAtMs = Date.now()\n const blendedScore = scoredWeightSum > 0 ? scoredWeightedTotal / scoredWeightSum : 0\n const resultByName = new Map(results.map((result) => [result.layer, result]))\n const completeTaskMeasurement =\n scoredWeightSum > 0 &&\n results.length === layers.length &&\n layers.every((layer) => {\n const result = resultByName.get(layer.name)\n if (!result) return false\n if ((layer.weight ?? 1) <= 0) return true\n if (result.status === 'pass') {\n return result.score === undefined || isValidTaskMeasurement(result)\n }\n return (\n result.status === 'fail' &&\n layer.failContributesToScore === true &&\n isValidTaskMeasurement(result)\n )\n })\n const taskScore =\n completeTaskMeasurement && scoredWeightSum > 0 && Number.isFinite(blendedScore)\n ? blendedScore\n : undefined\n const allPass =\n taskScore !== undefined &&\n results.length === layers.length &&\n failCount === 0 &&\n skippedCount === 0 &&\n errorCount === 0\n // Layers that produced no measurement are the steps this composite\n // certificate rests on without verifying — named per layer, never folded\n // into the blend silently.\n const assumptions = results\n .filter((r) => r.status === 'skipped' || r.status === 'error' || r.status === 'timeout')\n .map((r) => `layer '${r.layer}' ${r.status} — its obligations are unverified`)\n return {\n layers: results,\n passCount,\n failCount,\n skippedCount,\n errorCount,\n allPass,\n blendedScore,\n ...(taskScore === undefined ? {} : { taskScore }),\n valid: allPass,\n score: taskScore ?? 0,\n certification: {\n strategy: 'composite',\n checker: { name: 'agent-eval:multi-layer-verifier', version: packageVersion() },\n assumptions,\n evidenceDigest: certificationEvidenceDigest(results),\n },\n durationMs: finishedAtMs - startedAtMs,\n startedAt,\n finishedAt: new Date(finishedAtMs).toISOString(),\n }\n}\n\nfunction isValidTaskMeasurement(\n result: LayerResult,\n): result is LayerResult & { status: 'pass' | 'fail'; score: number } {\n return (\n (result.status === 'pass' || result.status === 'fail') &&\n typeof result.score === 'number' &&\n Number.isFinite(result.score) &&\n result.score >= 0 &&\n result.score <= 1\n )\n}\n\nfunction mergeSignals(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a\n if (b.aborted) return b\n const c = new AbortController()\n const onAbort = (signal: AbortSignal) => () => c.abort(signal.reason)\n a.addEventListener('abort', onAbort(a), { once: true })\n b.addEventListener('abort', onAbort(b), { once: true })\n return c.signal\n}\n","/**\n * Declarative oracles — ground-truth assertions without an LLM.\n *\n * Lifted from browser-agent-driver's _oracle.mjs. When you know the\n * expected outcome exactly (a URL, a text fragment, a JSON shape), you\n * don't need an LLM judge — you need a regex. These oracles are\n * composable pass/fail checks over an observation bundle.\n *\n * Each oracle returns { pass, detail, evidence? } and has a short `id` for\n * reporting. `evaluateOracles` runs a batch and lands the aggregate in the\n * shared verdict spine (`DefaultVerdict`, docs/verdicts.md) with a\n * `'test'`-strategy certification: an oracle set IS a small answer key,\n * and certifies nothing outside its own coverage.\n */\n\nimport { packageVersion } from './package-version'\nimport { certificationEvidenceDigest, type DefaultVerdict } from './verdict'\n\nexport interface OracleObservation {\n /** Final observable text output from the agent (response, page snapshot, stdout). */\n text?: string\n /** Final URL — for browser-style scenarios. */\n url?: string\n /** Any structured JSON the agent produced. */\n json?: unknown\n /** Free-form context used by custom oracles. */\n context?: Record<string, unknown>\n}\n\nexport interface OracleResult {\n id: string\n pass: boolean\n detail: string\n evidence?: string\n}\n\nexport interface Oracle {\n id: string\n check(obs: OracleObservation): OracleResult\n}\n\nexport function textInSnapshot(needle: string, opts: { caseSensitive?: boolean } = {}): Oracle {\n const id = `text-in-snapshot(${needle})`\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n const found = opts.caseSensitive\n ? hay.includes(needle)\n : hay.toLowerCase().includes(needle.toLowerCase())\n return {\n id,\n pass: found,\n detail: found ? `\"${needle}\" found` : `\"${needle}\" not present in observation`,\n evidence: found ? excerpt(hay, needle, opts.caseSensitive) : undefined,\n }\n },\n }\n}\n\nexport function urlContains(fragment: string): Oracle {\n const id = `url-contains(${fragment})`\n return {\n id,\n check(obs) {\n const url = obs.url ?? ''\n const pass = url.toLowerCase().includes(fragment.toLowerCase())\n return {\n id,\n pass,\n detail: pass ? `url ok (${url})` : `url \"${url}\" missing \"${fragment}\"`,\n evidence: url,\n }\n },\n }\n}\n\nexport function jsonShape(expected: Record<string, unknown>): Oracle {\n const id = `json-shape(${Object.keys(expected).join(',')})`\n return {\n id,\n check(obs) {\n const json = obs.json\n if (!isObject(json)) {\n return { id, pass: false, detail: 'observation.json missing or not an object' }\n }\n for (const [k, v] of Object.entries(expected)) {\n if (!(k in json)) return { id, pass: false, detail: `key \"${k}\" missing` }\n const actual = (json as Record<string, unknown>)[k]\n if (typeof v === 'string' && v.startsWith('re:')) {\n const re = new RegExp(v.slice(3))\n if (typeof actual !== 'string' || !re.test(actual)) {\n return { id, pass: false, detail: `key \"${k}\" failed regex ${v}` }\n }\n } else if (actual !== v) {\n return {\n id,\n pass: false,\n detail: `key \"${k}\" = ${JSON.stringify(actual)}, expected ${JSON.stringify(v)}`,\n }\n }\n }\n return { id, pass: true, detail: 'all keys match' }\n },\n }\n}\n\nexport function regexMatches(pattern: RegExp): Oracle {\n const id = `regex(${pattern.source})`\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n const m = hay.match(pattern)\n return {\n id,\n pass: m !== null,\n detail: m ? `matched \"${m[0]}\"` : `pattern ${pattern.source} not matched`,\n evidence: m?.[0],\n }\n },\n }\n}\n\n/**\n * Anti-bot detector — distinguishes genuine failures from blocked navigation\n * (cloudflare, recaptcha, etc). Returns an Oracle that PASSES when no block\n * marker is present; on block, detail names the blocker so runners can tag\n * results as \"blocked\" rather than \"failed\". Lifted from browser-agent-driver.\n */\nexport function notBlocked(): Oracle {\n const id = 'not-blocked'\n const markers: Array<{ name: string; re: RegExp }> = [\n { name: 'cloudflare', re: /just a moment|verifying you are human|cf-chl-|cloudflare/i },\n { name: 'recaptcha', re: /recaptcha|i'?m not a robot|challenge.?form/i },\n { name: 'hcaptcha', re: /hcaptcha/i },\n { name: 'akamai', re: /akamai|pragma: no-cache/i },\n { name: 'perimeterx', re: /perimeterx|px-captcha/i },\n { name: 'rate-limit', re: /rate.?limit|429 too many requests/i },\n { name: 'access-denied', re: /access denied|403 forbidden/i },\n ]\n return {\n id,\n check(obs) {\n const hay = obs.text ?? ''\n for (const { name, re } of markers) {\n if (re.test(hay)) {\n return {\n id,\n pass: false,\n detail: `blocked by ${name}`,\n evidence: (hay.match(re) ?? [])[0],\n }\n }\n }\n return { id, pass: true, detail: 'no anti-bot block detected' }\n },\n }\n}\n\n/** Extends the substrate verdict spine: `valid` = every oracle passed (and\n * at least one ran); `score` = ratio of oracles passed; `scores` = per-\n * oracle 0|1 keyed by oracle id. */\nexport interface OracleReport extends DefaultVerdict {\n results: OracleResult[]\n passCount: number\n failCount: number\n}\n\n/** Run all oracles against one observation and aggregate. */\nexport function evaluateOracles(obs: OracleObservation, oracles: Oracle[]): OracleReport {\n const results = oracles.map((o) => o.check(obs))\n const passCount = results.filter((r) => r.pass).length\n const failCount = results.length - passCount\n const scores: Record<string, number> = {}\n for (const r of results) scores[r.id] = r.pass ? 1 : 0\n return {\n results,\n passCount,\n failCount,\n valid: failCount === 0 && results.length > 0,\n score: results.length ? passCount / results.length : 0,\n scores,\n notes: `${passCount}/${results.length} oracles passed`,\n certification: {\n strategy: 'test',\n checker: { name: 'agent-eval:declarative-oracles', version: packageVersion() },\n assumptions: [],\n evidenceDigest: certificationEvidenceDigest(results),\n },\n }\n}\n\nfunction excerpt(hay: string, needle: string, caseSensitive = false): string {\n const haySearch = caseSensitive ? hay : hay.toLowerCase()\n const needleSearch = caseSensitive ? needle : needle.toLowerCase()\n const idx = haySearch.indexOf(needleSearch)\n if (idx === -1) return ''\n const start = Math.max(0, idx - 20)\n const end = Math.min(hay.length, idx + needle.length + 20)\n return (start > 0 ? '…' : '') + hay.slice(start, end) + (end < hay.length ? '…' : '')\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n","/**\n * Treatment-applied gate — \"did the treatment's tool actually fire this run?\"\n *\n * A tool-treatment A/B (mount a search provider, a browser, a code-exec\n * sandbox, a retrieval MCP — anything one arm gets and the other doesn't) only\n * means something on the treatment arm if that arm actually EXERCISED the tool.\n * A treatment run that never called the mounted tool is not a weak data point\n * — it is a NON-data-point: the manipulation never happened, so the run cannot\n * speak to the treatment and must be excluded from the objective, the same way\n * an infra-tainted run is excluded.\n *\n * This is the manipulation/validity precondition that protects the paired A/B\n * tests downstream (`mcnemar`, `pairedRiskDifference`): they must only ever see\n * runs where the treatment was applied, or they measure noise and report it as\n * an effect.\n *\n * Shape mirrors `authenticity`'s `gateRealness`: a pure predicate over already-\n * computed signals, with explicit fail-open/fail-closed discipline. It is not a\n * trace parser — the tool-call telemetry it reads is the deterministic\n * `toolHistogram` that `computeTraceMetrics(spans)` already produces (OTLP\n * tool-name extraction via `TOOL_NAME_ATTR_KEYS`), or the `ToolSpan[]` a\n * `toolSpans(store, runId)` query returns. The gate never re-derives either.\n *\n * General by construction:\n * - The \"which tool counts as the treatment\" decision is a `matches` PARAMETER\n * — a `(toolName: string) => boolean`. There is no `search`/`web`/`fetch`\n * literal anywhere in this module; a search A/B passes its own matcher.\n * - The \"is THIS run a treatment arm (vs a control)\" decision is the caller's\n * policy and stays at the call site. The gate only answers the narrower,\n * domain-free question: \"given this run's telemetry, did a matching tool\n * fire?\" — so it generalizes to any tool-treatment, not search.\n *\n * Fail-open on telemetry absence: when NO tool calls were captured at all\n * (`sum(toolHistogram) === 0`), the gate cannot distinguish \"the agent used no\n * tools\" from \"this harness's tool calls weren't recorded\". Quarantining on a\n * telemetry gap would silently delete real runs, so the default is\n * applied=true / gated=false. Pass `failOpenWhenNoTelemetry: false` to flip to\n * fail-closed for harnesses where tool capture is guaranteed.\n */\n\nimport type { RunRecord } from './run-record'\nimport type { ToolSpan } from './trace/schema'\nimport type { BehavioralMetrics } from './trace-analyst/behavioral-metrics'\nimport { computeTraceMetrics } from './trace-analyst/behavioral-metrics'\nimport type { TraceAnalystSpan } from './trace-analyst/types'\n\n/** A tool-name matcher: does this tool name belong to the treatment under test?\n * The caller supplies it — the substrate ships no `search` (or any) literal. */\nexport type ToolMatcher = (toolName: string) => boolean\n\nexport interface TreatmentGateInput {\n /** Tool-call counts by tool name — exactly `computeTraceMetrics(spans).toolHistogram`.\n * The gate consumes this; it does not parse spans itself. */\n toolHistogram: Readonly<Record<string, number>>\n /** Which tool names count as the treatment firing. A parameter, never baked in. */\n matches: ToolMatcher\n}\n\nexport interface TreatmentGateOptions {\n /** When the histogram is empty (no tool telemetry captured), treat the run as\n * applied rather than quarantining it. Default true — a telemetry gap must\n * never be mistaken for \"treatment not applied\". Set false only when tool\n * capture is guaranteed for this harness. */\n failOpenWhenNoTelemetry?: boolean\n}\n\nexport interface TreatmentGate {\n /** True iff the treatment's tool is considered to have fired this run. False\n * ONLY when telemetry was present and no matching call appears. */\n applied: boolean\n /** Objective-exclusion flag, parallel to `outcome.realness.gated`: a gated run\n * is dropped from the objective denominator and reported as\n * treatment-not-applied (like infra-loss). `gated === !applied`. */\n gated: boolean\n reason?: string\n /** How many recorded tool calls matched the treatment matcher. */\n matchedCalls: number\n /** Total recorded tool calls (`sum(toolHistogram)`) — 0 means no telemetry. */\n observedTools: number\n}\n\n/**\n * Core predicate. Gated (treatment-not-applied) ONLY when telemetry was\n * captured AND zero matching calls appear; an empty histogram fails open.\n */\nexport function gateTreatmentApplied(\n input: TreatmentGateInput,\n opts: TreatmentGateOptions = {},\n): TreatmentGate {\n const failOpen = opts.failOpenWhenNoTelemetry ?? true\n\n let observedTools = 0\n let matchedCalls = 0\n for (const [tool, count] of Object.entries(input.toolHistogram)) {\n const n = Number.isFinite(count) && count > 0 ? count : 0\n observedTools += n\n if (n > 0 && input.matches(tool)) matchedCalls += n\n }\n\n if (observedTools === 0) {\n return failOpen\n ? {\n applied: true,\n gated: false,\n reason: 'no tool telemetry captured — fail-open (not quarantined)',\n matchedCalls: 0,\n observedTools: 0,\n }\n : {\n applied: false,\n gated: true,\n reason: 'no tool telemetry captured — fail-closed',\n matchedCalls: 0,\n observedTools: 0,\n }\n }\n\n if (matchedCalls === 0) {\n return {\n applied: false,\n gated: true,\n reason: `treatment tool never fired (${observedTools} tool calls, 0 matched)`,\n matchedCalls: 0,\n observedTools,\n }\n }\n\n return { applied: true, gated: false, matchedCalls, observedTools }\n}\n\n/**\n * Convenience: gate from an already-computed `BehavioralMetrics` (the common\n * case — analysts already hold `computeTraceMetrics(spans)` for the run). Reads\n * the metrics' `toolHistogram`; does no re-derivation.\n */\nexport function gateTreatmentFromMetrics(\n metrics: Pick<BehavioralMetrics, 'toolHistogram'>,\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n return gateTreatmentApplied({ toolHistogram: metrics.toolHistogram, matches }, opts)\n}\n\n/**\n * Convenience: gate directly from analyst spans, reusing the substrate's\n * deterministic histogram builder. For callers holding the trace store's typed\n * `ToolSpan[]` instead, see {@link gateTreatmentFromToolSpans}.\n */\nexport function gateTreatmentFromSpans(\n spans: readonly TraceAnalystSpan[],\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n return gateTreatmentFromMetrics(computeTraceMetrics(spans), matches, opts)\n}\n\n/**\n * Convenience: gate from the trace store's canonical `ToolSpan[]` (e.g. the\n * result of `toolSpans(store, runId)`). Counts by `toolName` — the typed\n * tool-call field — so it needs no OTLP attribute extraction.\n */\nexport function gateTreatmentFromToolSpans(\n toolSpans: readonly ToolSpan[],\n matches: ToolMatcher,\n opts?: TreatmentGateOptions,\n): TreatmentGate {\n const toolHistogram: Record<string, number> = {}\n for (const s of toolSpans) {\n if (s.toolName) toolHistogram[s.toolName] = (toolHistogram[s.toolName] ?? 0) + 1\n }\n return gateTreatmentApplied({ toolHistogram, matches }, opts)\n}\n\n/** Measurable runs count toward the objective; treatment-not-applied runs are\n * excluded (like infra-loss), NOT counted as treatment failures. This is a\n * partition over the existing exclusion-flag pattern — it adds no new\n * classification enum. */\nexport type TreatmentClass = 'measurable' | 'treatment-not-applied'\n\n/**\n * Map a gate verdict onto a single measurable-vs-excluded label keyed on a\n * `RunRecord`, so consumers (paired A/B filters, reporters) read the partition\n * in one place instead of re-implementing the fail-open guard inline. The\n * `RunRecord` is accepted so callers key on the canonical run row, mirroring\n * how `outcome.realness.gated` rides along on the record; the verdict itself is\n * the gate's, not re-derived here.\n */\nexport function classifyTreatment(_record: RunRecord, gate: TreatmentGate): TreatmentClass {\n return gate.gated ? 'treatment-not-applied' : 'measurable'\n}\n","/**\n * Anti-slop quality judge.\n *\n * Deterministic pattern-based quality check — no LLM call. Catches the\n * 80% of AI slop that every production agent leaks:\n * - Banned phrases (voice-specific: \"delve\", \"it's worth noting\", etc.)\n * - N-gram repetition (same phrase over and over)\n * - Hedging overuse (\"I could be wrong, but...\")\n * - Apology padding (\"I'm so sorry for the confusion...\")\n * - Unused opening formulas (\"Great question!\")\n * - Length bounds (too short to be useful, too long to be read)\n *\n * Produces a JudgeScore in the same shape as LLM judges so it composes into\n * any `JudgeFn` array transparently.\n */\n\nimport type { JudgeFn, JudgeInput, JudgeScore } from './types'\n\nexport interface AntiSlopConfig {\n /** Domain label — appears in the JudgeScore output */\n domain?: string\n\n /** Case-insensitive substrings that must not appear. Each occurrence = penalty. */\n bannedPhrases?: string[]\n\n /** Regexes matching opening formulas to penalize (e.g. /^great question/i). */\n bannedOpenings?: RegExp[]\n\n /** Regexes matching hedges (e.g. /i could be wrong/i). Ratio of hedged sentences drives score. */\n hedgingPatterns?: RegExp[]\n\n /** Regexes matching apology padding. */\n apologyPatterns?: RegExp[]\n\n /** Fraction of sentences that can be duplicates before penalty (default 0.15 = 15%). */\n repetitionThreshold?: number\n\n /** Min output length in chars; below this the turn is deemed too terse. */\n minLength?: number\n\n /** Max output length in chars; above this the turn is deemed too verbose. */\n maxLength?: number\n\n /** How heavily each violation class reduces the score (default 1). */\n penaltyWeights?: Partial<Record<SlopCategory, number>>\n}\n\nexport type SlopCategory =\n | 'banned_phrase'\n | 'banned_opening'\n | 'hedging'\n | 'apology'\n | 'repetition'\n | 'length'\n\nconst DEFAULT_HEDGES: RegExp[] = [\n /\\bi\\s+could\\s+be\\s+wrong\\b/i,\n /\\bi\\s+think\\s+maybe\\b/i,\n /\\bit\\s+might\\s+be\\s+that\\b/i,\n /\\bperhaps\\s+(?:you\\s+)?could\\b/i,\n]\n\nconst DEFAULT_APOLOGIES: RegExp[] = [\n /\\bi\\s+(?:apologize|apologise)\\s+(?:for|if)\\b/i,\n /\\bi'?m\\s+(?:so\\s+|really\\s+)?sorry\\s+(?:for|if|about)\\b/i,\n /\\bmy\\s+apologies\\b/i,\n]\n\n/** Create a reusable Judge function from an anti-slop config. */\nexport function createAntiSlopJudge(config: AntiSlopConfig = {}): JudgeFn {\n const conf: Required<Omit<AntiSlopConfig, 'penaltyWeights'>> & {\n penaltyWeights: Record<SlopCategory, number>\n } = {\n domain: config.domain ?? 'general',\n bannedPhrases: config.bannedPhrases ?? [],\n bannedOpenings: config.bannedOpenings ?? [],\n hedgingPatterns: config.hedgingPatterns ?? DEFAULT_HEDGES,\n apologyPatterns: config.apologyPatterns ?? DEFAULT_APOLOGIES,\n repetitionThreshold: config.repetitionThreshold ?? 0.15,\n minLength: config.minLength ?? 20,\n maxLength: config.maxLength ?? 8000,\n penaltyWeights: {\n banned_phrase: 1,\n banned_opening: 1,\n hedging: 0.5,\n apology: 0.5,\n repetition: 0.75,\n length: 0.5,\n ...config.penaltyWeights,\n },\n }\n\n const judge: JudgeFn = async (_tc, input: JudgeInput): Promise<JudgeScore[]> => {\n const outputs = input.turns.map((t) => t.agentResponse ?? '')\n const report = analyzeAntiSlop(outputs, conf)\n return [\n {\n judgeName: `anti-slop(${conf.domain})`,\n dimension: 'anti_slop',\n score: report.score,\n reasoning: report.issues.length\n ? report.issues\n .slice(0, 5)\n .map((i) => `${i.category}: ${i.detail}`)\n .join('; ')\n : 'No slop patterns detected.',\n evidence: report.issues[0]?.example,\n },\n ]\n }\n return judge\n}\n\nexport interface AntiSlopIssue {\n category: SlopCategory\n detail: string\n example?: string\n}\n\nexport interface AntiSlopReport {\n /** 0–10 score; 10 is clean, lower values mean more slop. */\n score: number\n issues: AntiSlopIssue[]\n /** Count of each category for programmatic aggregation. */\n counts: Record<SlopCategory, number>\n}\n\n/**\n * Pure function — analyze one or more outputs against the config. Exposed\n * separately so consumers can build their own reporters on top.\n */\nexport function analyzeAntiSlop(\n outputs: string[],\n config: Omit<Required<AntiSlopConfig>, 'domain'> & {\n penaltyWeights: Record<SlopCategory, number>\n },\n): AntiSlopReport {\n const issues: AntiSlopIssue[] = []\n const counts: Record<SlopCategory, number> = {\n banned_phrase: 0,\n banned_opening: 0,\n hedging: 0,\n apology: 0,\n repetition: 0,\n length: 0,\n }\n\n for (const output of outputs) {\n if (!output) continue\n const lower = output.toLowerCase()\n\n for (const phrase of config.bannedPhrases) {\n const needle = phrase.toLowerCase()\n let idx = lower.indexOf(needle, 0)\n while (idx !== -1) {\n counts.banned_phrase += 1\n if (issues.length < 20) {\n issues.push({\n category: 'banned_phrase',\n detail: `\"${phrase}\"`,\n example: snippet(output, idx, phrase.length),\n })\n }\n idx = lower.indexOf(needle, idx + needle.length)\n }\n }\n\n for (const re of config.bannedOpenings) {\n if (re.test(output)) {\n counts.banned_opening += 1\n issues.push({ category: 'banned_opening', detail: re.source, example: output.slice(0, 80) })\n }\n }\n\n for (const re of config.hedgingPatterns) {\n const matches = output.match(\n new RegExp(re, re.flags.includes('g') ? re.flags : `${re.flags}g`),\n )\n if (matches) {\n counts.hedging += matches.length\n issues.push({\n category: 'hedging',\n detail: `${matches.length}x ${re.source}`,\n example: matches[0],\n })\n }\n }\n\n for (const re of config.apologyPatterns) {\n const matches = output.match(\n new RegExp(re, re.flags.includes('g') ? re.flags : `${re.flags}g`),\n )\n if (matches) {\n counts.apology += matches.length\n issues.push({\n category: 'apology',\n detail: `${matches.length}x ${re.source}`,\n example: matches[0],\n })\n }\n }\n\n // Repetition: compare sentence-level dupes\n const sentences = splitSentences(output)\n if (sentences.length >= 4) {\n const seen = new Map<string, number>()\n for (const s of sentences) {\n const key = normalizeForDupe(s)\n if (!key) continue\n seen.set(key, (seen.get(key) ?? 0) + 1)\n }\n let dupes = 0\n for (const n of seen.values()) if (n > 1) dupes += n - 1\n const ratio = dupes / sentences.length\n if (ratio > config.repetitionThreshold) {\n counts.repetition += 1\n issues.push({\n category: 'repetition',\n detail: `${(ratio * 100).toFixed(0)}% duplicated (threshold ${(config.repetitionThreshold * 100).toFixed(0)}%)`,\n })\n }\n }\n\n // Length\n if (output.length < config.minLength) {\n counts.length += 1\n issues.push({\n category: 'length',\n detail: `too short (${output.length} < ${config.minLength})`,\n })\n } else if (output.length > config.maxLength) {\n counts.length += 1\n issues.push({\n category: 'length',\n detail: `too long (${output.length} > ${config.maxLength})`,\n })\n }\n }\n\n // Score: 10 minus weighted violations, clamped. Each violation of category c\n // subtracts `penaltyWeights[c]` points. Violations beyond 10/weight saturate.\n let penalty = 0\n for (const cat of Object.keys(counts) as SlopCategory[]) {\n penalty += counts[cat] * (config.penaltyWeights[cat] ?? 1)\n }\n const score = Math.max(0, Math.min(10, 10 - penalty))\n\n return { score, issues, counts }\n}\n\nfunction snippet(source: string, at: number, len: number): string {\n const pad = 24\n const start = Math.max(0, at - pad)\n const end = Math.min(source.length, at + len + pad)\n return (start > 0 ? '…' : '') + source.slice(start, end) + (end < source.length ? '…' : '')\n}\n\nfunction splitSentences(text: string): string[] {\n // Simple sentence split — good enough for slop detection; not linguistically perfect.\n return text\n .split(/[.!?\\n]+/)\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n}\n\nfunction normalizeForDupe(s: string): string {\n return s\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .replace(/[^a-z0-9 ]/g, '')\n .trim()\n}\n","/**\n * EvalTraceStore — JSONL save / query / compare over the analysis-time\n * `RunRecord` row.\n *\n * `FileSystemTraceStore` (in `./trace/store`) persists the rich TraceSchema-v1\n * span corpus — runs, spans, events, artifacts — the runtime emits live. That\n * is NOT the thing three consumers hand-roll in `tests/eval/lib/trace-store.ts`.\n * What they hand-roll is the *analysis* layer: append each finished run as one\n * JSONL line keyed by scenario/candidate, then query it (\"every run where score\n * < 50\"), pick the best run for a scenario (few-shot seeding), and compare two\n * candidates on matched scenarios.\n *\n * The substrate already has the canonical analysis-time row — `RunRecord` — so\n * this is that query/compare API expressed over `RunRecord[]`, with a\n * JSONL-backed store. It does NOT fork `FileSystemTraceStore`; it sits beside it\n * for the analysis projection.\n */\n\nimport { ValidationError } from './errors'\nimport { isRealnessGated, trainingScore } from './rollout/reward'\nimport { isRunRecord, type RunRecord, type RunSplitTag, validateRunRecord } from './run-record'\n\n/**\n * The score the query/compare layer ranks on: holdout when present, else\n * search, with the anti-Goodhart gate applied — a run flagged as gamed reads 0\n * however high it claims to have scored.\n *\n * The gate is load-bearing here and this function did not previously apply it,\n * despite saying it did. `getBest` is few-shot exemplar selection: whatever it\n * returns is pasted into the next agent's prompt as an example to imitate.\n * Ranking on the raw number handed the highest-scoring gamed trajectory to\n * every subsequent run — propagation through the context window rather than\n * through a gradient, but propagation all the same.\n *\n * Analysis that needs to SEE the inflated number (reward-hack detection,\n * per-run reporting) reads `observedScore` from `rollout/reward.ts` directly.\n *\n * Returns `undefined` for an execution-only record (neither score present):\n * such rows are valid RunRecords, but cannot participate in score-ranked\n * queries. A gated run still reads 0 — the gate's verdict is a number, never\n * a gap.\n */\nexport function runScore(record: RunRecord): number | undefined {\n return trainingScore(record)\n}\n\nexport interface RunRecordFilter {\n experimentId?: string\n candidateId?: string\n scenarioId?: string\n model?: string\n splitTag?: RunSplitTag\n /** Inclusive lower bound on `runScore`. */\n minScore?: number\n /** Inclusive upper bound on `runScore`. */\n maxScore?: number\n /** Match a single tag in `outcome.raw` by exact numeric value. */\n rawEquals?: { key: string; value: number }\n /** Custom predicate, ANDed with the structured filters. */\n where?: (record: RunRecord) => boolean\n}\n\nfunction matches(record: RunRecord, f: RunRecordFilter): boolean {\n if (f.experimentId && record.experimentId !== f.experimentId) return false\n if (f.candidateId && record.candidateId !== f.candidateId) return false\n if (f.scenarioId && record.scenarioId !== f.scenarioId) return false\n if (f.model && record.model !== f.model) return false\n if (f.splitTag && record.splitTag !== f.splitTag) return false\n if (f.minScore !== undefined || f.maxScore !== undefined) {\n const score = runScore(record)\n if (score === undefined) return false\n if (f.minScore !== undefined && score < f.minScore) return false\n if (f.maxScore !== undefined && score > f.maxScore) return false\n }\n if (f.rawEquals && record.outcome.raw[f.rawEquals.key] !== f.rawEquals.value) return false\n if (f.where && !f.where(record)) return false\n return true\n}\n\nexport interface CandidateComparison {\n a: string\n b: string\n /** Scenario ids present for BOTH candidates — the paired comparison set. */\n pairedScenarioIds: string[]\n /** Mean `runScore` for candidate a over the paired scenarios. */\n meanA: number\n /** Mean `runScore` for candidate b over the paired scenarios. */\n meanB: number\n /** meanB − meanA. Positive ⇒ b scored higher on the matched scenarios. */\n meanDelta: number\n /** Scenarios where b beat a (strictly), tied, and a beat b. */\n bWins: number\n ties: number\n aWins: number\n /**\n * Runs of either candidate excluded from the comparison because the\n * authenticity gate flagged them (`outcome.realness.gated`).\n *\n * Excluded rather than scored 0: `runScore` is gated, so leaving them in\n * would have entered a gamed run as a silent zero, which reads as \"this\n * candidate failed the scenario\" when what happened is \"this candidate's\n * result is not evidence\". A non-zero count here is itself the finding — a\n * comparison drawn over a shrunken scenario set has to say so.\n */\n realnessGatedRuns: number\n}\n\n/**\n * Backing persistence for `EvalTraceStore`. The in-memory store is the default;\n * the JSONL file store appends one validated `RunRecord` per line. Both keep an\n * append order so `getBest` / `compareRuns` are reproducible.\n */\nexport interface RunRecordBackend {\n append(record: RunRecord): Promise<void>\n load(): Promise<RunRecord[]>\n}\n\nexport function inMemoryRunRecordBackend(initial: RunRecord[] = []): RunRecordBackend {\n const rows = initial.map((r) => validateRunRecord(r))\n return {\n async append(record) {\n rows.push(record)\n },\n async load() {\n return [...rows]\n },\n }\n}\n\n/**\n * JSONL-backed store at `path`, one `RunRecord` per line. Malformed lines fail\n * loud on load (a corrupt corpus must not silently shrink the analysis set);\n * pass `skipInvalid` only for forensics on a known-bad file.\n */\nexport function jsonlRunRecordBackend(\n path: string,\n opts: { skipInvalid?: boolean } = {},\n): RunRecordBackend {\n return {\n async append(record) {\n const fs = await import('node:fs/promises')\n const pathMod = await import('node:path')\n await fs.mkdir(pathMod.dirname(path), { recursive: true })\n await fs.appendFile(path, `${JSON.stringify(record)}\\n`, 'utf8')\n },\n async load() {\n const fs = await import('node:fs/promises')\n let raw: string\n try {\n raw = await fs.readFile(path, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw err\n }\n const out: RunRecord[] = []\n let lineNo = 0\n for (const line of raw.split('\\n')) {\n lineNo++\n if (!line.trim()) continue\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch (err) {\n if (opts.skipInvalid) continue\n throw new ValidationError(`EvalTraceStore: ${path}:${lineNo} is not valid JSON`)\n }\n if (opts.skipInvalid) {\n if (isRunRecord(parsed)) out.push(parsed)\n continue\n }\n try {\n out.push(validateRunRecord(parsed))\n } catch (err) {\n throw new ValidationError(\n `EvalTraceStore: ${path}:${lineNo} is not a valid RunRecord — ${(err as Error).message}`,\n )\n }\n }\n return out\n },\n }\n}\n\n/**\n * Query / compare layer over a `RunRecord` corpus. Append finished runs, query\n * with a structured filter, take the best run for a scenario, and compare two\n * candidates on their matched scenarios. Persistence is injected via\n * `RunRecordBackend` (in-memory by default, JSONL file via\n * `jsonlRunRecordBackend`).\n */\nexport class EvalTraceStore {\n private readonly backend: RunRecordBackend\n\n constructor(backend: RunRecordBackend = inMemoryRunRecordBackend()) {\n this.backend = backend\n }\n\n /** Validate and append one run. Throws on an invalid record — the corpus\n * stays paper-grade. */\n async append(record: RunRecord): Promise<void> {\n await this.backend.append(validateRunRecord(record))\n }\n\n async all(): Promise<RunRecord[]> {\n return this.backend.load()\n }\n\n async query(filter: RunRecordFilter = {}): Promise<RunRecord[]> {\n const rows = await this.backend.load()\n return rows.filter((r) => matches(r, filter))\n }\n\n /**\n * Highest-scoring run for a scenario (optionally restricted to a candidate).\n * Returns null when no run matches. Ties resolve to the earliest-appended run\n * so the result is stable.\n *\n * Runs flagged as gamed are DROPPED, not zeroed. The caller's use for this is\n * few-shot seeding — the returned trajectory becomes an example to copy — so\n * the same rule as SFT applies: a faked success must not be in the candidate\n * set at all. When every run for the scenario is gated the honest answer is\n * `null` (no exemplar), never the least-bad fake.\n */\n async getBest(\n scenarioId: string,\n opts: { candidateId?: string; splitTag?: RunSplitTag } = {},\n ): Promise<RunRecord | null> {\n const rows = (\n await this.query({\n scenarioId,\n candidateId: opts.candidateId,\n splitTag: opts.splitTag,\n })\n ).filter((r) => !isRealnessGated(r))\n const scored = rows.flatMap((record) => {\n const score = runScore(record)\n return score === undefined ? [] : [{ record, score }]\n })\n if (scored.length === 0) return null\n let best = scored[0]!.record\n let bestScore = scored[0]!.score\n for (let i = 1; i < scored.length; i++) {\n const s = scored[i]!.score\n if (s > bestScore) {\n best = scored[i]!.record\n bestScore = s\n }\n }\n return best\n }\n\n /**\n * Compare two candidates on the scenarios they BOTH ran. When a candidate\n * ran a scenario more than once, its best `runScore` for that scenario is\n * used. Throws when there is no paired scenario — an unpaired \"comparison\" is\n * not one.\n *\n * Realness-gated runs are excluded and counted in `realnessGatedRuns`, never\n * folded in as a zero.\n */\n async compareRuns(candidateA: string, candidateB: string): Promise<CandidateComparison> {\n if (candidateA === candidateB) {\n throw new ValidationError(\n `EvalTraceStore.compareRuns: candidates must differ (\"${candidateA}\")`,\n )\n }\n const rows = await this.backend.load()\n let realnessGatedRuns = 0\n const bestByScenario = (candidate: string): Map<string, number> => {\n const m = new Map<string, number>()\n for (const r of rows) {\n if (r.candidateId !== candidate) continue\n const sid = r.scenarioId\n if (!sid) continue\n if (isRealnessGated(r)) {\n realnessGatedRuns++\n continue\n }\n const s = runScore(r)\n if (s === undefined) continue\n const prev = m.get(sid)\n if (prev === undefined || s > prev) m.set(sid, s)\n }\n return m\n }\n const aScores = bestByScenario(candidateA)\n const bScores = bestByScenario(candidateB)\n const paired = [...aScores.keys()].filter((sid) => bScores.has(sid)).sort()\n if (paired.length === 0) {\n // Distinguish \"the corpora never overlapped\" from \"they overlap, but\n // every shared scenario lost a side to the realness gate\" — the second\n // diagnosis points at gamed runs, not at a mislabeled corpus.\n throw new ValidationError(\n realnessGatedRuns > 0\n ? `EvalTraceStore.compareRuns: \"${candidateA}\" and \"${candidateB}\" share no scenario ` +\n `with honest runs on both sides (${realnessGatedRuns} run(s) were realness-gated)`\n : `EvalTraceStore.compareRuns: \"${candidateA}\" and \"${candidateB}\" share no scenario (need scenarioId on records)`,\n )\n }\n let sumA = 0\n let sumB = 0\n let bWins = 0\n let aWins = 0\n let ties = 0\n for (const sid of paired) {\n const sa = aScores.get(sid)!\n const sb = bScores.get(sid)!\n sumA += sa\n sumB += sb\n if (sb > sa) bWins++\n else if (sb < sa) aWins++\n else ties++\n }\n const meanA = sumA / paired.length\n const meanB = sumB / paired.length\n return {\n a: candidateA,\n b: candidateB,\n pairedScenarioIds: paired,\n meanA,\n meanB,\n meanDelta: meanB - meanA,\n bWins,\n ties,\n aWins,\n realnessGatedRuns,\n }\n }\n}\n","/**\n * Backend preflight: verify the models a campaign is about to spend tokens\n * against are actually served by the router BEFORE the run starts. The PRE-hoc\n * complement to `assertRealBackend` (which inspects RunRecords AFTER the run to\n * catch a stub/unconfigured backend).\n *\n * The caller owns the endpoint. Agent Eval holds no base URL and no\n * credential: it asks a caller-supplied `request` function for each check and\n * reads the `Response` that comes back, so the status and the provider's own\n * error text stay readable here.\n *\n * Two checks, increasing in cost:\n * - membership (free): one `list-models` request; a model is `listed` when\n * its id is in the served set.\n * - probe (spends a tiny number of tokens): one `probe` request per model\n * with a `maxOutputTokens` budget; `served` is whether the endpoint reached\n * a provider, with the HTTP `status` and the body's `error.message`\n * captured in `detail`, and `servedModel` recording WHICH model answered.\n *\n * A 2xx is not proof the requested model answered — a gateway can accept one\n * id and route to another. The probe therefore compares the echoed id against\n * the requested one and reports `substitution`; `assertModelsServed` fails on\n * a substituted id exactly as it fails on a dead one, because a campaign that\n * runs on a silently-swapped model produces per-model numbers about a model it\n * never called.\n *\n * A default model the router cannot serve is a config bug. Gate a campaign on\n * `assertModelsServed` and it surfaces every dead or substituted id with its\n * status + detail instead of silently producing a stub or mislabelled run.\n */\n\nimport { AgentEvalError, ConfigError } from '../errors'\nimport {\n checkServedModel,\n PROBE_MAX_TOKENS,\n type ServedModelCheck,\n servedModelAcceptable,\n} from './served-model'\n\n/**\n * Provider signature for \"the budget ran out before an answer\". The model is\n * alive — a provider took the request and consumed the budget — so this must\n * never be scored as a dead id.\n */\nconst REASONING_BUDGET_EXHAUSTED = /reasoning[\\s_-]?budget[\\s_-]?exhausted/i\n\nexport interface ModelPreflight {\n /** The model id as supplied by the caller. */\n model: string\n /** Membership in the `{baseUrl}/models` served set. */\n listed: boolean\n /**\n * The router reached a provider for this model. `null` when `probe` was not\n * requested. True on a 2xx, and also when the provider answered by\n * exhausting its reasoning budget — that proves reachability while leaving\n * identity unproven (see `budgetExhausted`).\n */\n served: boolean | null\n /** HTTP status of the probe. `null` when not probed. */\n status: number | null\n /** Probe body's `error.message` when present, else `null`. */\n detail: string | null\n /**\n * The probe died on the token budget rather than on the model. Identity is\n * unproven, not refuted: raise `probeMaxTokens` to resolve it.\n */\n budgetExhausted: boolean\n /**\n * Identity of the model that answered the probe, compared against `model`.\n * `null` when the model was not probed or the probe failed.\n */\n substitution: ServedModelCheck | null\n}\n\n/** One check Agent Eval asks the caller's endpoint to perform. */\nexport type ModelEndpointCheck =\n | { readonly kind: 'list-models' }\n | {\n readonly kind: 'probe'\n readonly model: string\n /** Output-token budget the probe completion may bill. */\n readonly maxOutputTokens: number\n }\n\n/**\n * Caller-owned request into the model endpoint. The caller binds the base URL\n * and the credential and returns the raw `Response`; a `list-models` request\n * answers with an OpenAI-compatible `{ data: [{ id }] }` body, and a `probe`\n * request answers with one minimal chat completion for `model`.\n */\nexport type ModelEndpointRequest = (check: ModelEndpointCheck) => Promise<Response>\n\nexport interface PreflightModelsOptions {\n /** Caller-owned endpoint request. Agent Eval issues no provider HTTP itself. */\n request: ModelEndpointRequest\n /** Model ids to check. */\n models: string[]\n /** When true, additionally spend a small chat probe per model. Default false. */\n probe?: boolean\n /**\n * Output-token budget per probe. Default `PROBE_MAX_TOKENS`. Lowering it\n * below the reasoning floor makes healthy reasoning models report\n * `budgetExhausted` instead of proving their identity.\n */\n probeMaxTokens?: number\n}\n\nexport interface PreflightOutcome {\n succeeded: boolean\n value: ModelPreflight[] | null\n error: string | null\n}\n\ninterface ModelsListBody {\n data?: ReadonlyArray<{ id?: unknown }>\n}\n\ninterface ChatErrorBody {\n error?: { message?: unknown }\n message?: unknown\n}\n\ninterface ChatProbeBody {\n model?: unknown\n}\n\n/** Extract `error.message` (then top-level `message`) from a chat-completions error body. */\nfunction errorMessage(body: unknown): string | null {\n if (body == null || typeof body !== 'object') return null\n const b = body as ChatErrorBody\n if (b.error && typeof b.error.message === 'string') return b.error.message\n if (typeof b.message === 'string') return b.message\n return null\n}\n\n/**\n * Check that `models` are reachable on the router. Returns a typed outcome —\n * a network failure yields `{ succeeded: false, error }`, never a throw and\n * never a partial result silently reported as success. No retries, no\n * fallbacks.\n *\n * The membership check (one GET) always runs. When `probe` is true, each model\n * additionally gets a small chat probe so a model that is listed but\n * unconfigured (a 401 `model_not_found` from the router) is caught.\n */\nexport async function preflightModels(opts: PreflightModelsOptions): Promise<PreflightOutcome> {\n const maxTokens = opts.probeMaxTokens ?? PROBE_MAX_TOKENS\n if (!Number.isInteger(maxTokens) || maxTokens <= 0) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: probeMaxTokens must be a positive integer, got ${maxTokens}`,\n }\n }\n\n let served: Set<string>\n try {\n const res = await opts.request({ kind: 'list-models' })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: list-models → ${res.status} ${text.slice(0, 400)}`,\n }\n }\n const body = (await res.json()) as ModelsListBody\n const ids = Array.isArray(body.data) ? body.data : []\n served = new Set(ids.map((m) => m.id).filter((id): id is string => typeof id === 'string'))\n } catch (err) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: list-models failed — ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n\n const results: ModelPreflight[] = []\n for (const model of opts.models) {\n const listed = served.has(model)\n if (!opts.probe) {\n results.push({\n model,\n listed,\n served: null,\n status: null,\n detail: null,\n budgetExhausted: false,\n substitution: null,\n })\n continue\n }\n try {\n const res = await opts.request({ kind: 'probe', model, maxOutputTokens: maxTokens })\n let detail: string | null = null\n let substitution: ServedModelCheck | null = null\n let budgetExhausted = false\n const body = await res.json().catch(() => null)\n if (res.ok) {\n const echoed = (body as ChatProbeBody | null)?.model\n substitution = checkServedModel(\n model,\n typeof echoed === 'string' && echoed.trim() !== '' ? echoed : null,\n )\n } else {\n detail = errorMessage(body)\n budgetExhausted = detail !== null && REASONING_BUDGET_EXHAUSTED.test(detail)\n // The provider took the request and burned the budget, so the id is\n // live. It echoed no model, so identity stays unproven and the default\n // `allowUnreported: false` still refuses the run.\n if (budgetExhausted) substitution = checkServedModel(model, null)\n }\n results.push({\n model,\n listed,\n served: res.ok || budgetExhausted,\n status: res.status,\n detail,\n budgetExhausted,\n substitution,\n })\n } catch (err) {\n return {\n succeeded: false,\n value: null,\n error: `preflightModels: probe (model ${model}) failed — ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n return { succeeded: true, value: results, error: null }\n}\n\nexport class ModelsUnreachableError extends AgentEvalError {\n constructor(\n message: string,\n public readonly results: ReadonlyArray<ModelPreflight>,\n ) {\n super('config', message)\n this.name = 'ModelsUnreachableError'\n }\n}\n\nfunction describeFailure(r: ModelPreflight): string {\n if (!r.listed) {\n const probeNote =\n r.served === false ? ` (probe ${r.status}${r.detail ? `: ${r.detail}` : ''})` : ''\n return `${r.model}: not in /models${probeNote}`\n }\n if (r.served === false) {\n return `${r.model}: listed but probe ${r.status}${r.detail ? ` — ${r.detail}` : ''}`\n }\n if (r.budgetExhausted) {\n return (\n `${r.model}: alive but the probe ran out of reasoning budget (status ${r.status}` +\n `${r.detail ? `: ${r.detail}` : ''}) — it echoed no model id, so identity is unproven. ` +\n 'Raise probeMaxTokens, or pass allowUnreported to accept reachability without identity.'\n )\n }\n // listed, probe 2xx — but a different model answered\n const s = r.substitution\n if (s?.verdict === 'unreported') {\n return `${r.model}: probe answered without echoing a model id — identity unproven`\n }\n return `${r.model}: probe answered by ${s?.served} (${s?.verdict})`\n}\n\nexport interface AssertModelsServedOptions extends PreflightModelsOptions {\n /**\n * Accept a probe answered by a different model of the same provider family.\n * Default false. Only meaningful with `probe: true`.\n */\n allowWithinFamily?: boolean\n /**\n * Accept a probe whose response echoed no model id. Default false — an\n * unidentified response cannot prove the requested model is the one running.\n */\n allowUnreported?: boolean\n}\n\n/**\n * Throw `ModelsUnreachableError` naming EVERY model that is unusable for a\n * measured run — with status, detail, and served identity per model. A model\n * is unusable when it is unlisted, when its probe fails, or when its probe is\n * answered by a different model than the one requested. Callers gate a\n * campaign on this before spending tokens. When the network call itself fails\n * the underlying outcome error is rethrown — there is no partial silent pass.\n *\n * Substitution is only detectable with `probe: true`; a membership-only check\n * proves an id is in the catalogue, never that the catalogue entry answers.\n */\nexport async function assertModelsServed(\n opts: AssertModelsServedOptions,\n): Promise<ModelPreflight[]> {\n const outcome = await preflightModels(opts)\n if (!outcome.succeeded || outcome.value === null) {\n throw new ConfigError(\n outcome.error ?? 'assertModelsServed: preflight failed without an error message',\n )\n }\n const bad = outcome.value.filter(\n (r) =>\n !r.listed ||\n r.served === false ||\n (r.substitution !== null && !servedModelAcceptable(r.substitution, opts)),\n )\n if (bad.length > 0) {\n throw new ModelsUnreachableError(\n `assertModelsServed: ${bad.length}/${outcome.value.length} model(s) unusable on the router — ${bad\n .map(describeFailure)\n .join('; ')}`,\n outcome.value,\n )\n }\n return outcome.value\n}\n","/**\n * ModelSeats — the program's model seating chart.\n *\n * One object names which model fills each role in an eval program: the worker\n * under evaluation, the judge panel, the analyst, the reflection/driver model,\n * and the verifier. Re-tiering an entire program (economy ↔ frontier) is one\n * swapped object instead of a hunt through call sites.\n *\n * Wiring points — consumers thread seats; this module implements none of them\n * (those files belong to other surfaces):\n * - `judges` → `ensembleJudge({ models: seats.judges, … })` (src/judge-panel.ts)\n * and the `JudgeConfig`s handed to `makeEvalTools({ judges })`\n * (src/eval-tools.ts).\n * - `reflection` → the model configured by a custom `SurfaceProposer` or\n * external optimization engine.\n * - `worker` → the dispatch model the agent itself calls — the model an\n * `AgentProfile` declares.\n * - `analyst` → the LLM behind `analyzeRuns` / analyst-registry kinds.\n * - `verifier` → completion-verifier / objective-checker model.\n * - campaign cells thread `judges` + driver models the same way; that wiring\n * lands with the campaign surface, not here.\n *\n * `resolveSeat` is the only read path: an unset seat with no explicit fallback\n * throws — a model id is a budget decision, never a silent default.\n */\n\nimport { ConfigError, ValidationError } from './errors'\n\nexport interface ModelSeats {\n /** The model under evaluation — what the agent itself dispatches with. */\n worker?: string\n /** Judge-panel model ids — thread into `ensembleJudge({ models })`. */\n judges?: string[]\n /** Analyst model — `analyzeRuns` / analyst-registry LLM calls. */\n analyst?: string\n /** Reflection or candidate-generation model. */\n reflection?: string\n /** Verifier model — completion/objective checking. */\n verifier?: string\n}\n\nexport type SeatName = keyof ModelSeats\n\nexport type SeatPresetName = keyof typeof seatPresets\n\n/**\n * Tier presets — plain data, swap or spread freely.\n *\n * A preset names REQUESTED ids, and a requested id is NOT a guarantee of\n * family, of provider, or of liveness. A routing gateway can accept any id\n * below and answer from a different model on HTTP 200, with only the response\n * body's `model` field betraying the swap. The served assertion is the\n * guarantee: gate a run on `assertModelsServed({ probe: true })` and assert\n * `assertServedModel` per call. `assertCrossFamily` over these ids proves the\n * configuration is diverse; only `assertCrossFamilyServed` over the ids that\n * ANSWERED proves the run was.\n *\n * `economy` names ids a live router probe answered from the provider their\n * name implies, so the judge trio spanned three provider families (deepseek /\n * zhipu / google) as configured and, at that probe, as served. A preset is\n * only as good as its last probe: ids go dead and start resolving elsewhere\n * without notice, so re-probe rather than trusting this list.\n *\n * `frontier` is deliberately EMPTY: entitled frontier ids vary per router\n * account, and a hardcoded claude/gpt-5 id 401s on keys that lack it. Supply\n * your own: `{ ...seatPresets.frontier, worker: '<your-frontier-id>', … }` —\n * `resolveSeat` throws on every seat you haven't filled.\n */\nexport const seatPresets: Record<'economy' | 'frontier', ModelSeats> = {\n economy: {\n worker: 'zai/glm-5.2',\n judges: ['deepseek-v4-pro', 'zai/glm-5.2', 'google/gemini-2.5-flash'],\n analyst: 'zai/glm-5.2',\n reflection: 'zai/glm-5.2',\n verifier: 'deepseek-v4-pro',\n },\n frontier: {},\n}\n\n/** Thrown by `resolveSeat` when a seat is unset and no fallback was given. */\nexport class SeatUnsetError extends ConfigError {\n constructor(public readonly seat: SeatName) {\n super(\n `ModelSeats: seat '${seat}' is unset and no fallback was given — ` +\n 'name a model explicitly (a model id is a budget decision, never a silent default)',\n )\n }\n}\n\n/**\n * Read one seat. Blank strings and empty arrays count as unset (env-var\n * plumbing produces them); malformed values (non-string seat, non-array or\n * blank-entry `judges`) throw `ValidationError`. When the seat is unset, an\n * explicit `fallback` is returned (`[fallback]` for `judges` — a one-model\n * panel); without one, `SeatUnsetError`.\n */\nexport function resolveSeat(seats: ModelSeats, seat: 'judges', fallback?: string): string[]\nexport function resolveSeat(\n seats: ModelSeats,\n seat: Exclude<SeatName, 'judges'>,\n fallback?: string,\n): string\nexport function resolveSeat(seats: ModelSeats, seat: SeatName, fallback?: string): string | string[]\nexport function resolveSeat(\n seats: ModelSeats,\n seat: SeatName,\n fallback?: string,\n): string | string[] {\n const value = seats[seat]\n if (seat === 'judges') {\n if (value !== undefined && !Array.isArray(value)) {\n throw new ValidationError(`ModelSeats: seat 'judges' must be a string[], got ${typeof value}`)\n }\n const models = Array.isArray(value) ? value : []\n if (models.length > 0) {\n const blank = models.findIndex((m) => typeof m !== 'string' || m.trim() === '')\n if (blank >= 0) {\n throw new ValidationError(\n `ModelSeats: judges[${blank}] is blank — every panel model must be a non-empty id`,\n )\n }\n return [...models]\n }\n } else {\n if (value !== undefined && typeof value !== 'string') {\n throw new ValidationError(`ModelSeats: seat '${seat}' must be a string, got ${typeof value}`)\n }\n if (typeof value === 'string' && value.trim() !== '') return value\n }\n if (fallback !== undefined) {\n if (fallback.trim() === '') {\n throw new ValidationError(`ModelSeats: fallback for seat '${seat}' is blank`)\n }\n return seat === 'judges' ? [fallback] : fallback\n }\n throw new SeatUnsetError(seat)\n}\n","/**\n * Versioned prompt registry.\n *\n * Every prompt used in an eval run is registered with an explicit version.\n * Reports include the content hash so A/B compares are rigorous: if the\n * hash changes between two reports, the prompt actually changed; if it\n * matches, the variance is elsewhere.\n *\n * Hash is SHA-256(content), truncated to 12 hex chars for readability.\n * Uses the Web Crypto API (works in Workers, Node 22+, browsers).\n */\n\nexport interface PromptHandle {\n /** Stable human-readable id, e.g. 'browser.system' */\n id: string\n /** Caller-chosen version string, e.g. 'v3' or '2026-04-20' */\n version: string\n /** SHA-256 of content, 12-hex-char prefix */\n hash: string\n /** Full prompt body */\n content: string\n}\n\nexport class PromptRegistry {\n private readonly entries = new Map<string, PromptHandle>() // `${id}@${version}` → handle\n\n /**\n * Register a prompt. Re-registering the same id+version with DIFFERENT\n * content throws — versions are immutable. Re-registering with the SAME\n * content is a no-op (idempotent).\n */\n async register(id: string, version: string, content: string): Promise<PromptHandle> {\n validateId(id)\n validateVersion(version)\n\n const key = makeKey(id, version)\n const hash = await hashContent(content)\n const existing = this.entries.get(key)\n if (existing) {\n if (existing.hash !== hash) {\n throw new Error(\n `Prompt ${key} already registered with a different hash (${existing.hash} vs ${hash}). Bump the version.`,\n )\n }\n return existing\n }\n const handle: PromptHandle = { id, version, hash, content }\n this.entries.set(key, handle)\n return handle\n }\n\n /** Look up a registered prompt. Throws if unknown — no implicit defaults. */\n get(id: string, version: string): PromptHandle {\n const key = makeKey(id, version)\n const handle = this.entries.get(key)\n if (!handle) throw new Error(`Prompt ${key} not registered`)\n return handle\n }\n\n /** Return all versions of an id, newest-first (lex-descending on version). */\n listVersions(id: string): PromptHandle[] {\n return [...this.entries.values()]\n .filter((h) => h.id === id)\n .sort((a, b) => b.version.localeCompare(a.version))\n }\n\n /** Snapshot the whole registry — useful for including in reports. */\n list(): PromptHandle[] {\n return [...this.entries.values()]\n }\n\n /** Verify a hash against registered content. Returns null if not found. */\n verifyHash(id: string, version: string, expectedHash: string): boolean | null {\n const handle = this.entries.get(makeKey(id, version))\n if (!handle) return null\n return handle.hash === expectedHash\n }\n}\n\n/** SHA-256(content) → first 12 hex chars. Stable across runtimes. */\nexport async function hashContent(content: string): Promise<string> {\n const bytes = new TextEncoder().encode(content)\n const digest = await crypto.subtle.digest('SHA-256', bytes)\n const full = Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return full.slice(0, 12)\n}\n\nfunction makeKey(id: string, version: string): string {\n return `${id}@${version}`\n}\n\nconst ID_RE = /^[a-z][a-z0-9._-]*$/i\nfunction validateId(id: string): void {\n if (!ID_RE.test(id)) {\n throw new Error(`Invalid prompt id \"${id}\": must match ${ID_RE}`)\n }\n}\n\nfunction validateVersion(version: string): void {\n if (!version || version.length > 64) {\n throw new Error(`Invalid version \"${version}\": must be 1–64 chars`)\n }\n}\n","import { aggregateRunScore, type RunScore, type RunScoreWeights } from './run-score'\nimport type { SteeringBundle } from './steering'\n\nexport type SteeringOptimizerBackend = 'pairwise'\n\nexport interface SteeringOptimizationRow {\n variantId: string\n scenarioId: string\n bundle: SteeringBundle\n score: RunScore\n metadata?: Record<string, unknown>\n}\n\nexport interface SteeringOptimizationSelector {\n backend: SteeringOptimizerBackend\n signature?: string\n labels?: string[]\n rationale?: string\n}\n\nexport interface SteeringOptimizationResult {\n backend: SteeringOptimizerBackend\n recommendedVariantId: string\n rationale: string\n rankings: Array<{ variantId: string; mean: number; runs: number }>\n selector?: SteeringOptimizationSelector\n skipped?: boolean\n}\n\nexport interface SteeringOptimizerConfig {\n weights?: Partial<RunScoreWeights>\n}\n\n/**\n * Rank already-evaluated steering variants.\n *\n * Model-backed candidate generation belongs to the official GEPA campaign\n * integration. This class only performs the deterministic selection it owns.\n */\nexport class PairwiseSteeringOptimizer {\n optimize(\n rows: SteeringOptimizationRow[],\n config: SteeringOptimizerConfig = {},\n ): SteeringOptimizationResult {\n const rankings = rankRows(rows, config.weights)\n if (rankings.length === 0) throw new Error('no steering optimization rows')\n return {\n backend: 'pairwise',\n recommendedVariantId: rankings[0]!.variantId,\n rationale: `Highest observed mean aggregate across ${rows.length} scored run(s).`,\n rankings,\n }\n }\n}\n\nfunction rankRows(\n rows: readonly SteeringOptimizationRow[],\n weights?: Partial<RunScoreWeights>,\n): Array<{ variantId: string; mean: number; runs: number }> {\n const buckets = new Map<string, number[]>()\n for (const row of rows) {\n const values = buckets.get(row.variantId) ?? []\n values.push(aggregateRunScore(row.score, weights))\n buckets.set(row.variantId, values)\n }\n return [...buckets.entries()]\n .map(([variantId, values]) => ({\n variantId,\n mean: values.reduce((sum, value) => sum + value, 0) / values.length,\n runs: values.length,\n }))\n .sort((a, b) => b.mean - a.mean)\n}\n"],"mappings":"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"}