@tangle-network/agent-eval 0.187.2 → 0.189.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 (279) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/dist/adapters/http.d.ts +2 -2
  3. package/dist/{agent-profile-uAIQK3Nr.d.ts → agent-profile-DNV_U6QR.d.ts} +4 -4
  4. package/dist/{agent-profile-uAIQK3Nr.d.ts.map → agent-profile-DNV_U6QR.d.ts.map} +1 -1
  5. package/dist/analyst/index.d.ts +12 -12
  6. package/dist/analyst/index.d.ts.map +1 -1
  7. package/dist/analyst/index.js +7 -7
  8. package/dist/{analyze-runs-DapYZz02.d.ts → analyze-runs-BvK4-wSs.d.ts} +5 -5
  9. package/dist/{analyze-runs-DapYZz02.d.ts.map → analyze-runs-BvK4-wSs.d.ts.map} +1 -1
  10. package/dist/{analyze-runs-DCY7LMt4.js → analyze-runs-SCSWYpy0.js} +17 -9
  11. package/dist/analyze-runs-SCSWYpy0.js.map +1 -0
  12. package/dist/{benchmark-command-DGokT8zd.js → benchmark-command-BhhAYstU.js} +14 -14
  13. package/dist/benchmark-command-BhhAYstU.js.map +1 -0
  14. package/dist/benchmarks/index.d.ts +4 -4
  15. package/dist/benchmarks/index.js +3 -3
  16. package/dist/builder-eval/index.d.ts +3 -3
  17. package/dist/builder-eval/index.js +1 -1
  18. package/dist/campaign/index.d.ts +5 -5
  19. package/dist/campaign/index.js +7 -7
  20. package/dist/{campaign-DlxdTOvw.js → campaign-BWoSQPSU.js} +10 -10
  21. package/dist/{campaign-DlxdTOvw.js.map → campaign-BWoSQPSU.js.map} +1 -1
  22. package/dist/{campaign-evidence-IF1p0oDa.js → campaign-evidence-CBlGJ3kC.js} +5 -5
  23. package/dist/campaign-evidence-CBlGJ3kC.js.map +1 -0
  24. package/dist/{chat-client-DqPqWzVV.js → chat-client-C4dg7Ng_.js} +2 -2
  25. package/dist/{chat-client-DqPqWzVV.js.map → chat-client-C4dg7Ng_.js.map} +1 -1
  26. package/dist/{chat-json-call-C-DnDxEy.js → chat-json-call-JVGbfx95.js} +2 -2
  27. package/dist/{chat-json-call-C-DnDxEy.js.map → chat-json-call-JVGbfx95.js.map} +1 -1
  28. package/dist/cli.js +4 -4
  29. package/dist/{client-DCc7a8ZC.d.ts → client-BhEyAdfe.d.ts} +4 -4
  30. package/dist/{client-DCc7a8ZC.d.ts.map → client-BhEyAdfe.d.ts.map} +1 -1
  31. package/dist/{client-CXE-U1SA.js → client-QwJpsNYU.js} +5 -1
  32. package/dist/client-QwJpsNYU.js.map +1 -0
  33. package/dist/contract/index.d.ts +11 -11
  34. package/dist/contract/index.js +22 -13
  35. package/dist/contract/index.js.map +1 -1
  36. package/dist/{counterfactual-CLgrwhkY.d.ts → counterfactual-CPaWN99-.d.ts} +4 -4
  37. package/dist/{counterfactual-CLgrwhkY.d.ts.map → counterfactual-CPaWN99-.d.ts.map} +1 -1
  38. package/dist/{counterfactual-Bjq1mlUu.js → counterfactual-DtMWvn7D.js} +2 -2
  39. package/dist/{counterfactual-Bjq1mlUu.js.map → counterfactual-DtMWvn7D.js.map} +1 -1
  40. package/dist/deep-freeze-CurcOQg3.js +16 -0
  41. package/dist/deep-freeze-CurcOQg3.js.map +1 -0
  42. package/dist/{default-registry-DMxeb4GD.d.ts → default-registry-B5HrwrPM.d.ts} +6 -6
  43. package/dist/{default-registry-DMxeb4GD.d.ts.map → default-registry-B5HrwrPM.d.ts.map} +1 -1
  44. package/dist/{default-registry-Ca2IWH1X.js → default-registry-m2jhbG6Q.js} +4 -3
  45. package/dist/default-registry-m2jhbG6Q.js.map +1 -0
  46. package/dist/{define-agent-eval-C0EqJ9Gz.js → define-agent-eval-98sgUaC1.js} +8 -8
  47. package/dist/{define-agent-eval-C0EqJ9Gz.js.map → define-agent-eval-98sgUaC1.js.map} +1 -1
  48. package/dist/{define-agent-eval-CGBwPPaq.d.ts → define-agent-eval-q6890HU4.d.ts} +7 -7
  49. package/dist/{define-agent-eval-CGBwPPaq.d.ts.map → define-agent-eval-q6890HU4.d.ts.map} +1 -1
  50. package/dist/diagnosis/index.d.ts +38 -96
  51. package/dist/diagnosis/index.d.ts.map +1 -1
  52. package/dist/diagnosis/index.js +84 -135
  53. package/dist/diagnosis/index.js.map +1 -1
  54. package/dist/{dspy-rlm-engine-BE9lCzzL.js → dspy-rlm-engine-DLYttKBm.js} +3 -3
  55. package/dist/{dspy-rlm-engine-BE9lCzzL.js.map → dspy-rlm-engine-DLYttKBm.js.map} +1 -1
  56. package/dist/emitter-DbMXUIVP.js +334 -0
  57. package/dist/emitter-DbMXUIVP.js.map +1 -0
  58. package/dist/{emitter-Cs0egaFd.d.ts → emitter-HcCmFQl_.d.ts} +37 -6
  59. package/dist/emitter-HcCmFQl_.d.ts.map +1 -0
  60. package/dist/{engine-DNlKhIm0.d.ts → engine-BkLCnZQX.d.ts} +15 -5
  61. package/dist/engine-BkLCnZQX.d.ts.map +1 -0
  62. package/dist/{eval-campaign-XFHEpN86.js → eval-campaign-C0Q1Eeo_.js} +8 -5
  63. package/dist/{eval-campaign-XFHEpN86.js.map → eval-campaign-C0Q1Eeo_.js.map} +1 -1
  64. package/dist/evaluation.d.ts +2 -2
  65. package/dist/{exact-types-BEHN7tnq.d.ts → exact-types-CfpP2A4Z.d.ts} +2 -2
  66. package/dist/{exact-types-BEHN7tnq.d.ts.map → exact-types-CfpP2A4Z.d.ts.map} +1 -1
  67. package/dist/experiment/index.d.ts +3 -3
  68. package/dist/experiment/index.js +2 -3
  69. package/dist/experiment/index.js.map +1 -1
  70. package/dist/{external-optimizer-process-BbhvXTFx.js → external-optimizer-process-C3quNeKV.js} +3 -3
  71. package/dist/{external-optimizer-process-BbhvXTFx.js.map → external-optimizer-process-C3quNeKV.js.map} +1 -1
  72. package/dist/{external-optimizer-subprocess-DMgmqTB6.js → external-optimizer-subprocess-BDwgKLO1.js} +3 -3
  73. package/dist/{external-optimizer-subprocess-DMgmqTB6.js.map → external-optimizer-subprocess-BDwgKLO1.js.map} +1 -1
  74. package/dist/{failure-cluster-OldNRoAt.d.ts → failure-cluster-CbgEDcFJ.d.ts} +3 -3
  75. package/dist/{failure-cluster-OldNRoAt.d.ts.map → failure-cluster-CbgEDcFJ.d.ts.map} +1 -1
  76. package/dist/failure-taxonomy-CjabTATj.js +538 -0
  77. package/dist/failure-taxonomy-CjabTATj.js.map +1 -0
  78. package/dist/{feedback-trajectory-CytTR7u4.d.ts → feedback-trajectory-B3ZSkfAq.d.ts} +6 -6
  79. package/dist/{feedback-trajectory-CytTR7u4.d.ts.map → feedback-trajectory-B3ZSkfAq.d.ts.map} +1 -1
  80. package/dist/hosted/index.d.ts +2 -2
  81. package/dist/hosted/index.d.ts.map +1 -1
  82. package/dist/hosted/index.js +1 -1
  83. package/dist/{index-vYNHCV2G.d.ts → index-2e_MTznj.d.ts} +8 -8
  84. package/dist/{index-vYNHCV2G.d.ts.map → index-2e_MTznj.d.ts.map} +1 -1
  85. package/dist/{index-CKZa_rnt.d.ts → index-Bcc9PkOz.d.ts} +3 -3
  86. package/dist/{index-CKZa_rnt.d.ts.map → index-Bcc9PkOz.d.ts.map} +1 -1
  87. package/dist/{index-u0d1Jp4F.d.ts → index-BqDJ6fUK.d.ts} +45 -24
  88. package/dist/index-BqDJ6fUK.d.ts.map +1 -0
  89. package/dist/{index-BRsrfSHT.d.ts → index-CnJOPR_E.d.ts} +10 -10
  90. package/dist/{index-BRsrfSHT.d.ts.map → index-CnJOPR_E.d.ts.map} +1 -1
  91. package/dist/{index-YZrbnBSV.d.ts → index-Dk1dOUfm.d.ts} +11 -11
  92. package/dist/{index-YZrbnBSV.d.ts.map → index-Dk1dOUfm.d.ts.map} +1 -1
  93. package/dist/index.d.ts +384 -69
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1492 -217
  96. package/dist/index.js.map +1 -1
  97. package/dist/{insight-report-DpOo-3iL.d.ts → insight-report-CvPkEIcC.d.ts} +14 -7
  98. package/dist/insight-report-CvPkEIcC.d.ts.map +1 -0
  99. package/dist/{integrity-Cy9WHAtb.js → integrity-BFP4kjGj.js} +6 -1
  100. package/dist/integrity-BFP4kjGj.js.map +1 -0
  101. package/dist/{integrity-rGOfSUle.d.ts → integrity-CaeNeusS.d.ts} +4 -4
  102. package/dist/integrity-CaeNeusS.d.ts.map +1 -0
  103. package/dist/jev.d.ts +2 -2
  104. package/dist/jev.js +2 -1
  105. package/dist/jev.js.map +1 -1
  106. package/dist/{journal-BuRLm6ho.js → journal-CDP0Vhx_.js} +262 -115
  107. package/dist/journal-CDP0Vhx_.js.map +1 -0
  108. package/dist/{kind-factory-V79Hw0AU.js → kind-factory-BGwN0nE6.js} +17 -5
  109. package/dist/{kind-factory-V79Hw0AU.js.map → kind-factory-BGwN0nE6.js.map} +1 -1
  110. package/dist/ledger-core/index.d.ts +2 -2
  111. package/dist/ledger-core/index.js +1 -1
  112. package/dist/{llm-client-DDhZ29Vm.js → llm-client-DF9bPNYA.js} +2 -2
  113. package/dist/{llm-client-DDhZ29Vm.js.map → llm-client-DF9bPNYA.js.map} +1 -1
  114. package/dist/{llm-judge-BVso5x-u.js → llm-judge-M_l_WXw2.js} +26 -24
  115. package/dist/llm-judge-M_l_WXw2.js.map +1 -0
  116. package/dist/{matrix-CPKsRY8Y.d.ts → matrix-CNypzP-v.d.ts} +2 -2
  117. package/dist/{matrix-CPKsRY8Y.d.ts.map → matrix-CNypzP-v.d.ts.map} +1 -1
  118. package/dist/meta-eval/index.d.ts +4 -4
  119. package/dist/{mint-BI14xehJ.d.ts → mint-DsS38v5c.d.ts} +25 -5
  120. package/dist/{mint-BI14xehJ.d.ts.map → mint-DsS38v5c.d.ts.map} +1 -1
  121. package/dist/{mint-B4zgSAJW.js → mint-iCD-W43s.js} +30 -12
  122. package/dist/mint-iCD-W43s.js.map +1 -0
  123. package/dist/multishot/golden/index.d.ts +1 -1
  124. package/dist/multishot/index.d.ts +2 -2
  125. package/dist/openapi.json +1 -1
  126. package/dist/pipelines/index.d.ts +67 -12
  127. package/dist/pipelines/index.d.ts.map +1 -1
  128. package/dist/pipelines/index.js +178 -41
  129. package/dist/pipelines/index.js.map +1 -1
  130. package/dist/{prime-protocol-CDBcL9NM.d.ts → prime-protocol-Fwvctmhm.d.ts} +2 -2
  131. package/dist/{prime-protocol-CDBcL9NM.d.ts.map → prime-protocol-Fwvctmhm.d.ts.map} +1 -1
  132. package/dist/{produced-state-Cn9ECr4v.js → produced-state-BOY98IJO.js} +4 -4
  133. package/dist/{produced-state-Cn9ECr4v.js.map → produced-state-BOY98IJO.js.map} +1 -1
  134. package/dist/{query-D6W6MaGx.d.ts → query-DBUQhehH.d.ts} +3 -3
  135. package/dist/{query-D6W6MaGx.d.ts.map → query-DBUQhehH.d.ts.map} +1 -1
  136. package/dist/random-DGEyr3zG.d.ts +83 -0
  137. package/dist/random-DGEyr3zG.d.ts.map +1 -0
  138. package/dist/{raw-provider-sink-BQd7mzyT.js → raw-provider-sink-C96CcqeG.js} +19 -56
  139. package/dist/raw-provider-sink-C96CcqeG.js.map +1 -0
  140. package/dist/redact-DPoH1-OW.d.ts +158 -0
  141. package/dist/redact-DPoH1-OW.d.ts.map +1 -0
  142. package/dist/redact-DxwlUAvh.js +824 -0
  143. package/dist/redact-DxwlUAvh.js.map +1 -0
  144. package/dist/{registry-D5Ly3GRV.d.ts → registry-mAQVtuLx.d.ts} +4 -4
  145. package/dist/{registry-D5Ly3GRV.d.ts.map → registry-mAQVtuLx.d.ts.map} +1 -1
  146. package/dist/{release-confidence-CSp3MsU4.d.ts → release-confidence-CkoXFx9I.d.ts} +4 -4
  147. package/dist/{release-confidence-CSp3MsU4.d.ts.map → release-confidence-CkoXFx9I.d.ts.map} +1 -1
  148. package/dist/{release-confidence-RanRUXRW.js → release-confidence-XQm_xjhR.js} +3 -3
  149. package/dist/release-confidence-XQm_xjhR.js.map +1 -0
  150. package/dist/{report-command-CSTjzFGY.js → report-command-DKJ_yAIj.js} +21 -12
  151. package/dist/{report-command-CSTjzFGY.js.map → report-command-DKJ_yAIj.js.map} +1 -1
  152. package/dist/reporting.d.ts +3 -3
  153. package/dist/reporting.js +1 -1
  154. package/dist/{researcher-D7E92STT.d.ts → researcher-DojEMb7E.d.ts} +7 -7
  155. package/dist/{researcher-D7E92STT.d.ts.map → researcher-DojEMb7E.d.ts.map} +1 -1
  156. package/dist/{reward-hacking-BIQ2BWLG.d.ts → reward-hacking-Cyk-QHk9.d.ts} +2 -2
  157. package/dist/{reward-hacking-BIQ2BWLG.d.ts.map → reward-hacking-Cyk-QHk9.d.ts.map} +1 -1
  158. package/dist/rl.d.ts +11 -10
  159. package/dist/rl.d.ts.map +1 -1
  160. package/dist/rl.js +7 -6
  161. package/dist/rl.js.map +1 -1
  162. package/dist/rollout/index.d.ts +4 -4
  163. package/dist/rollout/index.js +2 -2
  164. package/dist/{rollout-C0Ifk3vK.js → rollout-B-XBReTC.js} +2 -2
  165. package/dist/{rollout-C0Ifk3vK.js.map → rollout-B-XBReTC.js.map} +1 -1
  166. package/dist/{rubric-predictive-validity-CTU8y8Cv.d.ts → rubric-predictive-validity-DIUwJJ9Y.d.ts} +2 -2
  167. package/dist/{rubric-predictive-validity-CTU8y8Cv.d.ts.map → rubric-predictive-validity-DIUwJJ9Y.d.ts.map} +1 -1
  168. package/dist/{run-record-tg_5H2IK.js → run-record-BRlM99rX.js} +41 -3
  169. package/dist/run-record-BRlM99rX.js.map +1 -0
  170. package/dist/{run-record-D9wS35fK.d.ts → run-record-DF-fuu31.d.ts} +59 -7
  171. package/dist/run-record-DF-fuu31.d.ts.map +1 -0
  172. package/dist/{run-record-CNNzWGpB.js → run-record-DnMFyg_g.js} +26 -13
  173. package/dist/run-record-DnMFyg_g.js.map +1 -0
  174. package/dist/{schema-CR5cpjQ3.d.ts → schema-2g7trUwH.d.ts} +17 -2
  175. package/dist/schema-2g7trUwH.d.ts.map +1 -0
  176. package/dist/{schema-BzWDXhOR.d.ts → schema-B5LtYvn9.d.ts} +7 -5
  177. package/dist/{schema-BzWDXhOR.d.ts.map → schema-B5LtYvn9.d.ts.map} +1 -1
  178. package/dist/schema-C1aaAxTf.js.map +1 -1
  179. package/dist/schema-CSf6qWgZ.js.map +1 -1
  180. package/dist/{semantic-concept-judge-Cnt0TWp0.js → semantic-concept-judge-Cm2K2wAo.js} +6 -6
  181. package/dist/{semantic-concept-judge-Cnt0TWp0.js.map → semantic-concept-judge-Cm2K2wAo.js.map} +1 -1
  182. package/dist/{series-convergence-BnMs_uAr.d.ts → series-convergence-DY7ha0kx.d.ts} +2 -2
  183. package/dist/{series-convergence-BnMs_uAr.d.ts.map → series-convergence-DY7ha0kx.d.ts.map} +1 -1
  184. package/dist/{server-DmpcFiVK.js → server-C8XvqCg8.js} +2 -2
  185. package/dist/{server-DmpcFiVK.js.map → server-C8XvqCg8.js.map} +1 -1
  186. package/dist/{skillopt-optimization-method-Cc9SVLqi.js → skillopt-optimization-method-BVSB676o.js} +7 -7
  187. package/dist/{skillopt-optimization-method-Cc9SVLqi.js.map → skillopt-optimization-method-BVSB676o.js.map} +1 -1
  188. package/dist/spans-W0o8pbEg.d.ts +60 -0
  189. package/dist/spans-W0o8pbEg.d.ts.map +1 -0
  190. package/dist/{statistical-heldout-DTmhTW8P.d.ts → statistical-heldout-plAHG82H.d.ts} +3 -3
  191. package/dist/{statistical-heldout-DTmhTW8P.d.ts.map → statistical-heldout-plAHG82H.d.ts.map} +1 -1
  192. package/dist/{store-BErPvYBr.d.ts → store-C4avFjIi.d.ts} +2 -2
  193. package/dist/{store-BErPvYBr.d.ts.map → store-C4avFjIi.d.ts.map} +1 -1
  194. package/dist/{store-otlp-2gYCy-v0.js → store-otlp-D0AV4cvB.js} +2 -2
  195. package/dist/{store-otlp-2gYCy-v0.js.map → store-otlp-D0AV4cvB.js.map} +1 -1
  196. package/dist/{store-tool-spans-B3bX9yqn.d.ts → store-tool-spans-8PAyhRqb.d.ts} +9 -54
  197. package/dist/store-tool-spans-8PAyhRqb.d.ts.map +1 -0
  198. package/dist/{store-tool-spans-B1e6Auc2.js → store-tool-spans-B_0mXvYl.js} +4 -4
  199. package/dist/{store-tool-spans-B1e6Auc2.js.map → store-tool-spans-B_0mXvYl.js.map} +1 -1
  200. package/dist/storyboard/index.d.ts +1 -1
  201. package/dist/{summary-report-Iy6kXo8x.d.ts → summary-report-DvvesgR_.d.ts} +6 -5
  202. package/dist/summary-report-DvvesgR_.d.ts.map +1 -0
  203. package/dist/supervisor-run/index.d.ts +2 -2
  204. package/dist/supervisor-run/index.d.ts.map +1 -1
  205. package/dist/supervisor-run/index.js +1 -1
  206. package/dist/{tool-groups-veQYPiTy.d.ts → tool-groups-W7MJobX_.d.ts} +3 -3
  207. package/dist/tool-groups-W7MJobX_.d.ts.map +1 -0
  208. package/dist/{tool-waste-nbHPAxei.js → tool-waste-CJDfxH45.js} +3 -537
  209. package/dist/tool-waste-CJDfxH45.js.map +1 -0
  210. package/dist/{tool-waste-D23I0zWm.d.ts → tool-waste-CP5DO383.d.ts} +4 -4
  211. package/dist/{tool-waste-D23I0zWm.d.ts.map → tool-waste-CP5DO383.d.ts.map} +1 -1
  212. package/dist/trace-repair/index.d.ts +2 -2
  213. package/dist/traces.d.ts +12 -11
  214. package/dist/traces.d.ts.map +1 -1
  215. package/dist/traces.js +9 -9
  216. package/dist/{trajectory-D7qrNvaN.d.ts → trajectory-Y1fmdlw7.d.ts} +3 -3
  217. package/dist/{trajectory-D7qrNvaN.d.ts.map → trajectory-Y1fmdlw7.d.ts.map} +1 -1
  218. package/dist/trajectory-replay/index.d.ts +3 -3
  219. package/dist/trajectory-replay/index.js +2 -2
  220. package/dist/{types-BjB2wZM9.d.ts → types-Bay1dh2o.d.ts} +6 -6
  221. package/dist/{types-BjB2wZM9.d.ts.map → types-Bay1dh2o.d.ts.map} +1 -1
  222. package/dist/{types-BTRcIqFr.d.ts → types-BvmWNjjs.d.ts} +4 -4
  223. package/dist/{types-BTRcIqFr.d.ts.map → types-BvmWNjjs.d.ts.map} +1 -1
  224. package/dist/{types-CBbLtr2J.d.ts → types-C0bWoSKC.d.ts} +10 -11
  225. package/dist/types-C0bWoSKC.d.ts.map +1 -0
  226. package/dist/{types-C8VBbiw6.js → types-CW5b90JH.js} +2 -15
  227. package/dist/types-CW5b90JH.js.map +1 -0
  228. package/dist/{types--18oHwVF.d.ts → types-Cvqy7asY.d.ts} +3 -3
  229. package/dist/{types--18oHwVF.d.ts.map → types-Cvqy7asY.d.ts.map} +1 -1
  230. package/dist/{types-Tp5WhYL9.d.ts → types-DRNlLbBR.d.ts} +2 -2
  231. package/dist/{types-Tp5WhYL9.d.ts.map → types-DRNlLbBR.d.ts.map} +1 -1
  232. package/dist/wire/index.d.ts +3 -3
  233. package/dist/wire/index.js +1 -1
  234. package/docs/code-agent-intake.md +1 -1
  235. package/docs/diagnosis.md +2 -3
  236. package/docs/eval-surface-map.md +1 -1
  237. package/docs/experiment.md +0 -1
  238. package/docs/insight-report.md +3 -2
  239. package/docs/public-api.md +2 -2
  240. package/docs/redaction.md +59 -0
  241. package/docs/rollout.md +5 -5
  242. package/docs/search-history-receipts.md +1 -0
  243. package/docs/trace-contracts.md +102 -0
  244. package/docs/verdicts.md +1 -1
  245. package/package.json +3 -2
  246. package/dist/analyze-runs-DCY7LMt4.js.map +0 -1
  247. package/dist/benchmark-command-DGokT8zd.js.map +0 -1
  248. package/dist/campaign-evidence-IF1p0oDa.js.map +0 -1
  249. package/dist/client-CXE-U1SA.js.map +0 -1
  250. package/dist/default-registry-Ca2IWH1X.js.map +0 -1
  251. package/dist/emitter-Cs0egaFd.d.ts.map +0 -1
  252. package/dist/emitter-DeQHiDMm.js +0 -257
  253. package/dist/emitter-DeQHiDMm.js.map +0 -1
  254. package/dist/engine-DNlKhIm0.d.ts.map +0 -1
  255. package/dist/experiment-tracker-BKEumQug.js +0 -280
  256. package/dist/experiment-tracker-BKEumQug.js.map +0 -1
  257. package/dist/experiment-tracker-URRGP9ek.d.ts +0 -237
  258. package/dist/experiment-tracker-URRGP9ek.d.ts.map +0 -1
  259. package/dist/index-u0d1Jp4F.d.ts.map +0 -1
  260. package/dist/insight-report-DpOo-3iL.d.ts.map +0 -1
  261. package/dist/integrity-Cy9WHAtb.js.map +0 -1
  262. package/dist/integrity-rGOfSUle.d.ts.map +0 -1
  263. package/dist/journal-BuRLm6ho.js.map +0 -1
  264. package/dist/llm-judge-BVso5x-u.js.map +0 -1
  265. package/dist/mint-B4zgSAJW.js.map +0 -1
  266. package/dist/raw-provider-sink-BQd7mzyT.js.map +0 -1
  267. package/dist/redact-7Aq1ukl-.js +0 -107
  268. package/dist/redact-7Aq1ukl-.js.map +0 -1
  269. package/dist/release-confidence-RanRUXRW.js.map +0 -1
  270. package/dist/run-record-CNNzWGpB.js.map +0 -1
  271. package/dist/run-record-D9wS35fK.d.ts.map +0 -1
  272. package/dist/run-record-tg_5H2IK.js.map +0 -1
  273. package/dist/schema-CR5cpjQ3.d.ts.map +0 -1
  274. package/dist/store-tool-spans-B3bX9yqn.d.ts.map +0 -1
  275. package/dist/summary-report-Iy6kXo8x.d.ts.map +0 -1
  276. package/dist/tool-groups-veQYPiTy.d.ts.map +0 -1
  277. package/dist/tool-waste-nbHPAxei.js.map +0 -1
  278. package/dist/types-C8VBbiw6.js.map +0 -1
  279. package/dist/types-CBbLtr2J.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["populations","nonEmpty"],"sources":["../../src/experiment/budget.ts","../../src/experiment/funnel.ts","../../src/experiment/define.ts","../../src/experiment/evidence-record.ts","../../src/experiment/power.ts","../../src/experiment/prospective-canary-join.ts","../../src/experiment/randomized-canary.ts"],"sourcesContent":["/**\n * Matched-budget verification between arms, as a refusal object.\n *\n * A paired contrast is only meaningful when both arms spent comparable\n * resources; \"realized prompt and completion tokens must agree within 5%\" is\n * a registered rule, so its verification returns a verdict artifact — the\n * refusal lives inside the result, never in prose beside it.\n */\n\nimport { CaptureIntegrityError } from '../errors'\nimport type { MatchedBudgetRule } from './ast'\n\n/** Arms whose realized budgets diverge past the registered tolerance. */\nexport class MatchedBudgetError extends CaptureIntegrityError {}\n\nexport interface ArmRealizedBudget {\n armId: string\n /** Realized prompt + completion tokens the arm actually consumed. */\n realizedTokens: number\n}\n\nexport interface MatchedBudgetVerdict {\n rule: MatchedBudgetRule\n arms: ArmRealizedBudget[]\n /** (max - min) / max over all arms; 0 when every arm spent nothing. */\n maxRelativeGap: number\n /** The two arms with the widest gap; null when fewer than two arms. */\n widestPair: [string, string] | null\n matched: boolean\n /** Populated exactly when `matched` is false. */\n refusal: null | { onFail: 'refuse-contrast'; reason: string }\n}\n\n/**\n * Compare realized per-arm spend under the registered tolerance. Requires at\n * least two arms — a single arm has nothing to match against. Negative or\n * non-finite token counts are refused as evidence corruption, not compared.\n */\nexport function verifyMatchedBudgets(\n rule: MatchedBudgetRule,\n arms: readonly ArmRealizedBudget[],\n): MatchedBudgetVerdict {\n if (arms.length < 2) {\n throw new MatchedBudgetError(\n `verifyMatchedBudgets: need >= 2 arms to match budgets, got ${arms.length}`,\n )\n }\n for (const arm of arms) {\n if (!Number.isFinite(arm.realizedTokens) || arm.realizedTokens < 0) {\n throw new MatchedBudgetError(\n `verifyMatchedBudgets: arm '${arm.armId}' has invalid realized tokens ${arm.realizedTokens}`,\n )\n }\n }\n const sorted = [...arms].sort((a, b) => a.realizedTokens - b.realizedTokens)\n const min = sorted[0]!\n const max = sorted[sorted.length - 1]!\n const maxRelativeGap =\n max.realizedTokens === 0 ? 0 : (max.realizedTokens - min.realizedTokens) / max.realizedTokens\n const matched = maxRelativeGap <= rule.tolerance\n return {\n rule,\n arms: [...arms],\n maxRelativeGap,\n widestPair: [min.armId, max.armId],\n matched,\n refusal: matched\n ? null\n : {\n onFail: rule.onFail,\n reason:\n `realized ${rule.measure} diverge ${(maxRelativeGap * 100).toFixed(1)}% between ` +\n `'${min.armId}' (${min.realizedTokens}) and '${max.armId}' (${max.realizedTokens}) — ` +\n `registered tolerance is ${(rule.tolerance * 100).toFixed(1)}%; the contrast is refused`,\n },\n }\n}\n\n/** Throw the refusal for callers that gate the contrast on it. */\nexport function assertMatchedBudgets(\n rule: MatchedBudgetRule,\n arms: readonly ArmRealizedBudget[],\n): MatchedBudgetVerdict {\n const verdict = verifyMatchedBudgets(rule, arms)\n if (verdict.refusal) throw new MatchedBudgetError(verdict.refusal.reason)\n return verdict\n}\n","/**\n * The denominator chain as a first-class object.\n *\n * A benchmark whose denominator is not auditable is not a benchmark. Every\n * stage names what entered, what it removed, and what survived, so\n * `input = surviving + sum(excluded)` reads off the table instead of being\n * trusted. A stage that gains rows is refused at construction — a funnel is\n * monotone by definition, and a non-monotone one is a broken denominator,\n * not a formatting choice.\n *\n * The object is its own JSON render; `renderFunnelTable` is the text render.\n * `executeAdmissionRule` produces one by running a sealed {@link AdmissionRule}\n * over evidence records.\n */\n\nimport { CaptureIntegrityError } from '../errors'\nimport { type AdmissionRule, type EvidenceRecord, evaluatePredicate } from './ast'\n\n/** A funnel stage gained rows, double-counted them, or failed to reconcile. */\nexport class FunnelIntegrityError extends CaptureIntegrityError {}\n\nexport interface FunnelStageCount {\n id: string\n entering: number\n excluded: number\n remaining: number\n /** Named exclusion reasons summing to `excluded`, when the stage has them. */\n exclusions?: Record<string, number>\n /** Substrate checks this stage deliberately does not apply. Registered, never implicit. */\n waives?: string[]\n}\n\nexport interface FunnelPartitionCount {\n id: string\n /** Stage whose excluded rows the partition draws from. */\n from: string\n count: number\n /** A partition is reported separately and never pooled into the survivors. */\n pooling: 'never'\n}\n\nexport interface ExperimentFunnel {\n population: string\n input: number\n stages: FunnelStageCount[]\n surviving: number\n partitions: FunnelPartitionCount[]\n}\n\nexport interface FunnelStageInput {\n id: string\n /** Rows this stage removed. */\n excluded: number\n exclusions?: Record<string, number>\n waives?: string[]\n}\n\n/**\n * Build a funnel from counts and refuse anything non-monotone.\n *\n * Refusals: a negative count, a stage that gains rows (excluded < 0 is the\n * only way to gain — `remaining = entering - excluded` by construction, so a\n * gain cannot be smuggled in through `remaining`), named exclusions that do\n * not sum to the stage total, and a partition drawing from an unknown stage\n * or exceeding what that stage excluded.\n */\nexport function buildFunnel(input: {\n population: string\n input: number\n stages: FunnelStageInput[]\n partitions?: { id: string; from: string; count: number }[]\n}): ExperimentFunnel {\n if (!Number.isInteger(input.input) || input.input < 0) {\n throw new FunnelIntegrityError(\n `funnel input must be a non-negative integer, got ${input.input}`,\n )\n }\n let entering = input.input\n const stages: FunnelStageCount[] = []\n for (const stage of input.stages) {\n if (!Number.isInteger(stage.excluded)) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' excluded count must be an integer, got ${stage.excluded}`,\n )\n }\n if (stage.excluded < 0) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' gains ${-stage.excluded} rows — a funnel stage can only remove rows`,\n )\n }\n if (stage.excluded > entering) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' excludes ${stage.excluded} rows but only ${entering} entered`,\n )\n }\n if (stage.exclusions) {\n const sum = Object.values(stage.exclusions).reduce((a, b) => a + b, 0)\n if (sum !== stage.excluded) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' names exclusions summing to ${sum} but excludes ${stage.excluded}`,\n )\n }\n }\n const remaining = entering - stage.excluded\n stages.push({\n id: stage.id,\n entering,\n excluded: stage.excluded,\n remaining,\n ...(stage.exclusions ? { exclusions: { ...stage.exclusions } } : {}),\n ...(stage.waives ? { waives: [...stage.waives] } : {}),\n })\n entering = remaining\n }\n const byStage = new Map(stages.map((s) => [s.id, s]))\n const partitions: FunnelPartitionCount[] = (input.partitions ?? []).map((partition) => {\n const source = byStage.get(partition.from)\n if (!source) {\n throw new FunnelIntegrityError(\n `funnel partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n if (partition.count < 0 || partition.count > source.excluded) {\n throw new FunnelIntegrityError(\n `funnel partition '${partition.id}' counts ${partition.count} rows but stage '${partition.from}' excluded ${source.excluded}`,\n )\n }\n return { id: partition.id, from: partition.from, count: partition.count, pooling: 'never' }\n })\n const funnel: ExperimentFunnel = {\n population: input.population,\n input: input.input,\n stages,\n surviving: entering,\n partitions,\n }\n assertFunnelReconciles(funnel)\n return funnel\n}\n\n/** A chain that does not add up is a broken denominator, so this throws. */\nexport function assertFunnelReconciles(funnel: ExperimentFunnel): void {\n const excluded = funnel.stages.reduce((sum, stage) => sum + stage.excluded, 0)\n if (funnel.input !== funnel.surviving + excluded) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' does not reconcile: input ${funnel.input} != surviving ${funnel.surviving} + excluded ${excluded}`,\n )\n }\n let entering = funnel.input\n for (const stage of funnel.stages) {\n if (stage.entering !== entering || stage.remaining !== stage.entering - stage.excluded) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' stage '${stage.id}' does not chain: ` +\n `entering ${stage.entering} (expected ${entering}), remaining ${stage.remaining}`,\n )\n }\n if (stage.remaining > stage.entering) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' stage '${stage.id}' gains rows: ${stage.entering} -> ${stage.remaining}`,\n )\n }\n entering = stage.remaining\n }\n}\n\nexport interface AdmissionExecution {\n funnel: ExperimentFunnel\n survivors: EvidenceRecord[]\n /** Partition rows by partition id, reported separately and never pooled. */\n partitionRows: Record<string, EvidenceRecord[]>\n}\n\n/**\n * Run a sealed admission rule over evidence records. Each stage keeps the rows\n * its predicate accepts; partitions draw from the rows their source stage\n * dropped. The result embeds the funnel, so the denominator chain and the\n * surviving rows can never disagree.\n */\nexport function executeAdmissionRule(\n rule: AdmissionRule,\n records: readonly EvidenceRecord[],\n): AdmissionExecution {\n let current = [...records]\n const droppedAt = new Map<string, EvidenceRecord[]>()\n const stageInputs: FunnelStageInput[] = []\n for (const stage of rule.stages) {\n const kept: EvidenceRecord[] = []\n const dropped: EvidenceRecord[] = []\n for (const record of current) {\n if (evaluatePredicate(stage.keep, record)) kept.push(record)\n else dropped.push(record)\n }\n droppedAt.set(stage.id, dropped)\n stageInputs.push({\n id: stage.id,\n excluded: dropped.length,\n ...(stage.waives ? { waives: stage.waives } : {}),\n })\n current = kept\n }\n const partitionRows: Record<string, EvidenceRecord[]> = {}\n const partitionCounts: { id: string; from: string; count: number }[] = []\n for (const partition of rule.partitions ?? []) {\n const source = droppedAt.get(partition.from)\n if (!source) {\n throw new FunnelIntegrityError(\n `admission partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n const rows = source.filter((record) => evaluatePredicate(partition.keep, record))\n partitionRows[partition.id] = rows\n partitionCounts.push({ id: partition.id, from: partition.from, count: rows.length })\n }\n const funnel = buildFunnel({\n population: rule.population,\n input: records.length,\n stages: stageInputs,\n partitions: partitionCounts,\n })\n return { funnel, survivors: current, partitionRows }\n}\n\n/**\n * Chain two funnels whose boundary agrees: the second funnel's input must be\n * exactly the first funnel's survivors. Anything else is a gap or an\n * injection, and both are refused.\n */\nexport function composeFunnels(\n first: ExperimentFunnel,\n second: ExperimentFunnel,\n): ExperimentFunnel {\n if (second.input !== first.surviving) {\n throw new FunnelIntegrityError(\n `cannot compose funnels: '${first.population}' survives ${first.surviving} rows but '${second.population}' starts from ${second.input}`,\n )\n }\n return buildFunnel({\n population: first.population,\n input: first.input,\n stages: [...first.stages, ...second.stages].map((stage) => ({\n id: stage.id,\n excluded: stage.excluded,\n ...(stage.exclusions ? { exclusions: stage.exclusions } : {}),\n ...(stage.waives ? { waives: stage.waives } : {}),\n })),\n partitions: [...first.partitions, ...second.partitions].map((partition) => ({\n id: partition.id,\n from: partition.from,\n count: partition.count,\n })),\n })\n}\n\n/**\n * Text render of the chain. One row per stage; the reconciliation line at the\n * bottom restates `input = surviving + excluded` so a reader can check the\n * arithmetic without a tool.\n */\nexport function renderFunnelTable(funnel: ExperimentFunnel): string {\n const rows = funnel.stages.map((stage) => [\n stage.id + (stage.waives?.length ? ` (waives: ${stage.waives.join(', ')})` : ''),\n String(stage.entering),\n String(stage.excluded),\n String(stage.remaining),\n ])\n const header = ['stage', 'entering', 'excluded', 'remaining']\n const widths = header.map((h, col) => Math.max(h.length, ...rows.map((r) => r[col]!.length)))\n const line = (cells: string[]): string =>\n cells.map((cell, col) => cell.padEnd(widths[col]!)).join(' ')\n const out: string[] = [\n `population: ${funnel.population}`,\n `input: ${funnel.input}`,\n line(header),\n line(widths.map((w) => '-'.repeat(w))),\n ...rows.map((r) => line(r)),\n ]\n const excluded = funnel.stages.reduce((sum, stage) => sum + stage.excluded, 0)\n out.push(\n `surviving: ${funnel.surviving} (input ${funnel.input} = surviving ${funnel.surviving} + excluded ${excluded})`,\n )\n for (const partition of funnel.partitions) {\n out.push(\n `partition ${partition.id}: ${partition.count} rows from '${partition.from}' — reported separately, never pooled`,\n )\n }\n return out.join('\\n')\n}\n","/**\n * Define, seal, and execute experiments whose every rule is registered data.\n *\n * `defineExperiment` validates the cross-references inside a spec and freezes\n * it. `sealExperiment` canonicalizes and hashes the whole tree — arms, row\n * admission, selection, estimands, intervals, decision rule, gates, halt,\n * budget — into one digest that lands on every downstream artifact. Changing\n * what is decided requires a new digest: an amendment is a re-seal with a\n * reason and blindness attestations, and the digest history is the audit\n * trail.\n *\n * `openSealedExperiment` is the only execution surface. It verifies the seal\n * and returns executors bound to the sealed spec; none of them takes a\n * parameter for alpha, threshold, metric, or stopping rule, so\n * registered-vs-ran drift is unrepresentable rather than checked.\n */\n\nimport { ValidationError } from '../errors'\nimport { hashCanonical } from '../ledger-core/canonical'\nimport {\n type AdmissionRule,\n type BudgetRule,\n type ComputedInterval,\n type Condition,\n computeEstimand,\n computeInterval,\n type DecisionOutcome,\n type DecisionRule,\n type DerivedQuantities,\n type Estimand,\n type EstimandResult,\n type EvidenceRecord,\n evaluateHaltRule,\n evaluateIdentityGate,\n evaluateOracleDeterminismGate,\n evaluatePopulationReproducibilityGate,\n evaluatePowerFloorGate,\n evaluateProvenanceGate,\n executeDecisionRule,\n type GateResult,\n type HaltOutcome,\n type HaltRule,\n type IntervalSpec,\n intervalSpecProblems,\n type JsonValue,\n type MatchedBudgetRule,\n type NLadderProjection,\n type Obligation,\n powerFloorProblems,\n projectNLadderBudget,\n type ReissuePolicy,\n runSelectionRule,\n runUniformPassBudget,\n type SelectionRule,\n type UniformPassSchedule,\n type ValidityGate,\n} from './ast'\nimport { type ArmRealizedBudget, type MatchedBudgetVerdict, verifyMatchedBudgets } from './budget'\nimport {\n defineEvaluationClaim,\n type EvaluationClaim,\n type EvaluationUnitSummary,\n summarizeEvaluationUnits,\n} from './claim'\nimport { type AdmissionExecution, executeAdmissionRule } from './funnel'\n\n/** A sealed experiment whose digest no longer matches its spec. */\nexport class SealIntegrityError extends ValidationError {}\n\n// ── Spec ─────────────────────────────────────────────────────────────\n\nexport interface ArmSpec {\n id: string\n role: 'treatment' | 'control'\n /** Digest of the AgentProfile the arm runs under. */\n profileDigest?: string\n /** Digest of the pinned execution policy the arm runs under. */\n policyDigest?: string\n /** Registered arm pins (model, seed, step budget, ...) as data. */\n pins?: Record<string, JsonValue>\n}\n\nexport type OutcomeSpec =\n | {\n kind: 'binary'\n /** Where the pass verdict comes from, e.g. 'injected-suite'. */\n source?: string\n digestVerified?: boolean\n /** What counts as a pass, e.g. 'exit-0' or 'reward-file-contains-1'. */\n pass?: string\n /** Errored rollouts stay in the denominator; dropping them is unregistered. */\n droppedRollouts?: 'forbidden'\n }\n | {\n kind: 'bounded-score'\n min: number\n max: number\n orientation: 'higher-is-better' | 'lower-is-better'\n }\n\n/**\n * Per-rollout seed derivation as a closed source list. `arm` is not in the\n * union, so arm-dependent seeding is unrepresentable.\n */\nexport interface SeedDerivation {\n from: ('seed' | 'rowId' | 'rolloutIndex')[]\n}\n\nexport interface ExperimentSpec {\n id: string\n /** Population and independent observation unit for the intended use of this result. */\n claim?: EvaluationClaim\n /** Human prose for the audit trail — never executable. */\n hypothesis?: string\n arms: ArmSpec[]\n outcome: OutcomeSpec\n admission?: AdmissionRule\n /** Named deterministic subset rules. */\n selections?: Record<string, SelectionRule>\n /**\n * Selection OUTPUTS pinned into the seal. A filter-of base resolves here, so\n * reusing an earlier draw is registered and a re-draw is a new digest.\n */\n sealedSubsets?: Record<string, string[]>\n estimands?: Record<string, Estimand>\n intervals?: Record<string, IntervalSpec>\n decision: DecisionRule\n obligations?: Obligation[]\n /** Named pre-spend validity gates; the halt rule references these names. */\n gates?: Record<string, ValidityGate>\n halt?: HaltRule\n budget?: BudgetRule\n matchedBudget?: MatchedBudgetRule\n reissue?: ReissuePolicy\n seedDerivation?: SeedDerivation\n seed?: number\n}\n\n// ── Validation ───────────────────────────────────────────────────────\n\nfunction conditionRefs(condition: Condition): {\n intervals: string[]\n quantities: string[]\n obligations: string[]\n} {\n switch (condition.kind) {\n case 'interval-excludes-zero':\n case 'interval-includes-zero':\n return { intervals: [condition.interval], quantities: [], obligations: [] }\n case 'quantity-threshold':\n return { intervals: [], quantities: [condition.quantity], obligations: [] }\n case 'obligation-met':\n return { intervals: [], quantities: [], obligations: [condition.obligation] }\n case 'all':\n case 'any': {\n const nested = condition.of.map(conditionRefs)\n return {\n intervals: nested.flatMap((r) => r.intervals),\n quantities: nested.flatMap((r) => r.quantities),\n obligations: nested.flatMap((r) => r.obligations),\n }\n }\n case 'not':\n return conditionRefs(condition.of)\n }\n}\n\n/**\n * Validate every cross-reference inside a spec and freeze it.\n *\n * A decision condition may only read a registered interval, a registered\n * estimand, or a registered obligation; a halt rule may only reference\n * registered gates; a filter-of base must resolve to a registered selection\n * or sealed subset. Anything else is refused here, before sealing.\n */\nexport function defineExperiment(spec: ExperimentSpec): ExperimentSpec {\n const problems: string[] = []\n const claim = spec.claim === undefined ? undefined : defineEvaluationClaim(spec.claim)\n if (!spec.id || spec.id.trim().length === 0) problems.push('id is empty')\n if (spec.arms.length === 0) problems.push('at least one arm is required')\n const armIds = new Set<string>()\n for (const arm of spec.arms) {\n if (armIds.has(arm.id)) problems.push(`duplicate arm id '${arm.id}'`)\n armIds.add(arm.id)\n }\n if (!spec.arms.some((arm) => arm.role === 'treatment')) {\n problems.push('at least one arm must have role treatment')\n }\n\n const intervalNames = new Set(Object.keys(spec.intervals ?? {}))\n const estimandNames = new Set(Object.keys(spec.estimands ?? {}))\n const obligationIds = new Set((spec.obligations ?? []).map((o) => o.id))\n const gateNames = new Set(Object.keys(spec.gates ?? {}))\n const selectionNames = new Set(Object.keys(spec.selections ?? {}))\n const sealedSubsetNames = new Set(Object.keys(spec.sealedSubsets ?? {}))\n\n for (const [name, interval] of Object.entries(spec.intervals ?? {})) {\n problems.push(\n ...intervalSpecProblems(interval).map((problem) => `interval '${name}': ${problem}`),\n )\n }\n\n for (const [name, gate] of Object.entries(spec.gates ?? {})) {\n if (gate.kind !== 'power-floor') continue\n problems.push(...powerFloorProblems(gate).map((problem) => `gate '${name}': ${problem}`))\n if (claim?.minimumEffect !== undefined && gate.minimumEffect !== claim.minimumEffect) {\n problems.push(`gate '${name}' minimumEffect differs from the evaluation claim`)\n }\n }\n if (claim?.generalization === 'new-units') {\n for (const [name, interval] of Object.entries(spec.intervals ?? {})) {\n if (interval?.kind === 'cluster-bootstrap' && interval.clusterBy !== claim.independentUnit) {\n problems.push(\n `interval '${name}' must resample '${claim.independentUnit}' from the evaluation claim`,\n )\n }\n }\n }\n\n const checkCondition = (condition: Condition, where: string): void => {\n const refs = conditionRefs(condition)\n for (const name of refs.intervals) {\n if (!intervalNames.has(name)) problems.push(`${where} reads unregistered interval '${name}'`)\n }\n for (const name of refs.quantities) {\n if (!estimandNames.has(name)) problems.push(`${where} reads unregistered quantity '${name}'`)\n }\n for (const name of refs.obligations) {\n if (!obligationIds.has(name))\n problems.push(`${where} reads unregistered obligation '${name}'`)\n }\n }\n\n if (spec.decision.kind === 'table') {\n if (spec.decision.branches.length === 0) problems.push('decision table has no branches')\n spec.decision.branches.forEach((branch, index) => {\n checkCondition(branch.when, `decision branch ${index} ('${branch.verdict}')`)\n })\n } else {\n for (const name of spec.decision.estimands) {\n if (!estimandNames.has(name)) {\n problems.push(`report-only decision names unregistered estimand '${name}'`)\n }\n }\n for (const name of spec.decision.intervals) {\n if (!intervalNames.has(name)) {\n problems.push(`report-only decision names unregistered interval '${name}'`)\n }\n }\n }\n\n if (spec.decision.kind === 'table' && spec.obligations) {\n const verdicts = new Set(spec.decision.branches.map((b) => b.verdict))\n for (const obligation of spec.obligations) {\n for (const verdict of obligation.appliesToVerdicts) {\n if (!verdicts.has(verdict)) {\n problems.push(\n `obligation '${obligation.id}' applies to verdict '${verdict}' which no branch produces`,\n )\n }\n }\n }\n }\n\n if (spec.halt) {\n for (const gate of spec.halt.when.gates) {\n if (!gateNames.has(gate)) problems.push(`halt rule references unregistered gate '${gate}'`)\n }\n }\n\n for (const [name, selection] of Object.entries(spec.selections ?? {})) {\n if (selection.kind === 'filter-of') {\n if (!selectionNames.has(selection.base) && !sealedSubsetNames.has(selection.base)) {\n problems.push(\n `selection '${name}' filters unregistered base '${selection.base}' (not a selection or sealed subset)`,\n )\n }\n }\n }\n\n if (spec.admission) {\n const stageIds = new Set<string>()\n for (const stage of spec.admission.stages) {\n if (stageIds.has(stage.id)) problems.push(`duplicate admission stage id '${stage.id}'`)\n stageIds.add(stage.id)\n }\n for (const partition of spec.admission.partitions ?? []) {\n if (!stageIds.has(partition.from)) {\n problems.push(\n `admission partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n }\n }\n\n if (problems.length > 0) {\n throw new ValidationError(`defineExperiment('${spec.id}'): ${problems.join('; ')}`)\n }\n return deepFreeze(structuredClone({ ...spec, ...(claim ? { claim } : {}) }))\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value !== null && typeof value === 'object') {\n for (const key of Object.keys(value as object)) {\n deepFreeze((value as Record<string, unknown>)[key])\n }\n Object.freeze(value)\n }\n return value\n}\n\n// ── Seal ─────────────────────────────────────────────────────────────\n\nexport interface SealAmendment {\n /** ISO8601 timestamp of the re-seal. */\n at: string\n reason: string\n /** Blindness attestations: what was verifiably unseen when the amendment was made. */\n blind: string[]\n /** Digest of the spec after this amendment. */\n digest: string\n}\n\n/** SHA-256 over the RFC 8785 canonical JSON encoding of the experiment. */\nexport type SealAlgo = 'sha256-rfc8785'\n\nexport interface SealedExperiment {\n spec: ExperimentSpec\n /** sha256 over the serialized spec, under the scheme `algo` names. */\n digest: string\n /** Required digest scheme. Unsupported or missing schemes cannot execute. */\n algo: SealAlgo\n sealedAt: string\n /** Digest of the original registration, before any amendment. */\n initialDigest: string\n amendments: SealAmendment[]\n}\n\n/** Validate, canonicalize, and hash a spec into its registration. */\nexport async function sealExperiment(\n spec: ExperimentSpec,\n options: { sealedAt?: string } = {},\n): Promise<SealedExperiment> {\n const validated = defineExperiment(spec)\n const digest = specDigest(validated)\n return {\n spec: validated,\n digest,\n algo: 'sha256-rfc8785',\n sealedAt: options.sealedAt ?? new Date().toISOString(),\n initialDigest: digest,\n amendments: [],\n }\n}\n\n/**\n * Amend a sealed experiment. The current seal is verified first, the new spec\n * is validated and re-hashed, and the amendment appends to the digest chain.\n * There is no way to change what is decided without producing a new digest.\n */\nexport async function amendExperiment(\n sealed: SealedExperiment,\n amendment: { spec: ExperimentSpec; reason: string; blind: string[]; at?: string },\n): Promise<SealedExperiment> {\n const captured = structuredClone(sealed)\n const requested = structuredClone(amendment)\n await assertSealIntact(captured)\n const validated = defineExperiment(requested.spec)\n const digest = specDigest(validated)\n return {\n spec: validated,\n digest,\n algo: 'sha256-rfc8785',\n sealedAt: captured.sealedAt,\n initialDigest: captured.initialDigest,\n amendments: [\n ...captured.amendments,\n {\n at: requested.at ?? new Date().toISOString(),\n reason: requested.reason,\n blind: [...requested.blind],\n digest,\n },\n ],\n }\n}\n\n/** True when the supported seal matches its canonical spec. */\nexport async function verifySealedExperiment(sealed: SealedExperiment): Promise<boolean> {\n if (sealed.algo !== 'sha256-rfc8785') return false\n try {\n return specDigest(sealed.spec) === sealed.digest\n } catch {\n return false\n }\n}\n\nfunction specDigest(spec: ExperimentSpec): string {\n return hashCanonical(spec).slice('sha256:'.length)\n}\n\nasync function assertSealIntact(sealed: SealedExperiment): Promise<void> {\n if (!(await verifySealedExperiment(sealed))) {\n throw new SealIntegrityError(\n `sealed experiment '${sealed.spec.id}' has an unsupported digest scheme or its digest does not match its canonical spec`,\n )\n }\n}\n\n// ── Sealed execution ─────────────────────────────────────────────────\n\n/** Evidence a gate executor consumes, discriminated to match the gate kind. */\nexport type GateEvidence =\n | { kind: 'oracle-determinism'; repsByState: Record<string, readonly boolean[]> }\n | {\n kind: 'population-reproducibility'\n left: readonly EvidenceRecord[]\n right: readonly EvidenceRecord[]\n }\n | { kind: 'provenance-assertion'; provenance: EvidenceRecord }\n | { kind: 'identity'; pinned: string; served: string }\n | { kind: 'power-floor'; curve: readonly { effect: number; power: number }[] }\n\n/**\n * Executors bound to one verified seal. Every method reads its rule from the\n * sealed spec; evidence is the only argument anywhere.\n */\nexport interface RegisteredExperiment {\n readonly sealed: SealedExperiment\n /** Count independent units separately from repeated observations under the sealed claim. */\n units(records: readonly EvidenceRecord[]): EvaluationUnitSummary\n /** Execute the registered decision rule on derived quantities. */\n decide(evidence: DerivedQuantities): DecisionOutcome\n /** Run the registered admission funnel over evidence rows. */\n admit(records: readonly EvidenceRecord[]): AdmissionExecution\n /** Run a registered selection rule. Filter-of bases resolve to sealed subsets. */\n select(name: string, records: readonly EvidenceRecord[], options: { idField: string }): string[]\n /** Evaluate a registered validity gate on evidence of the matching kind. */\n gate(name: string, evidence: GateEvidence): GateResult\n /** Evaluate the registered halt rule over gate results. */\n halt(gates: readonly GateResult[]): HaltOutcome\n /** Execute the registered uniform-pass budget schedule. */\n runUniformPassBudget(measuredPassCosts: readonly number[]): UniformPassSchedule\n /** Project the registered n-ladder budget. */\n projectNLadderBudget(measured: { unitCostUsd: number; rows: number }): NLadderProjection\n /** Verify realized arm budgets under the registered matched-budget rule. */\n matchedBudgets(arms: readonly ArmRealizedBudget[]): MatchedBudgetVerdict\n /** Compute a registered estimand over evidence rows. */\n estimate(name: string, rows: readonly EvidenceRecord[]): EstimandResult\n /** Compute a registered interval spec. */\n interval(\n name: string,\n evidence:\n | { kind: 'rows'; rows: readonly EvidenceRecord[] }\n | { kind: 'binomial'; successes: number; trials: number; unitIds?: readonly string[] },\n ): ComputedInterval & { units?: EvaluationUnitSummary }\n}\n\n/**\n * Verify the seal and return executors bound to it. This is the module's only\n * execution surface: a rule that is not in the sealed spec cannot run, and a\n * rule that is cannot run differently.\n */\nexport async function openSealedExperiment(\n sealed: SealedExperiment,\n): Promise<RegisteredExperiment> {\n const captured = structuredClone(sealed)\n await assertSealIntact(captured)\n const spec = defineExperiment(captured.spec)\n const frozenSeal = deepFreeze({ ...captured, spec })\n const need = <T>(value: T | undefined, what: string): T => {\n if (value === undefined) {\n throw new ValidationError(`experiment '${spec.id}' registered no ${what}`)\n }\n return value\n }\n return {\n sealed: frozenSeal,\n units: (records) => summarizeEvaluationUnits(need(spec.claim, 'evaluation claim'), records),\n decide: (evidence) => executeDecisionRule(spec.decision, evidence),\n admit: (records) => executeAdmissionRule(need(spec.admission, 'admission rule'), records),\n select: (name, records, options) => {\n const rule = need(spec.selections?.[name], `selection '${name}'`)\n return runSelectionRule(rule, records, {\n idField: options.idField,\n bases: spec.sealedSubsets,\n })\n },\n gate: (name, evidence) => {\n const gate = need(spec.gates?.[name], `gate '${name}'`)\n if (gate.kind !== evidence.kind) {\n throw new ValidationError(\n `gate '${name}' is registered as ${gate.kind} but received ${evidence.kind} evidence`,\n )\n }\n switch (gate.kind) {\n case 'oracle-determinism':\n return evaluateOracleDeterminismGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'oracle-determinism' }>).repsByState,\n )\n case 'population-reproducibility': {\n const populations = evidence as Extract<\n GateEvidence,\n { kind: 'population-reproducibility' }\n >\n return evaluatePopulationReproducibilityGate(name, gate, populations)\n }\n case 'provenance-assertion':\n return evaluateProvenanceGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'provenance-assertion' }>).provenance,\n )\n case 'identity':\n return evaluateIdentityGate(\n name,\n gate,\n evidence as Extract<GateEvidence, { kind: 'identity' }>,\n )\n case 'power-floor':\n return evaluatePowerFloorGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'power-floor' }>).curve,\n )\n }\n },\n halt: (gates) => evaluateHaltRule(need(spec.halt, 'halt rule'), gates),\n runUniformPassBudget: (measuredPassCosts) => {\n const budget = need(spec.budget, 'budget rule')\n if (budget.kind !== 'uniform-pass') {\n throw new ValidationError(\n `experiment '${spec.id}' registered a ${budget.kind} budget, not uniform-pass`,\n )\n }\n return runUniformPassBudget(budget, measuredPassCosts)\n },\n projectNLadderBudget: (measured) => {\n const budget = need(spec.budget, 'budget rule')\n if (budget.kind !== 'n-ladder') {\n throw new ValidationError(\n `experiment '${spec.id}' registered a ${budget.kind} budget, not n-ladder`,\n )\n }\n return projectNLadderBudget(budget, measured)\n },\n matchedBudgets: (arms) =>\n verifyMatchedBudgets(need(spec.matchedBudget, 'matched-budget rule'), arms),\n estimate: (name, rows) =>\n computeEstimand(need(spec.estimands?.[name], `estimand '${name}'`), rows),\n interval: (name, evidence) => {\n const interval = need(spec.intervals?.[name], `interval '${name}'`)\n const claim = spec.claim\n let units: EvaluationUnitSummary | undefined\n if (claim && evidence.kind === 'rows') {\n units = summarizeEvaluationUnits(claim, evidence.rows)\n } else if (claim?.generalization === 'new-units' && evidence.kind === 'binomial') {\n if (\n evidence.unitIds === undefined ||\n evidence.unitIds.length !== evidence.trials ||\n new Set(evidence.unitIds).size !== evidence.trials ||\n evidence.unitIds.some((id) => typeof id !== 'string' || !id.trim() || id.trim() !== id)\n ) {\n throw new ValidationError(\n 'claimed binomial interval needs one unique unitId per independent trial',\n )\n }\n units = {\n observations: evidence.trials,\n independentUnits: evidence.trials,\n units: evidence.unitIds.map((id) => ({ id, observations: 1 })),\n }\n }\n return { ...computeInterval(interval, evidence), ...(units ? { units } : {}) }\n },\n }\n}\n","/**\n * The evidence registry record — the canonical, machine-readable unit for a\n * measured claim about an agent, a prompt, a policy, or an instrument.\n *\n * One record answers, in typed fields, the questions a scattered results doc\n * leaves to prose: what was claimed, what instrument measured it, the exact\n * command that reproduces it, which arms ran, the denominator, what it cost,\n * what confounds the comparison, and how much trust the evidence has earned.\n *\n * Records live as JSON files in `evidence/records/` at the repo root — one\n * file per claim, filename `<id>.json`. The registry lives in agent-eval\n * because the measurement substrate owns evidence legitimacy; every other\n * repo keeps at most a pointer file. `scripts/render-evidence-index.ts`\n * generates the human index from these records, so prose can never drift\n * from data, and `pnpm run evidence:check` (part of `verify:package`) fails\n * on an invalid record or a stale index.\n *\n * The shape extends the `.evolve/experiments.jsonl` session-log vocabulary\n * (ts/hypothesis/change/result/evidence) into a curated registry record.\n * Session logs stay append-only diaries; a registry record is the durable,\n * addressable claim distilled from them.\n */\n\nimport { z } from 'zod'\n\n/**\n * Trust ladder for a recorded claim, strongest first.\n *\n * - `CERTIFIED` — pre-registered rule, sealed or held-out data, and either a\n * defended challenge or a check that re-runs in the suite.\n * - `MEASURED-ONCE` — one honest measurement on the real path, not replicated.\n * - `RESOLVED-NULL` — measured with an adequate instrument; the effect did not\n * appear under the registered rule. A null is a result, not a failure.\n * - `UNVERIFIED` — stated somewhere load-bearing, but no independent check has\n * run. Admitting this state is what keeps folklore out of the other four.\n * - `KILLED` — refuted, invalidated, or superseded by a stronger record.\n */\nexport const EVIDENCE_STATES = [\n 'CERTIFIED',\n 'MEASURED-ONCE',\n 'RESOLVED-NULL',\n 'UNVERIFIED',\n 'KILLED',\n] as const\n\nexport type EvidenceState = (typeof EVIDENCE_STATES)[number]\n\nconst idPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nconst datePattern = /^\\d{4}-\\d{2}-\\d{2}$/\nconst sha256Pattern = /^[0-9a-f]{64}$/\n\n/** Denominator of the measurement. A claim without an `n` is prose, not evidence. */\nconst evidenceDenominatorSchema = z.strictObject({\n value: z.number().positive().finite(),\n /** What one unit is: rows, cases, rollouts, records, leaves… */\n unit: z.string().min(1),\n /** Clustering, reps, split names — whatever the bare number hides. */\n detail: z.string().min(1).optional(),\n})\n\nexport type EvidenceDenominator = z.infer<typeof evidenceDenominatorSchema>\n\nexport const evidenceRegistryRecordSchema = z.strictObject({\n /** Stable kebab-case identity; the registry filename is `<id>.json`. */\n id: z.string().regex(idPattern),\n /** Date the decisive measurement completed, `YYYY-MM-DD`. */\n date: z.string().regex(datePattern),\n /** The one-sentence load-bearing claim, stated so it can fail. */\n claim: z.string().min(1),\n /** Domain the claim lives in: trace-repair, multishot, analyst, vertical-bench… */\n domain: z.string().min(1),\n /** The instrument that produced the number — script, harness, oracle, judge. */\n instrument: z.string().min(1),\n /**\n * The exact invocation that reproduces the measurement.\n * `null` means the invocation was not preserved — a named gap, never a guess.\n */\n command: z.string().min(1).nullable(),\n /** Compared arms. Empty for a single-arm measurement. */\n arms: z.array(z.string().min(1)),\n n: evidenceDenominatorSchema,\n /** The measured numbers, with uncertainty when it exists. Numbers, not adjectives. */\n result: z.string().min(1),\n evidenceState: z.enum(EVIDENCE_STATES),\n /** Where the raw data lives: repo paths, PR/gist URLs, run directories. Never empty. */\n artifacts: z.array(z.string().min(1)).min(1),\n /**\n * Measured spend in USD. `0` is a true zero (deterministic, no paid calls);\n * `null` means spend was not captured — a named gap, never a silent zero.\n */\n costUsd: z.number().nonnegative().nullable(),\n /** Every known asymmetry or threat to validity. Empty only when none is known. */\n confounds: z.array(z.string().min(1)),\n /** Repo whose work produced the evidence (the registry itself lives here). */\n sourceRepo: z.string().min(1),\n /** Seal digest of the registered experiment (`./experiment`), when one governed the run. */\n experimentDigest: z.string().regex(sha256Pattern).optional(),\n /** Ids of records this one supersedes. */\n supersedes: z.array(z.string().regex(idPattern)).optional(),\n notes: z.string().min(1).optional(),\n})\n\nexport type EvidenceRegistryRecord = z.infer<typeof evidenceRegistryRecordSchema>\n\n/** Parse one record; throws with the zod issue list on any violation. */\nexport function parseEvidenceRegistryRecord(raw: unknown): EvidenceRegistryRecord {\n return evidenceRegistryRecordSchema.parse(raw)\n}\n\nclass EvidenceRegistryError extends Error {}\n\n/**\n * Validate a set of records as one registry: every record parses, ids are\n * unique, and every `supersedes` target exists. Returns records sorted in\n * the registry's canonical order (trust ladder, then date desc, then id).\n */\nexport function validateEvidenceRegistry(raws: readonly unknown[]): EvidenceRegistryRecord[] {\n const records = raws.map((raw) => parseEvidenceRegistryRecord(raw))\n const seen = new Set<string>()\n for (const record of records) {\n if (seen.has(record.id)) {\n throw new EvidenceRegistryError(`duplicate evidence record id: ${record.id}`)\n }\n seen.add(record.id)\n }\n for (const record of records) {\n for (const target of record.supersedes ?? []) {\n if (!seen.has(target)) {\n throw new EvidenceRegistryError(`record ${record.id} supersedes unknown record: ${target}`)\n }\n }\n }\n const stateRank = new Map(EVIDENCE_STATES.map((state, index) => [state, index]))\n return [...records].sort((a, b) => {\n const byState = (stateRank.get(a.evidenceState) ?? 0) - (stateRank.get(b.evidenceState) ?? 0)\n if (byState !== 0) return byState\n if (a.date !== b.date) return a.date < b.date ? 1 : -1\n return a.id < b.id ? -1 : 1\n })\n}\n\nfunction mdEscape(text: string): string {\n return text.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ')\n}\n\nfunction formatCost(costUsd: number | null): string {\n if (costUsd === null) return 'not captured'\n return `$${costUsd.toFixed(2)}`\n}\n\nfunction formatN(n: EvidenceDenominator): string {\n const base = `${n.value} ${n.unit}`\n return n.detail ? `${base} (${n.detail})` : base\n}\n\n/**\n * Render the registry's human index from records. Deterministic: identical\n * records always produce identical output, so a byte diff against the\n * committed index is the freshness check. No clocks, no environment.\n */\nexport function renderEvidenceIndex(raws: readonly unknown[]): string {\n const records = validateEvidenceRegistry(raws)\n const lines: string[] = [\n '# Evidence index',\n '',\n '<!-- GENERATED by scripts/render-evidence-index.ts from evidence/records/*.json.',\n ' Edit the records, run `pnpm run evidence:render`, and commit both.',\n ' `pnpm run evidence:check` (inside verify:package) fails when this file drifts. -->',\n '',\n `${records.length} records. States: ${EVIDENCE_STATES.join(' > ')}.`,\n '',\n '| state | date | id | claim | result |',\n '| --- | --- | --- | --- | --- |',\n ]\n for (const r of records) {\n lines.push(\n `| ${r.evidenceState} | ${r.date} | [\\`${r.id}\\`](#${r.id}) | ${mdEscape(r.claim)} | ${mdEscape(r.result)} |`,\n )\n }\n for (const r of records) {\n lines.push('', `## ${r.id}`, '')\n lines.push(`**${r.evidenceState}** · ${r.date} · ${r.domain} · source repo \\`${r.sourceRepo}\\``)\n lines.push('', `**Claim.** ${r.claim}`, '', `**Result.** ${r.result}`, '')\n lines.push(`- **Instrument**: ${r.instrument}`)\n lines.push(`- **Command**: ${r.command === null ? 'not preserved' : `\\`${r.command}\\``}`)\n lines.push(`- **Arms**: ${r.arms.length === 0 ? 'single-arm' : r.arms.join(' vs ')}`)\n lines.push(`- **n**: ${formatN(r.n)}`)\n lines.push(`- **Cost**: ${formatCost(r.costUsd)}`)\n if (r.experimentDigest) lines.push(`- **Experiment seal**: \\`${r.experimentDigest}\\``)\n lines.push(`- **Artifacts**:`)\n for (const artifact of r.artifacts) lines.push(` - ${artifact}`)\n if (r.confounds.length === 0) {\n lines.push('- **Confounds**: none recorded')\n } else {\n lines.push('- **Confounds**:')\n for (const confound of r.confounds) lines.push(` - ${confound}`)\n }\n if (r.supersedes && r.supersedes.length > 0) {\n lines.push(`- **Supersedes**: ${r.supersedes.map((s) => `\\`${s}\\``).join(', ')}`)\n }\n if (r.notes) lines.push(`- **Notes**: ${r.notes}`)\n }\n lines.push('')\n return lines.join('\\n')\n}\n","/**\n * Design-time power for task-clustered paired designs, with a refusal verdict.\n *\n * The failure this prevents (measured): a pre-registered kill test fixed a\n * task-clustered bootstrap over 14 rows in 4 task clusters. Simulated at the\n * registered seed, the design's power topped out at 0.69 — at a per-row\n * effect of 1.0. \"Four clusters cannot certify any effect size, including\n * 1.0\" was learned by running the experiment; this module computes it before\n * a dollar is spent.\n *\n * Two floors, one simulation:\n * - Closed form, zero spend: with C independent clusters the exact\n * whole-cluster sign-flip test can never produce a two-sided p below\n * 2^(1-C). C=4 gives 0.125; C=3 gives 0.25 — both above a 0.05 alpha, so\n * those designs are refused at ANY effect size, before simulation.\n * - Seeded simulation: per-row paired contrasts drawn under a registered\n * effect model, a whole-cluster percentile bootstrap on each trial, power =\n * the fraction of trials whose interval excludes zero.\n *\n * The refusal is a verdict INSIDE the returned artifact (the powerPreflight\n * shape, made cluster-aware); `assertDesignAdequate` turns it into a throw for\n * callers that want configuration-time failure.\n */\n\nimport { ValidationError } from '../errors'\nimport { mulberry32 } from '../statistics'\n\n/** A design refused at configuration time, before any spend. */\nexport class DesignRefusalError extends ValidationError {}\n\nexport interface ClusteredPowerOptions {\n /** Rows per independent cluster, e.g. [6, 3, 3, 2]. */\n clusterSizes: number[]\n /** P(win) − P(loss) in signal clusters; noisy clusters retain zero expected contrast. */\n effects: number[]\n /** Minimum worthwhile effect under the declared outcome model; must occur in effects. */\n minimumEffect: number\n /** Deterministic seed for outcome draws and bootstrap resampling. */\n seed: number\n /** Simulated experiments per effect. Default 2000. */\n trials?: number\n /** Whole-cluster bootstrap draws per trial. Default 4000. */\n resamples?: number\n /** Percentile interval level. Default 0.95. */\n confidence?: number\n /** Sign-flip alpha the closed-form floor is checked against. Default 0.05. */\n alpha?: number\n /** Power required at minimumEffect. Default 0.8. */\n targetPower?: number\n /** P(row favors treatment) under the zero-effect model. Must equal baseLossRate. Default 0.10. */\n baseWinRate?: number\n /** P(row favors control) under the zero-effect model. Must equal baseWinRate. Default 0.10. */\n baseLossRate?: number\n /**\n * Clusters whose rows carry outcome noise instead of signal: each row wins\n * with `flipRate` and loses with `flipRate`, independent of the effect.\n * Index into `clusterSizes`.\n */\n noisyClusters?: { index: number; flipRate: number }[]\n}\n\nexport interface ClusteredPowerPoint {\n effect: number\n power: number\n medianCiWidth: number\n}\n\nexport interface SignFlipFloor {\n /** Smallest achievable two-sided p: 2^(1-C) for C clusters. */\n twoSidedP: number\n /** Smallest achievable one-sided p: 2^-C. */\n oneSidedP: number\n alpha: number\n /** False when the cluster count can never certify at `alpha`, at any effect. */\n certifiableAtAlpha: boolean\n /** Smallest cluster count whose two-sided floor is at or under `alpha`. */\n minClustersForAlpha: number\n}\n\nexport interface ClusteredPowerRefusal {\n verdict: 'underpowered'\n reasons: string[]\n recommendation: string\n}\n\nexport interface ClusteredPowerResult {\n clusterCount: number\n totalRows: number\n trials: number\n resamples: number\n seed: number\n confidence: number\n targetPower: number\n minimumEffect: number\n powerAtMinimumEffect: number\n curve: ClusteredPowerPoint[]\n /** Maximum simulated power across the effect grid. */\n maxPower: number\n signFlipFloor: SignFlipFloor\n /** True when the sign-flip floor certifies and power at minimumEffect reaches target. */\n adequate: boolean\n /** Populated exactly when `adequate` is false. The refusal lives in the artifact. */\n refusal: ClusteredPowerRefusal | null\n}\n\n/**\n * Simulate the power of a whole-cluster percentile-bootstrap design and refuse\n * a structure that cannot reach target power at the declared minimum effect.\n */\nexport function clusteredPower(options: ClusteredPowerOptions): ClusteredPowerResult {\n const clusterSizes = options.clusterSizes\n if (clusterSizes.length === 0 || clusterSizes.some((n) => !Number.isInteger(n) || n <= 0)) {\n throw new ValidationError(\n `clusteredPower: clusterSizes must be positive integers, got [${clusterSizes.join(', ')}]`,\n )\n }\n if (options.effects.length === 0) {\n throw new ValidationError('clusteredPower: effects grid is empty')\n }\n if (\n options.effects.some((effect) => !Number.isFinite(effect) || effect < 0 || effect > 1) ||\n new Set(options.effects).size !== options.effects.length\n ) {\n throw new ValidationError('clusteredPower: effects must be unique finite values in [0,1]')\n }\n if (\n !Number.isFinite(options.minimumEffect) ||\n options.minimumEffect <= 0 ||\n options.minimumEffect > 1\n ) {\n throw new ValidationError('clusteredPower: minimumEffect must be in (0,1]')\n }\n if (!options.effects.includes(options.minimumEffect)) {\n throw new ValidationError(\n 'clusteredPower: effects must contain minimumEffect exactly; no interpolation is assumed',\n )\n }\n if (!Number.isInteger(options.seed)) {\n throw new ValidationError(`clusteredPower: seed must be an integer, got ${options.seed}`)\n }\n const trials = options.trials ?? 2000\n const resamples = options.resamples ?? 4000\n if (!Number.isInteger(trials) || trials <= 0 || !Number.isInteger(resamples) || resamples <= 0) {\n throw new ValidationError(\n `clusteredPower: trials and resamples must be positive integers, got ${trials}/${resamples}`,\n )\n }\n const confidence = options.confidence ?? 0.95\n if (!Number.isFinite(confidence) || confidence <= 0 || confidence >= 1) {\n throw new ValidationError(`clusteredPower: confidence must be in (0,1), got ${confidence}`)\n }\n const alpha = options.alpha ?? 0.05\n const targetPower = options.targetPower ?? 0.8\n if (!Number.isFinite(alpha) || alpha <= 0 || alpha >= 1) {\n throw new ValidationError('clusteredPower: alpha must be in (0,1)')\n }\n if (!Number.isFinite(targetPower) || targetPower <= 0 || targetPower > 1) {\n throw new ValidationError('clusteredPower: targetPower must be in (0,1]')\n }\n const baseWinRate = options.baseWinRate ?? 0.1\n const baseLossRate = options.baseLossRate ?? 0.1\n if (\n !Number.isFinite(baseWinRate) ||\n !Number.isFinite(baseLossRate) ||\n baseWinRate < 0 ||\n baseLossRate < 0 ||\n baseWinRate + baseLossRate > 1\n ) {\n throw new ValidationError(\n 'clusteredPower: base win/loss rates must be nonnegative and sum to at most 1',\n )\n }\n if (baseWinRate !== baseLossRate) {\n throw new ValidationError(\n 'clusteredPower: the zero-effect model requires equal baseWinRate and baseLossRate',\n )\n }\n const noisy = new Map<number, number>()\n for (const cluster of options.noisyClusters ?? []) {\n if (\n !Number.isInteger(cluster.index) ||\n cluster.index < 0 ||\n cluster.index >= clusterSizes.length\n ) {\n throw new ValidationError(\n `clusteredPower: noisy cluster index ${cluster.index} outside [0,${clusterSizes.length - 1}]`,\n )\n }\n if (\n noisy.has(cluster.index) ||\n !Number.isFinite(cluster.flipRate) ||\n cluster.flipRate < 0 ||\n cluster.flipRate > 1\n ) {\n throw new ValidationError(\n 'clusteredPower: noisy clusters need unique indices and flipRate in [0,1]',\n )\n }\n noisy.set(cluster.index, cluster.flipRate)\n }\n\n const clusterCount = clusterSizes.length\n const totalRows = clusterSizes.reduce((a, b) => a + b, 0)\n const signFlipFloor = computeSignFlipFloor(clusterCount, alpha)\n\n const curve: ClusteredPowerPoint[] = []\n for (const effect of options.effects) {\n curve.push(\n simulateEffect(effect, {\n clusterSizes,\n seed: options.seed,\n trials,\n resamples,\n confidence,\n baseWinRate,\n baseLossRate,\n noisy,\n }),\n )\n }\n const maxPower = Math.max(...curve.map((point) => point.power))\n const powerAtMinimumEffect = curve.find((point) => point.effect === options.minimumEffect)!.power\n\n const reasons: string[] = []\n if (!signFlipFloor.certifiableAtAlpha) {\n reasons.push(\n `${clusterCount} clusters cannot certify any effect size, including 1.0: the exact ` +\n `whole-cluster sign-flip test's smallest two-sided p is 2^(1-${clusterCount}) = ` +\n `${signFlipFloor.twoSidedP} > alpha ${alpha}; at least ` +\n `${signFlipFloor.minClustersForAlpha} clusters are needed`,\n )\n }\n if (powerAtMinimumEffect < targetPower) {\n reasons.push(\n `simulated power ${powerAtMinimumEffect.toFixed(3)} at minimum worthwhile effect ` +\n `${options.minimumEffect} is below target ${targetPower}; maximum grid power ` +\n `${maxPower.toFixed(3)} does not establish adequacy at that effect`,\n )\n }\n const adequate = reasons.length === 0\n return {\n clusterCount,\n totalRows,\n trials,\n resamples,\n seed: options.seed,\n confidence,\n targetPower,\n minimumEffect: options.minimumEffect,\n powerAtMinimumEffect,\n curve,\n maxPower,\n signFlipFloor,\n adequate,\n refusal: adequate\n ? null\n : {\n verdict: 'underpowered',\n reasons,\n recommendation:\n `Do not spend on this structure. Add independent clusters (>= ` +\n `${Math.max(signFlipFloor.minClustersForAlpha, clusterCount)}) or register a design ` +\n `whose simulated power reaches ${targetPower} at effect ${options.minimumEffect}, ` +\n `then re-run clusteredPower.`,\n },\n }\n}\n\n/** Throw the refusal for callers that want configuration-time failure. */\nexport function assertDesignAdequate(result: ClusteredPowerResult): void {\n if (result.refusal) {\n throw new DesignRefusalError(\n `design refused (underpowered): ${result.refusal.reasons.join('; ')}`,\n )\n }\n}\n\nfunction computeSignFlipFloor(clusterCount: number, alpha: number): SignFlipFloor {\n const twoSidedP = 2 ** (1 - clusterCount)\n const oneSidedP = 2 ** -clusterCount\n let minClusters = 1\n while (2 ** (1 - minClusters) > alpha) minClusters += 1\n return {\n twoSidedP,\n oneSidedP,\n alpha,\n certifiableAtAlpha: twoSidedP <= alpha,\n minClustersForAlpha: minClusters,\n }\n}\n\ninterface SimulationConfig {\n clusterSizes: number[]\n seed: number\n trials: number\n resamples: number\n confidence: number\n baseWinRate: number\n baseLossRate: number\n noisy: Map<number, number>\n}\n\n/**\n * One effect point. Loss probability is min(baseLoss, (1-effect)/2) and\n * win probability is loss probability plus effect. Their difference equals\n * effect, including near the probability boundary. Noisy clusters draw win\n * and loss independently at their\n * flip rate. Each trial computes a whole-cluster percentile bootstrap of the\n * pooled row mean; the trial counts toward power when the interval excludes\n * zero.\n */\nfunction simulateEffect(effect: number, config: SimulationConfig): ClusteredPowerPoint {\n const rng = mulberry32(mixSeed(config.seed, effect))\n const clusterCount = config.clusterSizes.length\n let excludes = 0\n const widths = new Array<number>(config.trials)\n const sums = new Array<number>(clusterCount)\n const means = new Array<number>(config.resamples)\n for (let trial = 0; trial < config.trials; trial++) {\n for (let cluster = 0; cluster < clusterCount; cluster++) {\n const size = config.clusterSizes[cluster]!\n const flipRate = config.noisy.get(cluster)\n let sum = 0\n for (let row = 0; row < size; row++) {\n if (flipRate !== undefined) {\n const win = rng() < flipRate ? 1 : 0\n const loss = rng() < flipRate ? 1 : 0\n sum += win - loss\n } else {\n const lossRate = Math.min(config.baseLossRate, (1 - effect) / 2)\n const winRate = lossRate + effect\n const u = rng()\n sum += u < winRate ? 1 : u < winRate + lossRate ? -1 : 0\n }\n }\n sums[cluster] = sum\n }\n for (let draw = 0; draw < config.resamples; draw++) {\n let pooledSum = 0\n let pooledRows = 0\n for (let pick = 0; pick < clusterCount; pick++) {\n const index = Math.floor(rng() * clusterCount)\n pooledSum += sums[index]!\n pooledRows += config.clusterSizes[index]!\n }\n means[draw] = pooledSum / pooledRows\n }\n means.sort((a, b) => a - b)\n const tail = 1 - config.confidence\n const lower = means[Math.floor((tail / 2) * config.resamples)]!\n const upper =\n means[\n Math.max(\n Math.floor((tail / 2) * config.resamples),\n Math.min(config.resamples - 1, Math.ceil((1 - tail / 2) * config.resamples) - 1),\n )\n ]!\n widths[trial] = upper - lower\n if (lower > 0 || upper < 0) excludes += 1\n }\n widths.sort((a, b) => a - b)\n return {\n effect,\n power: excludes / config.trials,\n medianCiWidth: widths[Math.floor(config.trials / 2)]!,\n }\n}\n\n/** Fold the effect into the seed so every grid point draws an independent stream. */\nfunction mixSeed(seed: number, effect: number): number {\n const scaled = Math.round(effect * 1_000_003)\n return ((seed ^ (scaled * 0x9e3779b9)) >>> 0) | 0\n}\n","import { ValidationError } from '../errors'\nimport type {\n CanaryAssignmentReceipt,\n CanaryObservation,\n SealedRandomizedCanaryRule,\n} from './randomized-canary'\n\n/** Host-ledger assignment written when an eligible request is routed. */\nexport interface ProspectiveCanaryAssignment extends CanaryAssignmentReceipt {\n sourceUnitId: string\n assignedAt: string\n}\n\n/** Independent checker result, including a null when the outcome is unavailable. */\nexport interface ProspectiveCanaryOutcome {\n assignmentId: string\n outcomeSourceId: string\n checkedOutcome: 0 | 1 | null\n outcomeCheckerDigest: string\n checkedAt: string\n}\n\n/** Served trace, or an independent receipt that the assigned unit never executed. */\nexport interface ProspectiveCanaryExecution {\n assignmentId: string\n traceSourceId: string | null\n noExecutionSourceId: string | null\n servedProfileDigest: string | null\n servedCodeRevisionDigest: string | null\n turns: number | null\n providerCallIds: readonly string[]\n recordedAt: string\n}\n\n/** Billing authority's settled snapshot for every provider call in one assignment. */\nexport interface ProspectiveCanaryBilling {\n assignmentId: string\n billingSourceId: string\n settlement: 'settled' | 'unknown'\n billedCostUsd: number | null\n providerCallIds: readonly string[]\n recordedAt: string\n}\n\nexport interface ProspectiveCanaryJoinInput {\n /** An opt-in host flag. Calling this function never routes product traffic. */\n enabled?: boolean\n sealed: SealedRandomizedCanaryRule\n /** The host must independently verify this witness predates every assignment. */\n protocolWitnessedAt: string\n /** The complete prior-source roster must be attested by the host verifier. */\n historicalSourceUnitIds: readonly string[]\n assignments: readonly ProspectiveCanaryAssignment[]\n outcomes: readonly ProspectiveCanaryOutcome[]\n executions: readonly ProspectiveCanaryExecution[]\n billing: readonly ProspectiveCanaryBilling[]\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {\n throw new ValidationError(`prospective canary: ${label} must be a nonempty trimmed string`)\n }\n}\n\nfunction utc(value: unknown, label: string): number {\n nonEmpty(value, label)\n const parsed = Date.parse(value)\n const canonical = Number.isFinite(parsed) ? new Date(parsed).toISOString() : ''\n if (\n !value.endsWith('Z') ||\n !Number.isFinite(parsed) ||\n (value !== canonical && value !== canonical.replace('.000Z', 'Z'))\n ) {\n throw new ValidationError(`prospective canary: ${label} must be a canonical UTC timestamp`)\n }\n return parsed\n}\n\nfunction indexRows<T extends { assignmentId: string }>(\n rows: readonly T[],\n label: string,\n assignments: ReadonlySet<string>,\n): Map<string, T> {\n const indexed = new Map<string, T>()\n for (const row of rows) {\n nonEmpty(row.assignmentId, `${label} assignmentId`)\n if (!assignments.has(row.assignmentId)) {\n throw new ValidationError(`prospective canary: orphan ${label} for '${row.assignmentId}'`)\n }\n if (indexed.has(row.assignmentId)) {\n throw new ValidationError(`prospective canary: duplicate ${label} for '${row.assignmentId}'`)\n }\n indexed.set(row.assignmentId, row)\n }\n return indexed\n}\n\nfunction uniqueIds(ids: readonly string[], label: string): string[] {\n if (!Array.isArray(ids)) {\n throw new ValidationError(`prospective canary: ${label} must be an array`)\n }\n const seen = new Set<string>()\n for (const id of ids) {\n nonEmpty(id, label)\n if (seen.has(id)) throw new ValidationError(`prospective canary: duplicate ${label} '${id}'`)\n seen.add(id)\n }\n return [...seen].sort()\n}\n\n/**\n * Join independently sourced served receipts without inventing missing costs.\n * The host still verifies ledger completeness, source authority, isolation,\n * randomization and the pre-traffic witness in `decideRandomizedCanary`.\n */\nexport function joinProspectiveCanaryReceipts(\n input: ProspectiveCanaryJoinInput,\n): CanaryObservation[] {\n if (input.enabled !== true) {\n throw new ValidationError('prospective canary: pilot is disabled')\n }\n const witnessedAt = utc(input.protocolWitnessedAt, 'protocolWitnessedAt')\n const cutoff = utc(input.sealed.rule.analysisCutoff, 'analysisCutoff')\n if (witnessedAt >= cutoff) {\n throw new ValidationError('prospective canary: protocol witness must precede cutoff')\n }\n if (!Array.isArray(input.assignments) || input.assignments.length === 0) {\n throw new ValidationError('prospective canary: assignment ledger is empty')\n }\n const historical = new Set(uniqueIds(input.historicalSourceUnitIds, 'historical source unit'))\n const assignmentIds = new Set<string>()\n const assignmentSources = new Set<string>()\n const sourceUnits = new Set<string>()\n for (const row of input.assignments) {\n nonEmpty(row.assignmentId, 'assignmentId')\n nonEmpty(row.assignmentSourceId, 'assignmentSourceId')\n nonEmpty(row.clusterId, 'clusterId')\n nonEmpty(row.sourceUnitId, 'sourceUnitId')\n if (row.arm !== 'control' && row.arm !== 'candidate') {\n throw new ValidationError('prospective canary: assignment arm is invalid')\n }\n if (assignmentIds.has(row.assignmentId) || assignmentSources.has(row.assignmentSourceId)) {\n throw new ValidationError('prospective canary: duplicate assignment identity')\n }\n if (sourceUnits.has(row.sourceUnitId) || historical.has(row.sourceUnitId)) {\n throw new ValidationError(`prospective canary: source unit '${row.sourceUnitId}' is reused`)\n }\n const assignedAt = utc(row.assignedAt, `assignment '${row.assignmentId}' assignedAt`)\n if (assignedAt <= witnessedAt || assignedAt > cutoff) {\n throw new ValidationError('prospective canary: assignment falls outside witnessed window')\n }\n assignmentIds.add(row.assignmentId)\n assignmentSources.add(row.assignmentSourceId)\n sourceUnits.add(row.sourceUnitId)\n }\n const outcomes = indexRows(input.outcomes, 'outcome', assignmentIds)\n const executions = indexRows(input.executions, 'execution', assignmentIds)\n const billing = indexRows(input.billing, 'billing', assignmentIds)\n const sourceIds = new Set(assignmentSources)\n const claimSource = (id: string, label: string) => {\n nonEmpty(id, label)\n if (sourceIds.has(id)) {\n throw new ValidationError(`prospective canary: reused independent source '${id}'`)\n }\n sourceIds.add(id)\n }\n\n return input.assignments.map((assignment) => {\n const outcome = outcomes.get(assignment.assignmentId)\n const execution = executions.get(assignment.assignmentId)\n const bill = billing.get(assignment.assignmentId)\n const assignedAt = Date.parse(assignment.assignedAt)\n if (outcome) {\n claimSource(outcome.outcomeSourceId, 'outcomeSourceId')\n nonEmpty(outcome.outcomeCheckerDigest, 'outcomeCheckerDigest')\n if (utc(outcome.checkedAt, 'checkedAt') < assignedAt) {\n throw new ValidationError('prospective canary: outcome precedes assignment')\n }\n if (![0, 1, null].includes(outcome.checkedOutcome)) {\n throw new ValidationError('prospective canary: checked outcome must be 0, 1 or null')\n }\n }\n if (execution) {\n if ((execution.traceSourceId === null) === (execution.noExecutionSourceId === null)) {\n throw new ValidationError(\n 'prospective canary: execution needs one trace or no-execution source',\n )\n }\n claimSource(execution.traceSourceId ?? execution.noExecutionSourceId!, 'execution source')\n if (utc(execution.recordedAt, 'execution recordedAt') < assignedAt) {\n throw new ValidationError('prospective canary: execution precedes assignment')\n }\n if (\n execution.turns !== null &&\n (!Number.isSafeInteger(execution.turns) || execution.turns < 0)\n ) {\n throw new ValidationError('prospective canary: turns must be a nonnegative integer')\n }\n if (\n execution.noExecutionSourceId !== null &&\n (execution.turns !== 0 || execution.providerCallIds.length !== 0)\n ) {\n throw new ValidationError(\n 'prospective canary: no-execution receipt contains turns or calls',\n )\n }\n }\n if (bill) {\n claimSource(bill.billingSourceId, 'billingSourceId')\n if (utc(bill.recordedAt, 'billing recordedAt') < assignedAt) {\n throw new ValidationError('prospective canary: billing precedes assignment')\n }\n if (bill.settlement === 'settled') {\n if (\n bill.billedCostUsd === null ||\n !Number.isFinite(bill.billedCostUsd) ||\n bill.billedCostUsd < 0\n ) {\n throw new ValidationError(\n 'prospective canary: settled billing needs nonnegative actual cost',\n )\n }\n } else if (bill.settlement !== 'unknown' || bill.billedCostUsd !== null) {\n throw new ValidationError('prospective canary: unknown billing cost must stay null')\n }\n if (\n execution &&\n uniqueIds(bill.providerCallIds, 'billing call').join('\\0') !==\n uniqueIds(execution.providerCallIds, 'execution call').join('\\0')\n ) {\n throw new ValidationError('prospective canary: provider-call billing join is incomplete')\n }\n }\n return {\n assignmentId: assignment.assignmentId,\n assignmentSourceId: assignment.assignmentSourceId,\n clusterId: assignment.clusterId,\n arm: assignment.arm,\n checkedOutcome: outcome?.checkedOutcome ?? null,\n outcomeSourceId: outcome?.outcomeSourceId ?? null,\n billedCostUsd: bill?.settlement === 'settled' ? bill.billedCostUsd : null,\n billingSourceId: bill?.billingSourceId ?? null,\n traceSourceId: execution?.traceSourceId ?? null,\n noExecutionSourceId: execution?.noExecutionSourceId ?? null,\n servedProfileDigest: execution?.servedProfileDigest ?? null,\n servedCodeRevisionDigest: execution?.servedCodeRevisionDigest ?? null,\n outcomeCheckerDigest: outcome?.outcomeCheckerDigest ?? null,\n turns: execution?.turns ?? null,\n }\n })\n}\n","/** Fixed-horizon, assignment-level decision for an unpaired served canary. */\n\nimport { ValidationError } from '../errors'\nimport { hashCanonical, LEDGER_HASH_PATTERN } from '../ledger-core/canonical'\nimport { studentTCdf, studentTQuantile } from '../math/student-t'\n\nexport type CanaryArm = 'control' | 'candidate'\n\n/** One assigned unit, including unsuccessful and unobserved executions. */\nexport interface CanaryAssignmentReceipt {\n assignmentId: string\n assignmentSourceId: string\n clusterId: string\n arm: CanaryArm\n}\n\nexport interface CanaryObservation extends CanaryAssignmentReceipt {\n /** Independently checked binary outcome. Null means measurement is unavailable. */\n checkedOutcome: 0 | 1 | null\n outcomeSourceId: string | null\n /** Billed cost, including measured zero. Null means billing is unavailable. */\n billedCostUsd: number | null\n billingSourceId: string | null\n /** Trace identity may be null for an assigned unit that never executed. */\n traceSourceId: string | null\n /** Required when no trace exists; identifies the independent no-execution record. */\n noExecutionSourceId: string | null\n /** Observed identities; null only when there was no execution or no checked outcome. */\n servedProfileDigest: string | null\n servedCodeRevisionDigest: string | null\n outcomeCheckerDigest: string | null\n turns: number | null\n}\n\n/** Seal this prospective protocol before the first eligible live assignment. */\nexport interface RandomizedCanaryRule {\n experimentId: string\n populationId: string\n eligibilityRuleDigest: string\n randomizationSourceId: string\n assignmentLedgerAuthorityId: string\n controlProfileDigest: string\n candidateProfileDigest: string\n servedCodeRevisionDigest: string\n outcomeCheckerDigest: string\n /** One externally reserved slot in a fixed family of confirmatory canaries. */\n confirmatoryFamilyId: string\n confirmatoryFamilySize: number\n confirmatoryIndex: number\n familyReservationSourceId: string\n assignmentUnit: 'customer' | 'session'\n /** Customer clustering also permits sessions of one customer in both arms. */\n clusterUnit: 'customer' | 'session'\n stoppingRule: 'fixed-time'\n /** No assignment after this UTC time enters the frozen cohort. */\n analysisCutoff: string\n /** Wait this long after cutoff for checked outcomes and billing to mature. */\n outcomeMaturityMs: number\n /** Candidate minus control success probability must exceed this margin. */\n minimumLift: number\n /** At least 40 total independent clusters and 20 represented in each arm. */\n minimumClusters: number\n}\n\n/** Post-cutoff evidence from the independently verified append-only assignment ledger. */\nexport interface CanaryCohortReceipt {\n protocolDigest: string\n assignmentRosterDigest: string\n assignmentCount: number\n assignmentLedgerSourceId: string\n assignmentLedgerTipDigest: string\n outcomeLedgerSourceId: string\n billingLedgerSourceId: string\n observationSnapshotDigest: string\n /** Exact preregistered cutoff + outcomeMaturityMs, not a selectable later look. */\n observationFrozenAt: string\n authorityId: string\n attestationSourceId: string\n closedAt: string\n attestedAt: string\n}\n\n/** Host verifies the independent witnesses and append-only ledger before inference. */\nexport type CanaryCohortVerifier = (\n receipt: CanaryCohortReceipt,\n protocol: SealedRandomizedCanaryRule,\n) =>\n | {\n verified: true\n authorityId: string\n protocolWitnessedBeforeTraffic: boolean\n familySlotReservedBeforeTraffic: boolean\n eligibilityAndDispositionVerified: boolean\n randomizationVerified: boolean\n rosterCompleteAtCutoff: boolean\n outcomeAndBillingSnapshotFrozen: boolean\n sourceJoinsVerified: boolean\n armIsolationVerified: boolean\n }\n | { verified: false; reason: string }\n\nexport interface SealedRandomizedCanaryRule {\n rule: RandomizedCanaryRule\n digest: string\n algo: 'sha256-rfc8785'\n}\n\nexport type CanaryRefusal =\n | 'missing-evidence'\n | 'missing-trace'\n | 'execution-drift'\n | 'insufficient-clusters'\n | 'dominant-cluster'\n | 'zero-variance'\n | null\n\nexport interface RandomizedCanaryDecision {\n registrationDigest: string\n cohortReceiptSourceId: string\n assignmentRosterDigest: string\n estimand: 'assignment-weighted-itt-risk-difference'\n method: 'cluster-robust-t'\n /** The fixed headline remains a nominal 95% interval. */\n confidence: 0.95\n /** Additional Bonferroni level: 1 - 0.05 / registered family size. */\n familyAdjustedConfidence: number\n assignments: number\n controlAssignments: number\n candidateAssignments: number\n clusters: number\n controlClusters: number\n candidateClusters: number\n coverage: Record<\n CanaryArm,\n {\n checkedOutcomes: number\n billedAssignments: number\n turnReceipts: number\n traceReceipts: number\n }\n >\n missingOutcomes: number\n missingBilling: number\n missingTurns: number\n missingTraces: number\n executionDrift: number\n controlSuccessRate: number | null\n candidateSuccessRate: number | null\n delta: number | null\n nominal95Interval: { low: number; high: number } | null\n headline95Pass: boolean\n familyAdjustedInterval: { low: number; high: number } | null\n familywisePass: boolean\n /** Two-sided zero-null p-value before the registered family correction. */\n unadjustedPValue: number | null\n controlBilledCostUsd: number | null\n candidateBilledCostUsd: number | null\n controlTurns: number | null\n candidateTurns: number | null\n refusal: CanaryRefusal\n /** Primary lift criterion only; product cost and latency gates remain external. */\n successCriterionMet: boolean\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {\n throw new ValidationError(`randomized canary: ${label} must be a nonempty trimmed string`)\n }\n}\n\nfunction validateAssignment(row: CanaryAssignmentReceipt, index: number): void {\n if (row === null || typeof row !== 'object' || Array.isArray(row)) {\n throw new ValidationError(`randomized canary: assignment ${index} must be an object`)\n }\n nonEmpty(row.assignmentId, `assignment ${index} id`)\n nonEmpty(row.assignmentSourceId, `assignment ${index} source id`)\n nonEmpty(row.clusterId, `assignment ${index} cluster id`)\n if (row.arm !== 'control' && row.arm !== 'candidate') {\n throw new ValidationError(\n `randomized canary: assignment ${index} arm must be control or candidate`,\n )\n }\n}\n\n/** Digest only assignment facts, so outcome and cost cannot change the roster. */\nexport function randomizedCanaryRosterDigest(rows: readonly CanaryAssignmentReceipt[]): string {\n const seen = new Set<string>()\n const seenSources = new Set<string>()\n const roster = rows.map((row, index) => {\n validateAssignment(row, index)\n if (seen.has(row.assignmentId)) {\n throw new ValidationError(`randomized canary: duplicate assignment id '${row.assignmentId}'`)\n }\n seen.add(row.assignmentId)\n if (seenSources.has(row.assignmentSourceId)) {\n throw new ValidationError(\n `randomized canary: duplicate assignment source id '${row.assignmentSourceId}'`,\n )\n }\n seenSources.add(row.assignmentSourceId)\n return {\n assignmentId: row.assignmentId,\n assignmentSourceId: row.assignmentSourceId,\n clusterId: row.clusterId,\n arm: row.arm,\n }\n })\n roster.sort((a, b) =>\n a.assignmentId < b.assignmentId ? -1 : a.assignmentId > b.assignmentId ? 1 : 0,\n )\n return hashCanonical(roster)\n}\n\n/** Commit to the one complete checked-outcome, trace, turn, and billing snapshot. */\nexport function randomizedCanaryObservationDigest(rows: readonly CanaryObservation[]): string {\n // The roster validation also prevents duplicate assignment IDs.\n randomizedCanaryRosterDigest(rows)\n const snapshot = rows.map((row) => ({\n assignmentId: row.assignmentId,\n checkedOutcome: row.checkedOutcome,\n outcomeSourceId: row.outcomeSourceId,\n billedCostUsd: row.billedCostUsd,\n billingSourceId: row.billingSourceId,\n traceSourceId: row.traceSourceId,\n noExecutionSourceId: row.noExecutionSourceId,\n servedProfileDigest: row.servedProfileDigest,\n servedCodeRevisionDigest: row.servedCodeRevisionDigest,\n outcomeCheckerDigest: row.outcomeCheckerDigest,\n turns: row.turns,\n }))\n snapshot.sort((a, b) =>\n a.assignmentId < b.assignmentId ? -1 : a.assignmentId > b.assignmentId ? 1 : 0,\n )\n return hashCanonical(snapshot)\n}\n\nfunction validateRule(rule: RandomizedCanaryRule): void {\n for (const field of [\n 'experimentId',\n 'populationId',\n 'eligibilityRuleDigest',\n 'randomizationSourceId',\n 'assignmentLedgerAuthorityId',\n 'controlProfileDigest',\n 'candidateProfileDigest',\n 'servedCodeRevisionDigest',\n 'outcomeCheckerDigest',\n 'confirmatoryFamilyId',\n 'familyReservationSourceId',\n 'analysisCutoff',\n ] as const)\n nonEmpty(rule[field], field)\n if (\n !Number.isSafeInteger(rule.confirmatoryFamilySize) ||\n rule.confirmatoryFamilySize < 1 ||\n rule.confirmatoryFamilySize > 1000\n ) {\n throw new ValidationError('randomized canary: confirmatoryFamilySize must be in [1, 1000]')\n }\n if (\n !Number.isSafeInteger(rule.confirmatoryIndex) ||\n rule.confirmatoryIndex < 1 ||\n rule.confirmatoryIndex > rule.confirmatoryFamilySize\n ) {\n throw new ValidationError(\n 'randomized canary: confirmatoryIndex must name a reserved family slot',\n )\n }\n if (rule.assignmentUnit !== 'customer' && rule.assignmentUnit !== 'session') {\n throw new ValidationError('randomized canary: assignmentUnit must be customer or session')\n }\n if (rule.clusterUnit !== 'customer' && rule.clusterUnit !== 'session') {\n throw new ValidationError('randomized canary: clusterUnit must be customer or session')\n }\n if (rule.assignmentUnit === 'customer' && rule.clusterUnit !== 'customer') {\n throw new ValidationError('randomized canary: customer assignments must cluster by customer')\n }\n if (rule.stoppingRule !== 'fixed-time') {\n throw new ValidationError('randomized canary: only fixed-time stopping is supported')\n }\n if (!Number.isFinite(Date.parse(rule.analysisCutoff)) || !rule.analysisCutoff.endsWith('Z')) {\n throw new ValidationError('randomized canary: analysisCutoff must be a UTC timestamp')\n }\n if (!Number.isSafeInteger(rule.outcomeMaturityMs) || rule.outcomeMaturityMs < 0) {\n throw new ValidationError('randomized canary: outcomeMaturityMs must be a nonnegative integer')\n }\n if (!Number.isFinite(rule.minimumLift) || rule.minimumLift < 0 || rule.minimumLift >= 1) {\n throw new ValidationError('randomized canary: minimumLift must be in [0, 1)')\n }\n if (!Number.isSafeInteger(rule.minimumClusters) || rule.minimumClusters < 40) {\n throw new ValidationError('randomized canary: minimumClusters must be at least 40')\n }\n}\n\n/** Seal the fixed decision controls; retaining this digest alone cannot prove preregistration time. */\nexport function sealRandomizedCanaryRule(rule: RandomizedCanaryRule): SealedRandomizedCanaryRule {\n validateRule(rule)\n const captured = structuredClone(rule)\n return { rule: captured, digest: hashCanonical(captured), algo: 'sha256-rfc8785' }\n}\n\n/** Apply one registered analysis to the entire frozen assignment roster. */\nexport function decideRandomizedCanary(\n sealed: SealedRandomizedCanaryRule,\n cohort: CanaryCohortReceipt,\n rows: readonly CanaryObservation[],\n verifyCohort: CanaryCohortVerifier,\n): RandomizedCanaryDecision {\n if (sealed.algo !== 'sha256-rfc8785') {\n throw new ValidationError('randomized canary: unsupported registration digest scheme')\n }\n validateRule(sealed.rule)\n if (hashCanonical(sealed.rule) !== sealed.digest) {\n throw new ValidationError('randomized canary: registration digest mismatch')\n }\n if (cohort === null || typeof cohort !== 'object' || Array.isArray(cohort)) {\n throw new ValidationError('randomized canary: independent cohort receipt is required')\n }\n for (const field of [\n 'assignmentLedgerSourceId',\n 'outcomeLedgerSourceId',\n 'billingLedgerSourceId',\n 'authorityId',\n 'attestationSourceId',\n 'closedAt',\n 'observationFrozenAt',\n 'attestedAt',\n ] as const) {\n nonEmpty(cohort[field], `cohort ${field}`)\n }\n if (cohort.protocolDigest !== sealed.digest) {\n throw new ValidationError('randomized canary: cohort protocol digest mismatch')\n }\n if (cohort.authorityId !== sealed.rule.assignmentLedgerAuthorityId) {\n throw new ValidationError('randomized canary: cohort authority differs from registered ledger')\n }\n for (const field of [\n 'assignmentRosterDigest',\n 'assignmentLedgerTipDigest',\n 'observationSnapshotDigest',\n ] as const) {\n if (!LEDGER_HASH_PATTERN.test(cohort[field])) {\n throw new ValidationError(`randomized canary: cohort ${field} must be a sha256 digest`)\n }\n }\n if (\n !Number.isSafeInteger(cohort.assignmentCount) ||\n cohort.assignmentCount < 1 ||\n rows.length !== cohort.assignmentCount\n ) {\n throw new ValidationError(\n 'randomized canary: assignment count differs from complete ledger receipt',\n )\n }\n if (randomizedCanaryRosterDigest(rows) !== cohort.assignmentRosterDigest) {\n throw new ValidationError('randomized canary: assignment roster digest mismatch')\n }\n if (randomizedCanaryObservationDigest(rows) !== cohort.observationSnapshotDigest) {\n throw new ValidationError('randomized canary: frozen observation snapshot digest mismatch')\n }\n const cutoff = Date.parse(sealed.rule.analysisCutoff)\n const closedAt = Date.parse(cohort.closedAt)\n const frozenAt = Date.parse(cohort.observationFrozenAt)\n const attestedAt = Date.parse(cohort.attestedAt)\n const expectedFreezeAt = cutoff + sealed.rule.outcomeMaturityMs\n if (\n !Number.isFinite(closedAt) ||\n closedAt < cutoff ||\n !cohort.closedAt.endsWith('Z') ||\n !Number.isFinite(frozenAt) ||\n frozenAt !== expectedFreezeAt ||\n closedAt > frozenAt ||\n !cohort.observationFrozenAt.endsWith('Z') ||\n !Number.isFinite(attestedAt) ||\n attestedAt < frozenAt ||\n !cohort.attestedAt.endsWith('Z')\n ) {\n throw new ValidationError(\n 'randomized canary: ledger closure or frozen observation time differs from registered cutoffs',\n )\n }\n if (typeof verifyCohort !== 'function') {\n throw new ValidationError('randomized canary: independent cohort verifier is required')\n }\n const verification = verifyCohort(cohort, sealed)\n if (\n verification?.verified !== true ||\n verification.authorityId !== cohort.authorityId ||\n verification.protocolWitnessedBeforeTraffic !== true ||\n verification.familySlotReservedBeforeTraffic !== true ||\n verification.eligibilityAndDispositionVerified !== true ||\n verification.randomizationVerified !== true ||\n verification.rosterCompleteAtCutoff !== true ||\n verification.outcomeAndBillingSnapshotFrozen !== true ||\n verification.sourceJoinsVerified !== true ||\n verification.armIsolationVerified !== true\n ) {\n throw new ValidationError(\n `randomized canary: cohort attestation or completeness unverified${verification?.verified === false ? `: ${verification.reason}` : ''}`,\n )\n }\n\n const clusters = new Map<string, CanaryObservation[]>()\n const arms = { control: [] as CanaryObservation[], candidate: [] as CanaryObservation[] }\n let missingOutcomes = 0\n let missingBilling = 0\n let missingTurns = 0\n let missingTraces = 0\n let executionDrift = 0\n for (const [index, row] of rows.entries()) {\n if (row.checkedOutcome !== 0 && row.checkedOutcome !== 1 && row.checkedOutcome !== null) {\n throw new ValidationError(\n `randomized canary: assignment ${index} outcome must be 0, 1, or null`,\n )\n }\n if (row.checkedOutcome === null) missingOutcomes++\n if (row.outcomeSourceId === null) {\n if (row.checkedOutcome !== null)\n throw new ValidationError(\n `randomized canary: assignment ${index} has an outcome without its source`,\n )\n } else nonEmpty(row.outcomeSourceId, `assignment ${index} outcome source id`)\n if (row.billedCostUsd === null) missingBilling++\n else if (!Number.isFinite(row.billedCostUsd) || row.billedCostUsd < 0) {\n throw new ValidationError(\n `randomized canary: assignment ${index} billed cost must be nonnegative`,\n )\n }\n if (row.billingSourceId === null) {\n if (row.billedCostUsd !== null)\n throw new ValidationError(\n `randomized canary: assignment ${index} has billed cost without its source`,\n )\n } else nonEmpty(row.billingSourceId, `assignment ${index} billing source id`)\n if (row.turns === null) missingTurns++\n else if (!Number.isSafeInteger(row.turns) || row.turns < 0) {\n throw new ValidationError(\n `randomized canary: assignment ${index} turns must be a nonnegative integer`,\n )\n }\n if (row.traceSourceId !== null)\n nonEmpty(row.traceSourceId, `assignment ${index} trace source id`)\n if (row.noExecutionSourceId !== null)\n nonEmpty(row.noExecutionSourceId, `assignment ${index} no-execution source id`)\n if (row.traceSourceId !== null && row.noExecutionSourceId !== null) {\n throw new ValidationError(\n `randomized canary: assignment ${index} has conflicting trace and no-execution receipts`,\n )\n }\n const noExecution =\n row.noExecutionSourceId !== null &&\n row.turns === 0 &&\n row.billedCostUsd === 0 &&\n row.checkedOutcome === 0\n if (row.traceSourceId === null && !noExecution) missingTraces++\n for (const field of [\n 'servedProfileDigest',\n 'servedCodeRevisionDigest',\n 'outcomeCheckerDigest',\n ] as const) {\n if (row[field] !== null) nonEmpty(row[field], `assignment ${index} ${field}`)\n }\n const expectedProfile =\n row.arm === 'control' ? sealed.rule.controlProfileDigest : sealed.rule.candidateProfileDigest\n if (\n (row.traceSourceId !== null &&\n (row.servedProfileDigest !== expectedProfile ||\n row.servedCodeRevisionDigest !== sealed.rule.servedCodeRevisionDigest)) ||\n (row.checkedOutcome !== null &&\n row.outcomeCheckerDigest !== sealed.rule.outcomeCheckerDigest) ||\n (noExecution && (row.servedProfileDigest !== null || row.servedCodeRevisionDigest !== null))\n ) {\n executionDrift++\n }\n arms[row.arm].push(row)\n const bucket = clusters.get(row.clusterId) ?? []\n bucket.push(row)\n clusters.set(row.clusterId, bucket)\n }\n const controlClusters = [...clusters.values()].filter((bucket) =>\n bucket.some((r) => r.arm === 'control'),\n ).length\n const candidateClusters = [...clusters.values()].filter((bucket) =>\n bucket.some((r) => r.arm === 'candidate'),\n ).length\n if (sealed.rule.assignmentUnit === sealed.rule.clusterUnit) {\n for (const [clusterId, bucket] of clusters) {\n if (bucket.length !== 1) {\n throw new ValidationError(\n `randomized canary: ${sealed.rule.assignmentUnit} cluster '${clusterId}' has multiple assignments`,\n )\n }\n }\n }\n const coverage = (arm: CanaryArm) => ({\n checkedOutcomes: arms[arm].filter((row) => row.checkedOutcome !== null).length,\n billedAssignments: arms[arm].filter((row) => row.billedCostUsd !== null).length,\n turnReceipts: arms[arm].filter((row) => row.turns !== null).length,\n traceReceipts: arms[arm].filter((row) => row.traceSourceId !== null).length,\n })\n const armCoverage = { control: coverage('control'), candidate: coverage('candidate') }\n const sum = (arm: CanaryArm, field: 'checkedOutcome' | 'billedCostUsd' | 'turns'): number =>\n arms[arm].reduce((total, row) => total + (row[field] ?? 0), 0)\n const n0 = arms.control.length\n const n1 = arms.candidate.length\n const outcomesComplete = missingOutcomes === 0 && n0 > 0 && n1 > 0\n const p0 = outcomesComplete ? sum('control', 'checkedOutcome') / n0 : null\n const p1 = outcomesComplete ? sum('candidate', 'checkedOutcome') / n1 : null\n const delta = p0 === null || p1 === null ? null : p1 - p0\n const result: RandomizedCanaryDecision = {\n registrationDigest: sealed.digest,\n cohortReceiptSourceId: cohort.attestationSourceId,\n assignmentRosterDigest: cohort.assignmentRosterDigest,\n estimand: 'assignment-weighted-itt-risk-difference',\n method: 'cluster-robust-t',\n confidence: 0.95,\n familyAdjustedConfidence: 1 - 0.05 / sealed.rule.confirmatoryFamilySize,\n assignments: rows.length,\n controlAssignments: n0,\n candidateAssignments: n1,\n clusters: clusters.size,\n controlClusters,\n candidateClusters,\n coverage: armCoverage,\n missingOutcomes,\n missingBilling,\n missingTurns,\n missingTraces,\n executionDrift,\n controlSuccessRate: p0,\n candidateSuccessRate: p1,\n delta,\n nominal95Interval: null,\n headline95Pass: false,\n familyAdjustedInterval: null,\n familywisePass: false,\n unadjustedPValue: null,\n controlBilledCostUsd:\n armCoverage.control.billedAssignments === n0 ? sum('control', 'billedCostUsd') : null,\n candidateBilledCostUsd:\n armCoverage.candidate.billedAssignments === n1 ? sum('candidate', 'billedCostUsd') : null,\n controlTurns: armCoverage.control.turnReceipts === n0 ? sum('control', 'turns') : null,\n candidateTurns: armCoverage.candidate.turnReceipts === n1 ? sum('candidate', 'turns') : null,\n refusal: null,\n successCriterionMet: false,\n }\n if (missingOutcomes > 0 || missingBilling > 0 || missingTurns > 0 || n0 === 0 || n1 === 0) {\n result.refusal = 'missing-evidence'\n return result\n }\n if (missingTraces > 0) {\n result.refusal = 'missing-trace'\n return result\n }\n if (executionDrift > 0) {\n result.refusal = 'execution-drift'\n return result\n }\n if (\n clusters.size < sealed.rule.minimumClusters ||\n controlClusters < 20 ||\n candidateClusters < 20\n ) {\n result.refusal = 'insufficient-clusters'\n return result\n }\n // A single customer may own many assigned sessions. One dominant customer\n // defeats the many-independent-clusters approximation even when G is large.\n for (const bucket of clusters.values()) {\n if (\n bucket.filter((r) => r.arm === 'control').length / n0 > 0.1 ||\n bucket.filter((r) => r.arm === 'candidate').length / n1 > 0.1\n ) {\n result.refusal = 'dominant-cluster'\n return result\n }\n }\n // OLS risk difference with customer/session cluster sandwich scores. A\n // cluster may contain both arms; its covariance contribution stays intact.\n const scores = [...clusters.values()].map((bucket) =>\n bucket.reduce(\n (score, row) =>\n score +\n (row.arm === 'candidate'\n ? (row.checkedOutcome! - p1!) / n1\n : -(row.checkedOutcome! - p0!) / n0),\n 0,\n ),\n )\n const G = clusters.size\n const variance =\n (((G / (G - 1)) * (rows.length - 1)) / (rows.length - 2)) *\n scores.reduce((total, score) => total + score * score, 0)\n if (!Number.isFinite(variance) || variance <= 0) {\n result.refusal = 'zero-variance'\n return result\n }\n const se = Math.sqrt(variance)\n const t = delta! / se\n const critical95 = studentTQuantile(0.975, G - 1)\n const familyCritical = studentTQuantile(1 - (1 - result.familyAdjustedConfidence) / 2, G - 1)\n result.nominal95Interval = { low: delta! - critical95 * se, high: delta! + critical95 * se }\n result.familyAdjustedInterval = {\n low: delta! - familyCritical * se,\n high: delta! + familyCritical * se,\n }\n result.unadjustedPValue = Math.min(1, 2 * (1 - studentTCdf(Math.abs(t), G - 1)))\n result.headline95Pass = result.nominal95Interval.low > 0\n result.familywisePass = result.familyAdjustedInterval.low > sealed.rule.minimumLift\n result.successCriterionMet = result.headline95Pass && result.familywisePass\n return result\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["populations","nonEmpty"],"sources":["../../src/experiment/budget.ts","../../src/experiment/funnel.ts","../../src/experiment/define.ts","../../src/experiment/evidence-record.ts","../../src/experiment/power.ts","../../src/experiment/prospective-canary-join.ts","../../src/experiment/randomized-canary.ts"],"sourcesContent":["/**\n * Matched-budget verification between arms, as a refusal object.\n *\n * A paired contrast is only meaningful when both arms spent comparable\n * resources; \"realized prompt and completion tokens must agree within 5%\" is\n * a registered rule, so its verification returns a verdict artifact — the\n * refusal lives inside the result, never in prose beside it.\n */\n\nimport { CaptureIntegrityError } from '../errors'\nimport type { MatchedBudgetRule } from './ast'\n\n/** Arms whose realized budgets diverge past the registered tolerance. */\nexport class MatchedBudgetError extends CaptureIntegrityError {}\n\nexport interface ArmRealizedBudget {\n armId: string\n /** Realized prompt + completion tokens the arm actually consumed. */\n realizedTokens: number\n}\n\nexport interface MatchedBudgetVerdict {\n rule: MatchedBudgetRule\n arms: ArmRealizedBudget[]\n /** (max - min) / max over all arms; 0 when every arm spent nothing. */\n maxRelativeGap: number\n /** The two arms with the widest gap; null when fewer than two arms. */\n widestPair: [string, string] | null\n matched: boolean\n /** Populated exactly when `matched` is false. */\n refusal: null | { onFail: 'refuse-contrast'; reason: string }\n}\n\n/**\n * Compare realized per-arm spend under the registered tolerance. Requires at\n * least two arms — a single arm has nothing to match against. Negative or\n * non-finite token counts are refused as evidence corruption, not compared.\n */\nexport function verifyMatchedBudgets(\n rule: MatchedBudgetRule,\n arms: readonly ArmRealizedBudget[],\n): MatchedBudgetVerdict {\n if (arms.length < 2) {\n throw new MatchedBudgetError(\n `verifyMatchedBudgets: need >= 2 arms to match budgets, got ${arms.length}`,\n )\n }\n for (const arm of arms) {\n if (!Number.isFinite(arm.realizedTokens) || arm.realizedTokens < 0) {\n throw new MatchedBudgetError(\n `verifyMatchedBudgets: arm '${arm.armId}' has invalid realized tokens ${arm.realizedTokens}`,\n )\n }\n }\n const sorted = [...arms].sort((a, b) => a.realizedTokens - b.realizedTokens)\n const min = sorted[0]!\n const max = sorted[sorted.length - 1]!\n const maxRelativeGap =\n max.realizedTokens === 0 ? 0 : (max.realizedTokens - min.realizedTokens) / max.realizedTokens\n const matched = maxRelativeGap <= rule.tolerance\n return {\n rule,\n arms: [...arms],\n maxRelativeGap,\n widestPair: [min.armId, max.armId],\n matched,\n refusal: matched\n ? null\n : {\n onFail: rule.onFail,\n reason:\n `realized ${rule.measure} diverge ${(maxRelativeGap * 100).toFixed(1)}% between ` +\n `'${min.armId}' (${min.realizedTokens}) and '${max.armId}' (${max.realizedTokens}) — ` +\n `registered tolerance is ${(rule.tolerance * 100).toFixed(1)}%; the contrast is refused`,\n },\n }\n}\n\n/** Throw the refusal for callers that gate the contrast on it. */\nexport function assertMatchedBudgets(\n rule: MatchedBudgetRule,\n arms: readonly ArmRealizedBudget[],\n): MatchedBudgetVerdict {\n const verdict = verifyMatchedBudgets(rule, arms)\n if (verdict.refusal) throw new MatchedBudgetError(verdict.refusal.reason)\n return verdict\n}\n","/**\n * The denominator chain as a first-class object.\n *\n * A benchmark whose denominator is not auditable is not a benchmark. Every\n * stage names what entered, what it removed, and what survived, so\n * `input = surviving + sum(excluded)` reads off the table instead of being\n * trusted. A stage that gains rows is refused at construction — a funnel is\n * monotone by definition, and a non-monotone one is a broken denominator,\n * not a formatting choice.\n *\n * The object is its own JSON render; `renderFunnelTable` is the text render.\n * `executeAdmissionRule` produces one by running a sealed {@link AdmissionRule}\n * over evidence records.\n */\n\nimport { CaptureIntegrityError } from '../errors'\nimport { type AdmissionRule, type EvidenceRecord, evaluatePredicate } from './ast'\n\n/** A funnel stage gained rows, double-counted them, or failed to reconcile. */\nexport class FunnelIntegrityError extends CaptureIntegrityError {}\n\nexport interface FunnelStageCount {\n id: string\n entering: number\n excluded: number\n remaining: number\n /** Named exclusion reasons summing to `excluded`, when the stage has them. */\n exclusions?: Record<string, number>\n /** Substrate checks this stage deliberately does not apply. Registered, never implicit. */\n waives?: string[]\n}\n\nexport interface FunnelPartitionCount {\n id: string\n /** Stage whose excluded rows the partition draws from. */\n from: string\n count: number\n /** A partition is reported separately and never pooled into the survivors. */\n pooling: 'never'\n}\n\nexport interface ExperimentFunnel {\n population: string\n input: number\n stages: FunnelStageCount[]\n surviving: number\n partitions: FunnelPartitionCount[]\n}\n\nexport interface FunnelStageInput {\n id: string\n /** Rows this stage removed. */\n excluded: number\n exclusions?: Record<string, number>\n waives?: string[]\n}\n\n/**\n * Build a funnel from counts and refuse anything non-monotone.\n *\n * Refusals: a negative count, a stage that gains rows (excluded < 0 is the\n * only way to gain — `remaining = entering - excluded` by construction, so a\n * gain cannot be smuggled in through `remaining`), named exclusions that do\n * not sum to the stage total, and a partition drawing from an unknown stage\n * or exceeding what that stage excluded.\n */\nexport function buildFunnel(input: {\n population: string\n input: number\n stages: FunnelStageInput[]\n partitions?: { id: string; from: string; count: number }[]\n}): ExperimentFunnel {\n if (!Number.isInteger(input.input) || input.input < 0) {\n throw new FunnelIntegrityError(\n `funnel input must be a non-negative integer, got ${input.input}`,\n )\n }\n let entering = input.input\n const stages: FunnelStageCount[] = []\n for (const stage of input.stages) {\n if (!Number.isInteger(stage.excluded)) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' excluded count must be an integer, got ${stage.excluded}`,\n )\n }\n if (stage.excluded < 0) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' gains ${-stage.excluded} rows — a funnel stage can only remove rows`,\n )\n }\n if (stage.excluded > entering) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' excludes ${stage.excluded} rows but only ${entering} entered`,\n )\n }\n if (stage.exclusions) {\n const sum = Object.values(stage.exclusions).reduce((a, b) => a + b, 0)\n if (sum !== stage.excluded) {\n throw new FunnelIntegrityError(\n `funnel stage '${stage.id}' names exclusions summing to ${sum} but excludes ${stage.excluded}`,\n )\n }\n }\n const remaining = entering - stage.excluded\n stages.push({\n id: stage.id,\n entering,\n excluded: stage.excluded,\n remaining,\n ...(stage.exclusions ? { exclusions: { ...stage.exclusions } } : {}),\n ...(stage.waives ? { waives: [...stage.waives] } : {}),\n })\n entering = remaining\n }\n const byStage = new Map(stages.map((s) => [s.id, s]))\n const partitions: FunnelPartitionCount[] = (input.partitions ?? []).map((partition) => {\n const source = byStage.get(partition.from)\n if (!source) {\n throw new FunnelIntegrityError(\n `funnel partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n if (partition.count < 0 || partition.count > source.excluded) {\n throw new FunnelIntegrityError(\n `funnel partition '${partition.id}' counts ${partition.count} rows but stage '${partition.from}' excluded ${source.excluded}`,\n )\n }\n return { id: partition.id, from: partition.from, count: partition.count, pooling: 'never' }\n })\n const funnel: ExperimentFunnel = {\n population: input.population,\n input: input.input,\n stages,\n surviving: entering,\n partitions,\n }\n assertFunnelReconciles(funnel)\n return funnel\n}\n\n/** A chain that does not add up is a broken denominator, so this throws. */\nexport function assertFunnelReconciles(funnel: ExperimentFunnel): void {\n const excluded = funnel.stages.reduce((sum, stage) => sum + stage.excluded, 0)\n if (funnel.input !== funnel.surviving + excluded) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' does not reconcile: input ${funnel.input} != surviving ${funnel.surviving} + excluded ${excluded}`,\n )\n }\n let entering = funnel.input\n for (const stage of funnel.stages) {\n if (stage.entering !== entering || stage.remaining !== stage.entering - stage.excluded) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' stage '${stage.id}' does not chain: ` +\n `entering ${stage.entering} (expected ${entering}), remaining ${stage.remaining}`,\n )\n }\n if (stage.remaining > stage.entering) {\n throw new FunnelIntegrityError(\n `funnel '${funnel.population}' stage '${stage.id}' gains rows: ${stage.entering} -> ${stage.remaining}`,\n )\n }\n entering = stage.remaining\n }\n}\n\nexport interface AdmissionExecution {\n funnel: ExperimentFunnel\n survivors: EvidenceRecord[]\n /** Partition rows by partition id, reported separately and never pooled. */\n partitionRows: Record<string, EvidenceRecord[]>\n}\n\n/**\n * Run a sealed admission rule over evidence records. Each stage keeps the rows\n * its predicate accepts; partitions draw from the rows their source stage\n * dropped. The result embeds the funnel, so the denominator chain and the\n * surviving rows can never disagree.\n */\nexport function executeAdmissionRule(\n rule: AdmissionRule,\n records: readonly EvidenceRecord[],\n): AdmissionExecution {\n let current = [...records]\n const droppedAt = new Map<string, EvidenceRecord[]>()\n const stageInputs: FunnelStageInput[] = []\n for (const stage of rule.stages) {\n const kept: EvidenceRecord[] = []\n const dropped: EvidenceRecord[] = []\n for (const record of current) {\n if (evaluatePredicate(stage.keep, record)) kept.push(record)\n else dropped.push(record)\n }\n droppedAt.set(stage.id, dropped)\n stageInputs.push({\n id: stage.id,\n excluded: dropped.length,\n ...(stage.waives ? { waives: stage.waives } : {}),\n })\n current = kept\n }\n const partitionRows: Record<string, EvidenceRecord[]> = {}\n const partitionCounts: { id: string; from: string; count: number }[] = []\n for (const partition of rule.partitions ?? []) {\n const source = droppedAt.get(partition.from)\n if (!source) {\n throw new FunnelIntegrityError(\n `admission partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n const rows = source.filter((record) => evaluatePredicate(partition.keep, record))\n partitionRows[partition.id] = rows\n partitionCounts.push({ id: partition.id, from: partition.from, count: rows.length })\n }\n const funnel = buildFunnel({\n population: rule.population,\n input: records.length,\n stages: stageInputs,\n partitions: partitionCounts,\n })\n return { funnel, survivors: current, partitionRows }\n}\n\n/**\n * Chain two funnels whose boundary agrees: the second funnel's input must be\n * exactly the first funnel's survivors. Anything else is a gap or an\n * injection, and both are refused.\n */\nexport function composeFunnels(\n first: ExperimentFunnel,\n second: ExperimentFunnel,\n): ExperimentFunnel {\n if (second.input !== first.surviving) {\n throw new FunnelIntegrityError(\n `cannot compose funnels: '${first.population}' survives ${first.surviving} rows but '${second.population}' starts from ${second.input}`,\n )\n }\n return buildFunnel({\n population: first.population,\n input: first.input,\n stages: [...first.stages, ...second.stages].map((stage) => ({\n id: stage.id,\n excluded: stage.excluded,\n ...(stage.exclusions ? { exclusions: stage.exclusions } : {}),\n ...(stage.waives ? { waives: stage.waives } : {}),\n })),\n partitions: [...first.partitions, ...second.partitions].map((partition) => ({\n id: partition.id,\n from: partition.from,\n count: partition.count,\n })),\n })\n}\n\n/**\n * Text render of the chain. One row per stage; the reconciliation line at the\n * bottom restates `input = surviving + excluded` so a reader can check the\n * arithmetic without a tool.\n */\nexport function renderFunnelTable(funnel: ExperimentFunnel): string {\n const rows = funnel.stages.map((stage) => [\n stage.id + (stage.waives?.length ? ` (waives: ${stage.waives.join(', ')})` : ''),\n String(stage.entering),\n String(stage.excluded),\n String(stage.remaining),\n ])\n const header = ['stage', 'entering', 'excluded', 'remaining']\n const widths = header.map((h, col) => Math.max(h.length, ...rows.map((r) => r[col]!.length)))\n const line = (cells: string[]): string =>\n cells.map((cell, col) => cell.padEnd(widths[col]!)).join(' ')\n const out: string[] = [\n `population: ${funnel.population}`,\n `input: ${funnel.input}`,\n line(header),\n line(widths.map((w) => '-'.repeat(w))),\n ...rows.map((r) => line(r)),\n ]\n const excluded = funnel.stages.reduce((sum, stage) => sum + stage.excluded, 0)\n out.push(\n `surviving: ${funnel.surviving} (input ${funnel.input} = surviving ${funnel.surviving} + excluded ${excluded})`,\n )\n for (const partition of funnel.partitions) {\n out.push(\n `partition ${partition.id}: ${partition.count} rows from '${partition.from}' — reported separately, never pooled`,\n )\n }\n return out.join('\\n')\n}\n","/**\n * Define, seal, and execute experiments whose every rule is registered data.\n *\n * `defineExperiment` validates the cross-references inside a spec and freezes\n * it. `sealExperiment` canonicalizes and hashes the whole tree — arms, row\n * admission, selection, estimands, intervals, decision rule, gates, halt,\n * budget — into one digest that lands on every downstream artifact. Changing\n * what is decided requires a new digest: an amendment is a re-seal with a\n * reason and blindness attestations, and the digest history is the audit\n * trail.\n *\n * `openSealedExperiment` is the only execution surface. It verifies the seal\n * and returns executors bound to the sealed spec; none of them takes a\n * parameter for alpha, threshold, metric, or stopping rule, so\n * registered-vs-ran drift is unrepresentable rather than checked.\n */\n\nimport { ValidationError } from '../errors'\nimport { hashCanonical } from '../ledger-core/canonical'\nimport {\n type AdmissionRule,\n type BudgetRule,\n type ComputedInterval,\n type Condition,\n computeEstimand,\n computeInterval,\n type DecisionOutcome,\n type DecisionRule,\n type DerivedQuantities,\n type Estimand,\n type EstimandResult,\n type EvidenceRecord,\n evaluateHaltRule,\n evaluateIdentityGate,\n evaluateOracleDeterminismGate,\n evaluatePopulationReproducibilityGate,\n evaluatePowerFloorGate,\n evaluateProvenanceGate,\n executeDecisionRule,\n type GateResult,\n type HaltOutcome,\n type HaltRule,\n type IntervalSpec,\n intervalSpecProblems,\n type JsonValue,\n type MatchedBudgetRule,\n type NLadderProjection,\n type Obligation,\n powerFloorProblems,\n projectNLadderBudget,\n type ReissuePolicy,\n runSelectionRule,\n runUniformPassBudget,\n type SelectionRule,\n type UniformPassSchedule,\n type ValidityGate,\n} from './ast'\nimport { type ArmRealizedBudget, type MatchedBudgetVerdict, verifyMatchedBudgets } from './budget'\nimport {\n defineEvaluationClaim,\n type EvaluationClaim,\n type EvaluationUnitSummary,\n summarizeEvaluationUnits,\n} from './claim'\nimport { type AdmissionExecution, executeAdmissionRule } from './funnel'\n\n/** A sealed experiment whose digest no longer matches its spec. */\nexport class SealIntegrityError extends ValidationError {}\n\n// ── Spec ─────────────────────────────────────────────────────────────\n\nexport interface ArmSpec {\n id: string\n role: 'treatment' | 'control'\n /** Digest of the AgentProfile the arm runs under. */\n profileDigest?: string\n /** Digest of the pinned execution policy the arm runs under. */\n policyDigest?: string\n /** Registered arm pins (model, seed, step budget, ...) as data. */\n pins?: Record<string, JsonValue>\n}\n\nexport type OutcomeSpec =\n | {\n kind: 'binary'\n /** Where the pass verdict comes from, e.g. 'injected-suite'. */\n source?: string\n digestVerified?: boolean\n /** What counts as a pass, e.g. 'exit-0' or 'reward-file-contains-1'. */\n pass?: string\n /** Errored rollouts stay in the denominator; dropping them is unregistered. */\n droppedRollouts?: 'forbidden'\n }\n | {\n kind: 'bounded-score'\n min: number\n max: number\n orientation: 'higher-is-better' | 'lower-is-better'\n }\n\n/**\n * Per-rollout seed derivation as a closed source list. `arm` is not in the\n * union, so arm-dependent seeding is unrepresentable.\n */\nexport interface SeedDerivation {\n from: ('seed' | 'rowId' | 'rolloutIndex')[]\n}\n\nexport interface ExperimentSpec {\n id: string\n /** Population and independent observation unit for the intended use of this result. */\n claim?: EvaluationClaim\n /** Human prose for the audit trail — never executable. */\n hypothesis?: string\n arms: ArmSpec[]\n outcome: OutcomeSpec\n admission?: AdmissionRule\n /** Named deterministic subset rules. */\n selections?: Record<string, SelectionRule>\n /**\n * Selection OUTPUTS pinned into the seal. A filter-of base resolves here, so\n * reusing an earlier draw is registered and a re-draw is a new digest.\n */\n sealedSubsets?: Record<string, string[]>\n estimands?: Record<string, Estimand>\n intervals?: Record<string, IntervalSpec>\n decision: DecisionRule\n obligations?: Obligation[]\n /** Named pre-spend validity gates; the halt rule references these names. */\n gates?: Record<string, ValidityGate>\n halt?: HaltRule\n budget?: BudgetRule\n matchedBudget?: MatchedBudgetRule\n reissue?: ReissuePolicy\n seedDerivation?: SeedDerivation\n seed?: number\n}\n\n// ── Validation ───────────────────────────────────────────────────────\n\nfunction conditionRefs(condition: Condition): {\n intervals: string[]\n quantities: string[]\n obligations: string[]\n} {\n switch (condition.kind) {\n case 'interval-excludes-zero':\n case 'interval-includes-zero':\n return { intervals: [condition.interval], quantities: [], obligations: [] }\n case 'quantity-threshold':\n return { intervals: [], quantities: [condition.quantity], obligations: [] }\n case 'obligation-met':\n return { intervals: [], quantities: [], obligations: [condition.obligation] }\n case 'all':\n case 'any': {\n const nested = condition.of.map(conditionRefs)\n return {\n intervals: nested.flatMap((r) => r.intervals),\n quantities: nested.flatMap((r) => r.quantities),\n obligations: nested.flatMap((r) => r.obligations),\n }\n }\n case 'not':\n return conditionRefs(condition.of)\n }\n}\n\n/**\n * Validate every cross-reference inside a spec and freeze it.\n *\n * A decision condition may only read a registered interval, a registered\n * estimand, or a registered obligation; a halt rule may only reference\n * registered gates; a filter-of base must resolve to a registered selection\n * or sealed subset. Anything else is refused here, before sealing.\n */\nexport function defineExperiment(spec: ExperimentSpec): ExperimentSpec {\n const problems: string[] = []\n const claim = spec.claim === undefined ? undefined : defineEvaluationClaim(spec.claim)\n if (!spec.id || spec.id.trim().length === 0) problems.push('id is empty')\n if (spec.arms.length === 0) problems.push('at least one arm is required')\n const armIds = new Set<string>()\n for (const arm of spec.arms) {\n if (armIds.has(arm.id)) problems.push(`duplicate arm id '${arm.id}'`)\n armIds.add(arm.id)\n }\n if (!spec.arms.some((arm) => arm.role === 'treatment')) {\n problems.push('at least one arm must have role treatment')\n }\n\n const intervalNames = new Set(Object.keys(spec.intervals ?? {}))\n const estimandNames = new Set(Object.keys(spec.estimands ?? {}))\n const obligationIds = new Set((spec.obligations ?? []).map((o) => o.id))\n const gateNames = new Set(Object.keys(spec.gates ?? {}))\n const selectionNames = new Set(Object.keys(spec.selections ?? {}))\n const sealedSubsetNames = new Set(Object.keys(spec.sealedSubsets ?? {}))\n\n for (const [name, interval] of Object.entries(spec.intervals ?? {})) {\n problems.push(\n ...intervalSpecProblems(interval).map((problem) => `interval '${name}': ${problem}`),\n )\n }\n\n for (const [name, gate] of Object.entries(spec.gates ?? {})) {\n if (gate.kind !== 'power-floor') continue\n problems.push(...powerFloorProblems(gate).map((problem) => `gate '${name}': ${problem}`))\n if (claim?.minimumEffect !== undefined && gate.minimumEffect !== claim.minimumEffect) {\n problems.push(`gate '${name}' minimumEffect differs from the evaluation claim`)\n }\n }\n if (claim?.generalization === 'new-units') {\n for (const [name, interval] of Object.entries(spec.intervals ?? {})) {\n if (interval?.kind === 'cluster-bootstrap' && interval.clusterBy !== claim.independentUnit) {\n problems.push(\n `interval '${name}' must resample '${claim.independentUnit}' from the evaluation claim`,\n )\n }\n }\n }\n\n const checkCondition = (condition: Condition, where: string): void => {\n const refs = conditionRefs(condition)\n for (const name of refs.intervals) {\n if (!intervalNames.has(name)) problems.push(`${where} reads unregistered interval '${name}'`)\n }\n for (const name of refs.quantities) {\n if (!estimandNames.has(name)) problems.push(`${where} reads unregistered quantity '${name}'`)\n }\n for (const name of refs.obligations) {\n if (!obligationIds.has(name))\n problems.push(`${where} reads unregistered obligation '${name}'`)\n }\n }\n\n if (spec.decision.kind === 'table') {\n if (spec.decision.branches.length === 0) problems.push('decision table has no branches')\n spec.decision.branches.forEach((branch, index) => {\n checkCondition(branch.when, `decision branch ${index} ('${branch.verdict}')`)\n })\n } else {\n for (const name of spec.decision.estimands) {\n if (!estimandNames.has(name)) {\n problems.push(`report-only decision names unregistered estimand '${name}'`)\n }\n }\n for (const name of spec.decision.intervals) {\n if (!intervalNames.has(name)) {\n problems.push(`report-only decision names unregistered interval '${name}'`)\n }\n }\n }\n\n if (spec.decision.kind === 'table' && spec.obligations) {\n const verdicts = new Set(spec.decision.branches.map((b) => b.verdict))\n for (const obligation of spec.obligations) {\n for (const verdict of obligation.appliesToVerdicts) {\n if (!verdicts.has(verdict)) {\n problems.push(\n `obligation '${obligation.id}' applies to verdict '${verdict}' which no branch produces`,\n )\n }\n }\n }\n }\n\n if (spec.halt) {\n for (const gate of spec.halt.when.gates) {\n if (!gateNames.has(gate)) problems.push(`halt rule references unregistered gate '${gate}'`)\n }\n }\n\n for (const [name, selection] of Object.entries(spec.selections ?? {})) {\n if (selection.kind === 'filter-of') {\n if (!selectionNames.has(selection.base) && !sealedSubsetNames.has(selection.base)) {\n problems.push(\n `selection '${name}' filters unregistered base '${selection.base}' (not a selection or sealed subset)`,\n )\n }\n }\n }\n\n if (spec.admission) {\n const stageIds = new Set<string>()\n for (const stage of spec.admission.stages) {\n if (stageIds.has(stage.id)) problems.push(`duplicate admission stage id '${stage.id}'`)\n stageIds.add(stage.id)\n }\n for (const partition of spec.admission.partitions ?? []) {\n if (!stageIds.has(partition.from)) {\n problems.push(\n `admission partition '${partition.id}' draws from unknown stage '${partition.from}'`,\n )\n }\n }\n }\n\n if (problems.length > 0) {\n throw new ValidationError(`defineExperiment('${spec.id}'): ${problems.join('; ')}`)\n }\n return deepFreeze(structuredClone({ ...spec, ...(claim ? { claim } : {}) }))\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value !== null && typeof value === 'object') {\n for (const key of Object.keys(value as object)) {\n deepFreeze((value as Record<string, unknown>)[key])\n }\n Object.freeze(value)\n }\n return value\n}\n\n// ── Seal ─────────────────────────────────────────────────────────────\n\nexport interface SealAmendment {\n /** ISO8601 timestamp of the re-seal. */\n at: string\n reason: string\n /** Blindness attestations: what was verifiably unseen when the amendment was made. */\n blind: string[]\n /** Digest of the spec after this amendment. */\n digest: string\n}\n\n/** SHA-256 over the RFC 8785 canonical JSON encoding of the experiment. */\nexport type SealAlgo = 'sha256-rfc8785'\n\nexport interface SealedExperiment {\n spec: ExperimentSpec\n /** sha256 over the serialized spec, under the scheme `algo` names. */\n digest: string\n /** Required digest scheme. Unsupported or missing schemes cannot execute. */\n algo: SealAlgo\n sealedAt: string\n /** Digest of the original registration, before any amendment. */\n initialDigest: string\n amendments: SealAmendment[]\n}\n\n/** Validate, canonicalize, and hash a spec into its registration. */\nexport async function sealExperiment(\n spec: ExperimentSpec,\n options: { sealedAt?: string } = {},\n): Promise<SealedExperiment> {\n const validated = defineExperiment(spec)\n const digest = specDigest(validated)\n return {\n spec: validated,\n digest,\n algo: 'sha256-rfc8785',\n sealedAt: options.sealedAt ?? new Date().toISOString(),\n initialDigest: digest,\n amendments: [],\n }\n}\n\n/**\n * Amend a sealed experiment. The current seal is verified first, the new spec\n * is validated and re-hashed, and the amendment appends to the digest chain.\n * There is no way to change what is decided without producing a new digest.\n */\nexport async function amendExperiment(\n sealed: SealedExperiment,\n amendment: { spec: ExperimentSpec; reason: string; blind: string[]; at?: string },\n): Promise<SealedExperiment> {\n const captured = structuredClone(sealed)\n const requested = structuredClone(amendment)\n await assertSealIntact(captured)\n const validated = defineExperiment(requested.spec)\n const digest = specDigest(validated)\n return {\n spec: validated,\n digest,\n algo: 'sha256-rfc8785',\n sealedAt: captured.sealedAt,\n initialDigest: captured.initialDigest,\n amendments: [\n ...captured.amendments,\n {\n at: requested.at ?? new Date().toISOString(),\n reason: requested.reason,\n blind: [...requested.blind],\n digest,\n },\n ],\n }\n}\n\n/** True when the supported seal matches its canonical spec. */\nexport async function verifySealedExperiment(sealed: SealedExperiment): Promise<boolean> {\n if (sealed.algo !== 'sha256-rfc8785') return false\n try {\n return specDigest(sealed.spec) === sealed.digest\n } catch {\n return false\n }\n}\n\nfunction specDigest(spec: ExperimentSpec): string {\n return hashCanonical(spec).slice('sha256:'.length)\n}\n\nasync function assertSealIntact(sealed: SealedExperiment): Promise<void> {\n if (!(await verifySealedExperiment(sealed))) {\n throw new SealIntegrityError(\n `sealed experiment '${sealed.spec.id}' has an unsupported digest scheme or its digest does not match its canonical spec`,\n )\n }\n}\n\n// ── Sealed execution ─────────────────────────────────────────────────\n\n/** Evidence a gate executor consumes, discriminated to match the gate kind. */\nexport type GateEvidence =\n | { kind: 'oracle-determinism'; repsByState: Record<string, readonly boolean[]> }\n | {\n kind: 'population-reproducibility'\n left: readonly EvidenceRecord[]\n right: readonly EvidenceRecord[]\n }\n | { kind: 'provenance-assertion'; provenance: EvidenceRecord }\n | { kind: 'identity'; pinned: string; served: string }\n | { kind: 'power-floor'; curve: readonly { effect: number; power: number }[] }\n\n/**\n * Executors bound to one verified seal. Every method reads its rule from the\n * sealed spec; evidence is the only argument anywhere.\n */\nexport interface RegisteredExperiment {\n readonly sealed: SealedExperiment\n /** Count independent units separately from repeated observations under the sealed claim. */\n units(records: readonly EvidenceRecord[]): EvaluationUnitSummary\n /** Execute the registered decision rule on derived quantities. */\n decide(evidence: DerivedQuantities): DecisionOutcome\n /** Run the registered admission funnel over evidence rows. */\n admit(records: readonly EvidenceRecord[]): AdmissionExecution\n /** Run a registered selection rule. Filter-of bases resolve to sealed subsets. */\n select(name: string, records: readonly EvidenceRecord[], options: { idField: string }): string[]\n /** Evaluate a registered validity gate on evidence of the matching kind. */\n gate(name: string, evidence: GateEvidence): GateResult\n /** Evaluate the registered halt rule over gate results. */\n halt(gates: readonly GateResult[]): HaltOutcome\n /** Execute the registered uniform-pass budget schedule. */\n runUniformPassBudget(measuredPassCosts: readonly number[]): UniformPassSchedule\n /** Project the registered n-ladder budget. */\n projectNLadderBudget(measured: { unitCostUsd: number; rows: number }): NLadderProjection\n /** Verify realized arm budgets under the registered matched-budget rule. */\n matchedBudgets(arms: readonly ArmRealizedBudget[]): MatchedBudgetVerdict\n /** Compute a registered estimand over evidence rows. */\n estimate(name: string, rows: readonly EvidenceRecord[]): EstimandResult\n /** Compute a registered interval spec. */\n interval(\n name: string,\n evidence:\n | { kind: 'rows'; rows: readonly EvidenceRecord[] }\n | { kind: 'binomial'; successes: number; trials: number; unitIds?: readonly string[] },\n ): ComputedInterval & { units?: EvaluationUnitSummary }\n}\n\n/**\n * Verify the seal and return executors bound to it. This is the module's only\n * execution surface: a rule that is not in the sealed spec cannot run, and a\n * rule that is cannot run differently.\n */\nexport async function openSealedExperiment(\n sealed: SealedExperiment,\n): Promise<RegisteredExperiment> {\n const captured = structuredClone(sealed)\n await assertSealIntact(captured)\n const spec = defineExperiment(captured.spec)\n const frozenSeal = deepFreeze({ ...captured, spec })\n const need = <T>(value: T | undefined, what: string): T => {\n if (value === undefined) {\n throw new ValidationError(`experiment '${spec.id}' registered no ${what}`)\n }\n return value\n }\n return {\n sealed: frozenSeal,\n units: (records) => summarizeEvaluationUnits(need(spec.claim, 'evaluation claim'), records),\n decide: (evidence) => executeDecisionRule(spec.decision, evidence),\n admit: (records) => executeAdmissionRule(need(spec.admission, 'admission rule'), records),\n select: (name, records, options) => {\n const rule = need(spec.selections?.[name], `selection '${name}'`)\n return runSelectionRule(rule, records, {\n idField: options.idField,\n bases: spec.sealedSubsets,\n })\n },\n gate: (name, evidence) => {\n const gate = need(spec.gates?.[name], `gate '${name}'`)\n if (gate.kind !== evidence.kind) {\n throw new ValidationError(\n `gate '${name}' is registered as ${gate.kind} but received ${evidence.kind} evidence`,\n )\n }\n switch (gate.kind) {\n case 'oracle-determinism':\n return evaluateOracleDeterminismGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'oracle-determinism' }>).repsByState,\n )\n case 'population-reproducibility': {\n const populations = evidence as Extract<\n GateEvidence,\n { kind: 'population-reproducibility' }\n >\n return evaluatePopulationReproducibilityGate(name, gate, populations)\n }\n case 'provenance-assertion':\n return evaluateProvenanceGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'provenance-assertion' }>).provenance,\n )\n case 'identity':\n return evaluateIdentityGate(\n name,\n gate,\n evidence as Extract<GateEvidence, { kind: 'identity' }>,\n )\n case 'power-floor':\n return evaluatePowerFloorGate(\n name,\n gate,\n (evidence as Extract<GateEvidence, { kind: 'power-floor' }>).curve,\n )\n }\n },\n halt: (gates) => evaluateHaltRule(need(spec.halt, 'halt rule'), gates),\n runUniformPassBudget: (measuredPassCosts) => {\n const budget = need(spec.budget, 'budget rule')\n if (budget.kind !== 'uniform-pass') {\n throw new ValidationError(\n `experiment '${spec.id}' registered a ${budget.kind} budget, not uniform-pass`,\n )\n }\n return runUniformPassBudget(budget, measuredPassCosts)\n },\n projectNLadderBudget: (measured) => {\n const budget = need(spec.budget, 'budget rule')\n if (budget.kind !== 'n-ladder') {\n throw new ValidationError(\n `experiment '${spec.id}' registered a ${budget.kind} budget, not n-ladder`,\n )\n }\n return projectNLadderBudget(budget, measured)\n },\n matchedBudgets: (arms) =>\n verifyMatchedBudgets(need(spec.matchedBudget, 'matched-budget rule'), arms),\n estimate: (name, rows) =>\n computeEstimand(need(spec.estimands?.[name], `estimand '${name}'`), rows),\n interval: (name, evidence) => {\n const interval = need(spec.intervals?.[name], `interval '${name}'`)\n const claim = spec.claim\n let units: EvaluationUnitSummary | undefined\n if (claim && evidence.kind === 'rows') {\n units = summarizeEvaluationUnits(claim, evidence.rows)\n } else if (claim?.generalization === 'new-units' && evidence.kind === 'binomial') {\n if (\n evidence.unitIds === undefined ||\n evidence.unitIds.length !== evidence.trials ||\n new Set(evidence.unitIds).size !== evidence.trials ||\n evidence.unitIds.some((id) => typeof id !== 'string' || !id.trim() || id.trim() !== id)\n ) {\n throw new ValidationError(\n 'claimed binomial interval needs one unique unitId per independent trial',\n )\n }\n units = {\n observations: evidence.trials,\n independentUnits: evidence.trials,\n units: evidence.unitIds.map((id) => ({ id, observations: 1 })),\n }\n }\n return { ...computeInterval(interval, evidence), ...(units ? { units } : {}) }\n },\n }\n}\n","/**\n * The evidence registry record — the canonical, machine-readable unit for a\n * measured claim about an agent, a prompt, a policy, or an instrument.\n *\n * One record answers, in typed fields, the questions a scattered results doc\n * leaves to prose: what was claimed, what instrument measured it, the exact\n * command that reproduces it, which arms ran, the denominator, what it cost,\n * what confounds the comparison, and how much trust the evidence has earned.\n *\n * Records live as JSON files in `evidence/records/` at the repo root — one\n * file per claim, filename `<id>.json`. The registry lives in agent-eval\n * because the measurement substrate owns evidence legitimacy; every other\n * repo keeps at most a pointer file. `scripts/render-evidence-index.ts`\n * generates the human index from these records, so prose can never drift\n * from data, and `pnpm run evidence:check` (part of `verify:package`) fails\n * on an invalid record or a stale index.\n *\n * The shape extends the `.evolve/experiments.jsonl` session-log vocabulary\n * (ts/hypothesis/change/result/evidence) into a curated registry record.\n * Session logs stay append-only diaries; a registry record is the durable,\n * addressable claim distilled from them.\n */\n\nimport { z } from 'zod'\n\n/**\n * Trust ladder for a recorded claim, strongest first.\n *\n * - `CERTIFIED` — pre-registered rule, sealed or held-out data, and either a\n * defended challenge or a check that re-runs in the suite.\n * - `MEASURED-ONCE` — one honest measurement on the real path, not replicated.\n * - `RESOLVED-NULL` — measured with an adequate instrument; the effect did not\n * appear under the registered rule. A null is a result, not a failure.\n * - `UNVERIFIED` — stated somewhere load-bearing, but no independent check has\n * run. Admitting this state is what keeps folklore out of the other four.\n * - `KILLED` — refuted, invalidated, or superseded by a stronger record.\n */\nexport const EVIDENCE_STATES = [\n 'CERTIFIED',\n 'MEASURED-ONCE',\n 'RESOLVED-NULL',\n 'UNVERIFIED',\n 'KILLED',\n] as const\n\nexport type EvidenceState = (typeof EVIDENCE_STATES)[number]\n\nconst idPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nconst datePattern = /^\\d{4}-\\d{2}-\\d{2}$/\nconst sha256Pattern = /^[0-9a-f]{64}$/\n\n/** Denominator of the measurement. A claim without an `n` is prose, not evidence. */\nconst evidenceDenominatorSchema = z.strictObject({\n value: z.number().positive().finite(),\n /** What one unit is: rows, cases, rollouts, records, leaves… */\n unit: z.string().min(1),\n /** Clustering, reps, split names — whatever the bare number hides. */\n detail: z.string().min(1).optional(),\n})\n\nexport type EvidenceDenominator = z.infer<typeof evidenceDenominatorSchema>\n\nexport const evidenceRegistryRecordSchema = z.strictObject({\n /** Stable kebab-case identity; the registry filename is `<id>.json`. */\n id: z.string().regex(idPattern),\n /** Date the decisive measurement completed, `YYYY-MM-DD`. */\n date: z.string().regex(datePattern),\n /** The one-sentence load-bearing claim, stated so it can fail. */\n claim: z.string().min(1),\n /** Domain the claim lives in: trace-repair, multishot, analyst, vertical-bench… */\n domain: z.string().min(1),\n /** The instrument that produced the number — script, harness, oracle, judge. */\n instrument: z.string().min(1),\n /**\n * The exact invocation that reproduces the measurement.\n * `null` means the invocation was not preserved — a named gap, never a guess.\n */\n command: z.string().min(1).nullable(),\n /** Compared arms. Empty for a single-arm measurement. */\n arms: z.array(z.string().min(1)),\n n: evidenceDenominatorSchema,\n /** The measured numbers, with uncertainty when it exists. Numbers, not adjectives. */\n result: z.string().min(1),\n evidenceState: z.enum(EVIDENCE_STATES),\n /** Where the raw data lives: repo paths, PR/gist URLs, run directories. Never empty. */\n artifacts: z.array(z.string().min(1)).min(1),\n /**\n * Measured spend in USD. `0` is a true zero (deterministic, no paid calls);\n * `null` means spend was not captured — a named gap, never a silent zero.\n */\n costUsd: z.number().nonnegative().nullable(),\n /** Every known asymmetry or threat to validity. Empty only when none is known. */\n confounds: z.array(z.string().min(1)),\n /** Repo whose work produced the evidence (the registry itself lives here). */\n sourceRepo: z.string().min(1),\n /** Seal digest of the registered experiment (`./experiment`), when one governed the run. */\n experimentDigest: z.string().regex(sha256Pattern).optional(),\n /** Ids of records this one supersedes. */\n supersedes: z.array(z.string().regex(idPattern)).optional(),\n notes: z.string().min(1).optional(),\n})\n\nexport type EvidenceRegistryRecord = z.infer<typeof evidenceRegistryRecordSchema>\n\n/** Parse one record; throws with the zod issue list on any violation. */\nexport function parseEvidenceRegistryRecord(raw: unknown): EvidenceRegistryRecord {\n return evidenceRegistryRecordSchema.parse(raw)\n}\n\nclass EvidenceRegistryError extends Error {}\n\n/**\n * Validate a set of records as one registry: every record parses, ids are\n * unique, and every `supersedes` target exists. Returns records sorted in\n * the registry's canonical order (trust ladder, then date desc, then id).\n */\nexport function validateEvidenceRegistry(raws: readonly unknown[]): EvidenceRegistryRecord[] {\n const records = raws.map((raw) => parseEvidenceRegistryRecord(raw))\n const seen = new Set<string>()\n for (const record of records) {\n if (seen.has(record.id)) {\n throw new EvidenceRegistryError(`duplicate evidence record id: ${record.id}`)\n }\n seen.add(record.id)\n }\n for (const record of records) {\n for (const target of record.supersedes ?? []) {\n if (!seen.has(target)) {\n throw new EvidenceRegistryError(`record ${record.id} supersedes unknown record: ${target}`)\n }\n }\n }\n const stateRank = new Map(EVIDENCE_STATES.map((state, index) => [state, index]))\n return [...records].sort((a, b) => {\n const byState = (stateRank.get(a.evidenceState) ?? 0) - (stateRank.get(b.evidenceState) ?? 0)\n if (byState !== 0) return byState\n if (a.date !== b.date) return a.date < b.date ? 1 : -1\n return a.id < b.id ? -1 : 1\n })\n}\n\nfunction mdEscape(text: string): string {\n return text.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ')\n}\n\nfunction formatCost(costUsd: number | null): string {\n if (costUsd === null) return 'not captured'\n return `$${costUsd.toFixed(2)}`\n}\n\nfunction formatN(n: EvidenceDenominator): string {\n const base = `${n.value} ${n.unit}`\n return n.detail ? `${base} (${n.detail})` : base\n}\n\n/**\n * Render the registry's human index from records. Deterministic: identical\n * records always produce identical output, so a byte diff against the\n * committed index is the freshness check. No clocks, no environment.\n */\nexport function renderEvidenceIndex(raws: readonly unknown[]): string {\n const records = validateEvidenceRegistry(raws)\n const lines: string[] = [\n '# Evidence index',\n '',\n '<!-- GENERATED by scripts/render-evidence-index.ts from evidence/records/*.json.',\n ' Edit the records, run `pnpm run evidence:render`, and commit both.',\n ' `pnpm run evidence:check` (inside verify:package) fails when this file drifts. -->',\n '',\n `${records.length} records. States: ${EVIDENCE_STATES.join(' > ')}.`,\n '',\n '| state | date | id | claim | result |',\n '| --- | --- | --- | --- | --- |',\n ]\n for (const r of records) {\n lines.push(\n `| ${r.evidenceState} | ${r.date} | [\\`${r.id}\\`](#${r.id}) | ${mdEscape(r.claim)} | ${mdEscape(r.result)} |`,\n )\n }\n for (const r of records) {\n lines.push('', `## ${r.id}`, '')\n lines.push(`**${r.evidenceState}** · ${r.date} · ${r.domain} · source repo \\`${r.sourceRepo}\\``)\n lines.push('', `**Claim.** ${r.claim}`, '', `**Result.** ${r.result}`, '')\n lines.push(`- **Instrument**: ${r.instrument}`)\n lines.push(`- **Command**: ${r.command === null ? 'not preserved' : `\\`${r.command}\\``}`)\n lines.push(`- **Arms**: ${r.arms.length === 0 ? 'single-arm' : r.arms.join(' vs ')}`)\n lines.push(`- **n**: ${formatN(r.n)}`)\n lines.push(`- **Cost**: ${formatCost(r.costUsd)}`)\n if (r.experimentDigest) lines.push(`- **Experiment seal**: \\`${r.experimentDigest}\\``)\n lines.push(`- **Artifacts**:`)\n for (const artifact of r.artifacts) lines.push(` - ${artifact}`)\n if (r.confounds.length === 0) {\n lines.push('- **Confounds**: none recorded')\n } else {\n lines.push('- **Confounds**:')\n for (const confound of r.confounds) lines.push(` - ${confound}`)\n }\n if (r.supersedes && r.supersedes.length > 0) {\n lines.push(`- **Supersedes**: ${r.supersedes.map((s) => `\\`${s}\\``).join(', ')}`)\n }\n if (r.notes) lines.push(`- **Notes**: ${r.notes}`)\n }\n lines.push('')\n return lines.join('\\n')\n}\n","/**\n * Design-time power for task-clustered paired designs, with a refusal verdict.\n *\n * The failure this prevents (measured): a pre-registered kill test fixed a\n * task-clustered bootstrap over 14 rows in 4 task clusters. Simulated at the\n * registered seed, the design's power topped out at 0.69 — at a per-row\n * effect of 1.0. \"Four clusters cannot certify any effect size, including\n * 1.0\" was learned by running the experiment; this module computes it before\n * a dollar is spent.\n *\n * Two floors, one simulation:\n * - Closed form, zero spend: with C independent clusters the exact\n * whole-cluster sign-flip test can never produce a two-sided p below\n * 2^(1-C). C=4 gives 0.125; C=3 gives 0.25 — both above a 0.05 alpha, so\n * those designs are refused at ANY effect size, before simulation.\n * - Seeded simulation: per-row paired contrasts drawn under a registered\n * effect model, a whole-cluster percentile bootstrap on each trial, power =\n * the fraction of trials whose interval excludes zero.\n *\n * The refusal is a verdict INSIDE the returned artifact (the powerPreflight\n * shape, made cluster-aware); `assertDesignAdequate` turns it into a throw for\n * callers that want configuration-time failure.\n */\n\nimport { ValidationError } from '../errors'\nimport { mulberry32 } from '../statistics'\n\n/** A design refused at configuration time, before any spend. */\nexport class DesignRefusalError extends ValidationError {}\n\nexport interface ClusteredPowerOptions {\n /** Rows per independent cluster, e.g. [6, 3, 3, 2]. */\n clusterSizes: number[]\n /** P(win) − P(loss) in signal clusters; noisy clusters retain zero expected contrast. */\n effects: number[]\n /** Minimum worthwhile effect under the declared outcome model; must occur in effects. */\n minimumEffect: number\n /** Deterministic seed for outcome draws and bootstrap resampling. */\n seed: number\n /** Simulated experiments per effect. Default 2000. */\n trials?: number\n /** Whole-cluster bootstrap draws per trial. Default 4000. */\n resamples?: number\n /** Percentile interval level. Default 0.95. */\n confidence?: number\n /** Sign-flip alpha the closed-form floor is checked against. Default 0.05. */\n alpha?: number\n /** Power required at minimumEffect. Default 0.8. */\n targetPower?: number\n /** P(row favors treatment) under the zero-effect model. Must equal baseLossRate. Default 0.10. */\n baseWinRate?: number\n /** P(row favors control) under the zero-effect model. Must equal baseWinRate. Default 0.10. */\n baseLossRate?: number\n /**\n * Clusters whose rows carry outcome noise instead of signal: each row wins\n * with `flipRate` and loses with `flipRate`, independent of the effect.\n * Index into `clusterSizes`.\n */\n noisyClusters?: { index: number; flipRate: number }[]\n}\n\nexport interface ClusteredPowerPoint {\n effect: number\n power: number\n medianCiWidth: number\n}\n\nexport interface SignFlipFloor {\n /** Smallest achievable two-sided p: 2^(1-C) for C clusters. */\n twoSidedP: number\n /** Smallest achievable one-sided p: 2^-C. */\n oneSidedP: number\n alpha: number\n /** False when the cluster count can never certify at `alpha`, at any effect. */\n certifiableAtAlpha: boolean\n /** Smallest cluster count whose two-sided floor is at or under `alpha`. */\n minClustersForAlpha: number\n}\n\nexport interface ClusteredPowerRefusal {\n verdict: 'underpowered'\n reasons: string[]\n recommendation: string\n}\n\nexport interface ClusteredPowerResult {\n clusterCount: number\n totalRows: number\n trials: number\n resamples: number\n seed: number\n confidence: number\n targetPower: number\n minimumEffect: number\n powerAtMinimumEffect: number\n curve: ClusteredPowerPoint[]\n /** Maximum simulated power across the effect grid. */\n maxPower: number\n signFlipFloor: SignFlipFloor\n /** True when the sign-flip floor certifies and power at minimumEffect reaches target. */\n adequate: boolean\n /** Populated exactly when `adequate` is false. The refusal lives in the artifact. */\n refusal: ClusteredPowerRefusal | null\n}\n\n/**\n * Simulate the power of a whole-cluster percentile-bootstrap design and refuse\n * a structure that cannot reach target power at the declared minimum effect.\n */\nexport function clusteredPower(options: ClusteredPowerOptions): ClusteredPowerResult {\n const clusterSizes = options.clusterSizes\n if (clusterSizes.length === 0 || clusterSizes.some((n) => !Number.isInteger(n) || n <= 0)) {\n throw new ValidationError(\n `clusteredPower: clusterSizes must be positive integers, got [${clusterSizes.join(', ')}]`,\n )\n }\n if (options.effects.length === 0) {\n throw new ValidationError('clusteredPower: effects grid is empty')\n }\n if (\n options.effects.some((effect) => !Number.isFinite(effect) || effect < 0 || effect > 1) ||\n new Set(options.effects).size !== options.effects.length\n ) {\n throw new ValidationError('clusteredPower: effects must be unique finite values in [0,1]')\n }\n if (\n !Number.isFinite(options.minimumEffect) ||\n options.minimumEffect <= 0 ||\n options.minimumEffect > 1\n ) {\n throw new ValidationError('clusteredPower: minimumEffect must be in (0,1]')\n }\n if (!options.effects.includes(options.minimumEffect)) {\n throw new ValidationError(\n 'clusteredPower: effects must contain minimumEffect exactly; no interpolation is assumed',\n )\n }\n if (!Number.isInteger(options.seed)) {\n throw new ValidationError(`clusteredPower: seed must be an integer, got ${options.seed}`)\n }\n const trials = options.trials ?? 2000\n const resamples = options.resamples ?? 4000\n if (!Number.isInteger(trials) || trials <= 0 || !Number.isInteger(resamples) || resamples <= 0) {\n throw new ValidationError(\n `clusteredPower: trials and resamples must be positive integers, got ${trials}/${resamples}`,\n )\n }\n const confidence = options.confidence ?? 0.95\n if (!Number.isFinite(confidence) || confidence <= 0 || confidence >= 1) {\n throw new ValidationError(`clusteredPower: confidence must be in (0,1), got ${confidence}`)\n }\n const alpha = options.alpha ?? 0.05\n const targetPower = options.targetPower ?? 0.8\n if (!Number.isFinite(alpha) || alpha <= 0 || alpha >= 1) {\n throw new ValidationError('clusteredPower: alpha must be in (0,1)')\n }\n if (!Number.isFinite(targetPower) || targetPower <= 0 || targetPower > 1) {\n throw new ValidationError('clusteredPower: targetPower must be in (0,1]')\n }\n const baseWinRate = options.baseWinRate ?? 0.1\n const baseLossRate = options.baseLossRate ?? 0.1\n if (\n !Number.isFinite(baseWinRate) ||\n !Number.isFinite(baseLossRate) ||\n baseWinRate < 0 ||\n baseLossRate < 0 ||\n baseWinRate + baseLossRate > 1\n ) {\n throw new ValidationError(\n 'clusteredPower: base win/loss rates must be nonnegative and sum to at most 1',\n )\n }\n if (baseWinRate !== baseLossRate) {\n throw new ValidationError(\n 'clusteredPower: the zero-effect model requires equal baseWinRate and baseLossRate',\n )\n }\n const noisy = new Map<number, number>()\n for (const cluster of options.noisyClusters ?? []) {\n if (\n !Number.isInteger(cluster.index) ||\n cluster.index < 0 ||\n cluster.index >= clusterSizes.length\n ) {\n throw new ValidationError(\n `clusteredPower: noisy cluster index ${cluster.index} outside [0,${clusterSizes.length - 1}]`,\n )\n }\n if (\n noisy.has(cluster.index) ||\n !Number.isFinite(cluster.flipRate) ||\n cluster.flipRate < 0 ||\n cluster.flipRate > 1\n ) {\n throw new ValidationError(\n 'clusteredPower: noisy clusters need unique indices and flipRate in [0,1]',\n )\n }\n noisy.set(cluster.index, cluster.flipRate)\n }\n\n const clusterCount = clusterSizes.length\n const totalRows = clusterSizes.reduce((a, b) => a + b, 0)\n const signFlipFloor = computeSignFlipFloor(clusterCount, alpha)\n\n const curve: ClusteredPowerPoint[] = []\n for (const effect of options.effects) {\n curve.push(\n simulateEffect(effect, {\n clusterSizes,\n seed: options.seed,\n trials,\n resamples,\n confidence,\n baseWinRate,\n baseLossRate,\n noisy,\n }),\n )\n }\n const maxPower = Math.max(...curve.map((point) => point.power))\n const powerAtMinimumEffect = curve.find((point) => point.effect === options.minimumEffect)!.power\n\n const reasons: string[] = []\n if (!signFlipFloor.certifiableAtAlpha) {\n reasons.push(\n `${clusterCount} clusters cannot certify any effect size, including 1.0: the exact ` +\n `whole-cluster sign-flip test's smallest two-sided p is 2^(1-${clusterCount}) = ` +\n `${signFlipFloor.twoSidedP} > alpha ${alpha}; at least ` +\n `${signFlipFloor.minClustersForAlpha} clusters are needed`,\n )\n }\n if (powerAtMinimumEffect < targetPower) {\n reasons.push(\n `simulated power ${powerAtMinimumEffect.toFixed(3)} at minimum worthwhile effect ` +\n `${options.minimumEffect} is below target ${targetPower}; maximum grid power ` +\n `${maxPower.toFixed(3)} does not establish adequacy at that effect`,\n )\n }\n const adequate = reasons.length === 0\n return {\n clusterCount,\n totalRows,\n trials,\n resamples,\n seed: options.seed,\n confidence,\n targetPower,\n minimumEffect: options.minimumEffect,\n powerAtMinimumEffect,\n curve,\n maxPower,\n signFlipFloor,\n adequate,\n refusal: adequate\n ? null\n : {\n verdict: 'underpowered',\n reasons,\n recommendation:\n `Do not spend on this structure. Add independent clusters (>= ` +\n `${Math.max(signFlipFloor.minClustersForAlpha, clusterCount)}) or register a design ` +\n `whose simulated power reaches ${targetPower} at effect ${options.minimumEffect}, ` +\n `then re-run clusteredPower.`,\n },\n }\n}\n\n/** Throw the refusal for callers that want configuration-time failure. */\nexport function assertDesignAdequate(result: ClusteredPowerResult): void {\n if (result.refusal) {\n throw new DesignRefusalError(\n `design refused (underpowered): ${result.refusal.reasons.join('; ')}`,\n )\n }\n}\n\nfunction computeSignFlipFloor(clusterCount: number, alpha: number): SignFlipFloor {\n const twoSidedP = 2 ** (1 - clusterCount)\n const oneSidedP = 2 ** -clusterCount\n let minClusters = 1\n while (2 ** (1 - minClusters) > alpha) minClusters += 1\n return {\n twoSidedP,\n oneSidedP,\n alpha,\n certifiableAtAlpha: twoSidedP <= alpha,\n minClustersForAlpha: minClusters,\n }\n}\n\ninterface SimulationConfig {\n clusterSizes: number[]\n seed: number\n trials: number\n resamples: number\n confidence: number\n baseWinRate: number\n baseLossRate: number\n noisy: Map<number, number>\n}\n\n/**\n * One effect point. Loss probability is min(baseLoss, (1-effect)/2) and\n * win probability is loss probability plus effect. Their difference equals\n * effect, including near the probability boundary. Noisy clusters draw win\n * and loss independently at their\n * flip rate. Each trial computes a whole-cluster percentile bootstrap of the\n * pooled row mean; the trial counts toward power when the interval excludes\n * zero.\n */\nfunction simulateEffect(effect: number, config: SimulationConfig): ClusteredPowerPoint {\n const rng = mulberry32(mixSeed(config.seed, effect))\n const clusterCount = config.clusterSizes.length\n let excludes = 0\n const widths = new Array<number>(config.trials)\n const sums = new Array<number>(clusterCount)\n const means = new Array<number>(config.resamples)\n for (let trial = 0; trial < config.trials; trial++) {\n for (let cluster = 0; cluster < clusterCount; cluster++) {\n const size = config.clusterSizes[cluster]!\n const flipRate = config.noisy.get(cluster)\n let sum = 0\n for (let row = 0; row < size; row++) {\n if (flipRate !== undefined) {\n const win = rng() < flipRate ? 1 : 0\n const loss = rng() < flipRate ? 1 : 0\n sum += win - loss\n } else {\n const lossRate = Math.min(config.baseLossRate, (1 - effect) / 2)\n const winRate = lossRate + effect\n const u = rng()\n sum += u < winRate ? 1 : u < winRate + lossRate ? -1 : 0\n }\n }\n sums[cluster] = sum\n }\n for (let draw = 0; draw < config.resamples; draw++) {\n let pooledSum = 0\n let pooledRows = 0\n for (let pick = 0; pick < clusterCount; pick++) {\n const index = Math.floor(rng() * clusterCount)\n pooledSum += sums[index]!\n pooledRows += config.clusterSizes[index]!\n }\n means[draw] = pooledSum / pooledRows\n }\n means.sort((a, b) => a - b)\n const tail = 1 - config.confidence\n const lower = means[Math.floor((tail / 2) * config.resamples)]!\n const upper =\n means[\n Math.max(\n Math.floor((tail / 2) * config.resamples),\n Math.min(config.resamples - 1, Math.ceil((1 - tail / 2) * config.resamples) - 1),\n )\n ]!\n widths[trial] = upper - lower\n if (lower > 0 || upper < 0) excludes += 1\n }\n widths.sort((a, b) => a - b)\n return {\n effect,\n power: excludes / config.trials,\n medianCiWidth: widths[Math.floor(config.trials / 2)]!,\n }\n}\n\n/** Fold the effect into the seed so every grid point draws an independent stream. */\nfunction mixSeed(seed: number, effect: number): number {\n const scaled = Math.round(effect * 1_000_003)\n return ((seed ^ (scaled * 0x9e3779b9)) >>> 0) | 0\n}\n","import { ValidationError } from '../errors'\nimport type {\n CanaryAssignmentReceipt,\n CanaryObservation,\n SealedRandomizedCanaryRule,\n} from './randomized-canary'\n\n/** Host-ledger assignment written when an eligible request is routed. */\nexport interface ProspectiveCanaryAssignment extends CanaryAssignmentReceipt {\n sourceUnitId: string\n assignedAt: string\n}\n\n/** Independent checker result, including a null when the outcome is unavailable. */\nexport interface ProspectiveCanaryOutcome {\n assignmentId: string\n outcomeSourceId: string\n checkedOutcome: 0 | 1 | null\n outcomeCheckerDigest: string\n checkedAt: string\n}\n\n/** Served trace, or an independent receipt that the assigned unit never executed. */\nexport interface ProspectiveCanaryExecution {\n assignmentId: string\n traceSourceId: string | null\n noExecutionSourceId: string | null\n servedProfileDigest: string | null\n servedCodeRevisionDigest: string | null\n turns: number | null\n providerCallIds: readonly string[]\n recordedAt: string\n}\n\n/** Billing authority's settled snapshot for every provider call in one assignment. */\nexport interface ProspectiveCanaryBilling {\n assignmentId: string\n billingSourceId: string\n settlement: 'settled' | 'unknown'\n billedCostUsd: number | null\n providerCallIds: readonly string[]\n recordedAt: string\n}\n\nexport interface ProspectiveCanaryJoinInput {\n /** An opt-in host flag. Calling this function never routes product traffic. */\n enabled?: boolean\n sealed: SealedRandomizedCanaryRule\n /** The host must independently verify this witness predates every assignment. */\n protocolWitnessedAt: string\n /** The complete prior-source roster must be attested by the host verifier. */\n historicalSourceUnitIds: readonly string[]\n assignments: readonly ProspectiveCanaryAssignment[]\n outcomes: readonly ProspectiveCanaryOutcome[]\n executions: readonly ProspectiveCanaryExecution[]\n billing: readonly ProspectiveCanaryBilling[]\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {\n throw new ValidationError(`prospective canary: ${label} must be a nonempty trimmed string`)\n }\n}\n\nfunction utc(value: unknown, label: string): number {\n nonEmpty(value, label)\n const parsed = Date.parse(value)\n const canonical = Number.isFinite(parsed) ? new Date(parsed).toISOString() : ''\n if (\n !value.endsWith('Z') ||\n !Number.isFinite(parsed) ||\n (value !== canonical && value !== canonical.replace('.000Z', 'Z'))\n ) {\n throw new ValidationError(`prospective canary: ${label} must be a canonical UTC timestamp`)\n }\n return parsed\n}\n\nfunction indexRows<T extends { assignmentId: string }>(\n rows: readonly T[],\n label: string,\n assignments: ReadonlySet<string>,\n): Map<string, T> {\n const indexed = new Map<string, T>()\n for (const row of rows) {\n nonEmpty(row.assignmentId, `${label} assignmentId`)\n if (!assignments.has(row.assignmentId)) {\n throw new ValidationError(`prospective canary: orphan ${label} for '${row.assignmentId}'`)\n }\n if (indexed.has(row.assignmentId)) {\n throw new ValidationError(`prospective canary: duplicate ${label} for '${row.assignmentId}'`)\n }\n indexed.set(row.assignmentId, row)\n }\n return indexed\n}\n\nfunction uniqueIds(ids: readonly string[], label: string): string[] {\n if (!Array.isArray(ids)) {\n throw new ValidationError(`prospective canary: ${label} must be an array`)\n }\n const seen = new Set<string>()\n for (const id of ids) {\n nonEmpty(id, label)\n if (seen.has(id)) throw new ValidationError(`prospective canary: duplicate ${label} '${id}'`)\n seen.add(id)\n }\n return [...seen].sort()\n}\n\n/**\n * Join independently sourced served receipts without inventing missing costs.\n * The host still verifies ledger completeness, source authority, isolation,\n * randomization and the pre-traffic witness in `decideRandomizedCanary`.\n */\nexport function joinProspectiveCanaryReceipts(\n input: ProspectiveCanaryJoinInput,\n): CanaryObservation[] {\n if (input.enabled !== true) {\n throw new ValidationError('prospective canary: pilot is disabled')\n }\n const witnessedAt = utc(input.protocolWitnessedAt, 'protocolWitnessedAt')\n const cutoff = utc(input.sealed.rule.analysisCutoff, 'analysisCutoff')\n if (witnessedAt >= cutoff) {\n throw new ValidationError('prospective canary: protocol witness must precede cutoff')\n }\n if (!Array.isArray(input.assignments) || input.assignments.length === 0) {\n throw new ValidationError('prospective canary: assignment ledger is empty')\n }\n const historical = new Set(uniqueIds(input.historicalSourceUnitIds, 'historical source unit'))\n const assignmentIds = new Set<string>()\n const assignmentSources = new Set<string>()\n const sourceUnits = new Set<string>()\n for (const row of input.assignments) {\n nonEmpty(row.assignmentId, 'assignmentId')\n nonEmpty(row.assignmentSourceId, 'assignmentSourceId')\n nonEmpty(row.clusterId, 'clusterId')\n nonEmpty(row.sourceUnitId, 'sourceUnitId')\n if (row.arm !== 'control' && row.arm !== 'candidate') {\n throw new ValidationError('prospective canary: assignment arm is invalid')\n }\n if (assignmentIds.has(row.assignmentId) || assignmentSources.has(row.assignmentSourceId)) {\n throw new ValidationError('prospective canary: duplicate assignment identity')\n }\n if (sourceUnits.has(row.sourceUnitId) || historical.has(row.sourceUnitId)) {\n throw new ValidationError(`prospective canary: source unit '${row.sourceUnitId}' is reused`)\n }\n const assignedAt = utc(row.assignedAt, `assignment '${row.assignmentId}' assignedAt`)\n if (assignedAt <= witnessedAt || assignedAt > cutoff) {\n throw new ValidationError('prospective canary: assignment falls outside witnessed window')\n }\n assignmentIds.add(row.assignmentId)\n assignmentSources.add(row.assignmentSourceId)\n sourceUnits.add(row.sourceUnitId)\n }\n const outcomes = indexRows(input.outcomes, 'outcome', assignmentIds)\n const executions = indexRows(input.executions, 'execution', assignmentIds)\n const billing = indexRows(input.billing, 'billing', assignmentIds)\n const sourceIds = new Set(assignmentSources)\n const claimSource = (id: string, label: string) => {\n nonEmpty(id, label)\n if (sourceIds.has(id)) {\n throw new ValidationError(`prospective canary: reused independent source '${id}'`)\n }\n sourceIds.add(id)\n }\n\n return input.assignments.map((assignment) => {\n const outcome = outcomes.get(assignment.assignmentId)\n const execution = executions.get(assignment.assignmentId)\n const bill = billing.get(assignment.assignmentId)\n const assignedAt = Date.parse(assignment.assignedAt)\n if (outcome) {\n claimSource(outcome.outcomeSourceId, 'outcomeSourceId')\n nonEmpty(outcome.outcomeCheckerDigest, 'outcomeCheckerDigest')\n if (utc(outcome.checkedAt, 'checkedAt') < assignedAt) {\n throw new ValidationError('prospective canary: outcome precedes assignment')\n }\n if (![0, 1, null].includes(outcome.checkedOutcome)) {\n throw new ValidationError('prospective canary: checked outcome must be 0, 1 or null')\n }\n }\n if (execution) {\n if ((execution.traceSourceId === null) === (execution.noExecutionSourceId === null)) {\n throw new ValidationError(\n 'prospective canary: execution needs one trace or no-execution source',\n )\n }\n claimSource(execution.traceSourceId ?? execution.noExecutionSourceId!, 'execution source')\n if (utc(execution.recordedAt, 'execution recordedAt') < assignedAt) {\n throw new ValidationError('prospective canary: execution precedes assignment')\n }\n if (\n execution.turns !== null &&\n (!Number.isSafeInteger(execution.turns) || execution.turns < 0)\n ) {\n throw new ValidationError('prospective canary: turns must be a nonnegative integer')\n }\n if (\n execution.noExecutionSourceId !== null &&\n (execution.turns !== 0 || execution.providerCallIds.length !== 0)\n ) {\n throw new ValidationError(\n 'prospective canary: no-execution receipt contains turns or calls',\n )\n }\n }\n if (bill) {\n claimSource(bill.billingSourceId, 'billingSourceId')\n if (utc(bill.recordedAt, 'billing recordedAt') < assignedAt) {\n throw new ValidationError('prospective canary: billing precedes assignment')\n }\n if (bill.settlement === 'settled') {\n if (\n bill.billedCostUsd === null ||\n !Number.isFinite(bill.billedCostUsd) ||\n bill.billedCostUsd < 0\n ) {\n throw new ValidationError(\n 'prospective canary: settled billing needs nonnegative actual cost',\n )\n }\n } else if (bill.settlement !== 'unknown' || bill.billedCostUsd !== null) {\n throw new ValidationError('prospective canary: unknown billing cost must stay null')\n }\n if (\n execution &&\n uniqueIds(bill.providerCallIds, 'billing call').join('\\0') !==\n uniqueIds(execution.providerCallIds, 'execution call').join('\\0')\n ) {\n throw new ValidationError('prospective canary: provider-call billing join is incomplete')\n }\n }\n return {\n assignmentId: assignment.assignmentId,\n assignmentSourceId: assignment.assignmentSourceId,\n clusterId: assignment.clusterId,\n arm: assignment.arm,\n checkedOutcome: outcome?.checkedOutcome ?? null,\n outcomeSourceId: outcome?.outcomeSourceId ?? null,\n billedCostUsd: bill?.settlement === 'settled' ? bill.billedCostUsd : null,\n billingSourceId: bill?.billingSourceId ?? null,\n traceSourceId: execution?.traceSourceId ?? null,\n noExecutionSourceId: execution?.noExecutionSourceId ?? null,\n servedProfileDigest: execution?.servedProfileDigest ?? null,\n servedCodeRevisionDigest: execution?.servedCodeRevisionDigest ?? null,\n outcomeCheckerDigest: outcome?.outcomeCheckerDigest ?? null,\n turns: execution?.turns ?? null,\n }\n })\n}\n","/** Fixed-horizon, assignment-level decision for an unpaired served canary. */\n\nimport { ValidationError } from '../errors'\nimport { hashCanonical, LEDGER_HASH_PATTERN } from '../ledger-core/canonical'\nimport { studentTCdf, studentTQuantile } from '../math/student-t'\n\nexport type CanaryArm = 'control' | 'candidate'\n\n/** One assigned unit, including unsuccessful and unobserved executions. */\nexport interface CanaryAssignmentReceipt {\n assignmentId: string\n assignmentSourceId: string\n clusterId: string\n arm: CanaryArm\n}\n\nexport interface CanaryObservation extends CanaryAssignmentReceipt {\n /** Independently checked binary outcome. Null means measurement is unavailable. */\n checkedOutcome: 0 | 1 | null\n outcomeSourceId: string | null\n /** Billed cost, including measured zero. Null means billing is unavailable. */\n billedCostUsd: number | null\n billingSourceId: string | null\n /** Trace identity may be null for an assigned unit that never executed. */\n traceSourceId: string | null\n /** Required when no trace exists; identifies the independent no-execution record. */\n noExecutionSourceId: string | null\n /** Observed identities; null only when there was no execution or no checked outcome. */\n servedProfileDigest: string | null\n servedCodeRevisionDigest: string | null\n outcomeCheckerDigest: string | null\n turns: number | null\n}\n\n/** Seal this prospective protocol before the first eligible live assignment. */\nexport interface RandomizedCanaryRule {\n experimentId: string\n populationId: string\n eligibilityRuleDigest: string\n randomizationSourceId: string\n assignmentLedgerAuthorityId: string\n controlProfileDigest: string\n candidateProfileDigest: string\n servedCodeRevisionDigest: string\n outcomeCheckerDigest: string\n /** One externally reserved slot in a fixed family of confirmatory canaries. */\n confirmatoryFamilyId: string\n confirmatoryFamilySize: number\n confirmatoryIndex: number\n familyReservationSourceId: string\n assignmentUnit: 'customer' | 'session'\n /** Customer clustering also permits sessions of one customer in both arms. */\n clusterUnit: 'customer' | 'session'\n stoppingRule: 'fixed-time'\n /** No assignment after this UTC time enters the frozen cohort. */\n analysisCutoff: string\n /** Wait this long after cutoff for checked outcomes and billing to mature. */\n outcomeMaturityMs: number\n /** Candidate minus control success probability must exceed this margin. */\n minimumLift: number\n /** At least 40 total independent clusters and 20 represented in each arm. */\n minimumClusters: number\n}\n\n/** Post-cutoff evidence from the independently verified append-only assignment ledger. */\nexport interface CanaryCohortReceipt {\n protocolDigest: string\n assignmentRosterDigest: string\n assignmentCount: number\n assignmentLedgerSourceId: string\n assignmentLedgerTipDigest: string\n outcomeLedgerSourceId: string\n billingLedgerSourceId: string\n observationSnapshotDigest: string\n /** Exact preregistered cutoff + outcomeMaturityMs, not a selectable later look. */\n observationFrozenAt: string\n authorityId: string\n attestationSourceId: string\n closedAt: string\n attestedAt: string\n}\n\n/** Host verifies the independent witnesses and append-only ledger before inference. */\nexport type CanaryCohortVerifier = (\n receipt: CanaryCohortReceipt,\n protocol: SealedRandomizedCanaryRule,\n) =>\n | {\n verified: true\n authorityId: string\n protocolWitnessedBeforeTraffic: boolean\n familySlotReservedBeforeTraffic: boolean\n eligibilityAndDispositionVerified: boolean\n randomizationVerified: boolean\n rosterCompleteAtCutoff: boolean\n outcomeAndBillingSnapshotFrozen: boolean\n sourceJoinsVerified: boolean\n armIsolationVerified: boolean\n }\n | { verified: false; reason: string }\n\nexport interface SealedRandomizedCanaryRule {\n rule: RandomizedCanaryRule\n digest: string\n algo: 'sha256-rfc8785'\n}\n\nexport type CanaryRefusal =\n | 'missing-evidence'\n | 'missing-trace'\n | 'execution-drift'\n | 'insufficient-clusters'\n | 'dominant-cluster'\n | 'zero-variance'\n | null\n\nexport interface RandomizedCanaryDecision {\n registrationDigest: string\n cohortReceiptSourceId: string\n assignmentRosterDigest: string\n estimand: 'assignment-weighted-itt-risk-difference'\n method: 'cluster-robust-t'\n /** The fixed headline remains a nominal 95% interval. */\n confidence: 0.95\n /** Additional Bonferroni level: 1 - 0.05 / registered family size. */\n familyAdjustedConfidence: number\n assignments: number\n controlAssignments: number\n candidateAssignments: number\n clusters: number\n controlClusters: number\n candidateClusters: number\n coverage: Record<\n CanaryArm,\n {\n checkedOutcomes: number\n billedAssignments: number\n turnReceipts: number\n traceReceipts: number\n }\n >\n missingOutcomes: number\n missingBilling: number\n missingTurns: number\n missingTraces: number\n executionDrift: number\n controlSuccessRate: number | null\n candidateSuccessRate: number | null\n delta: number | null\n nominal95Interval: { low: number; high: number } | null\n headline95Pass: boolean\n familyAdjustedInterval: { low: number; high: number } | null\n familywisePass: boolean\n /** Two-sided zero-null p-value before the registered family correction. */\n unadjustedPValue: number | null\n controlBilledCostUsd: number | null\n candidateBilledCostUsd: number | null\n controlTurns: number | null\n candidateTurns: number | null\n refusal: CanaryRefusal\n /** Primary lift criterion only; product cost and latency gates remain external. */\n successCriterionMet: boolean\n}\n\nfunction nonEmpty(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {\n throw new ValidationError(`randomized canary: ${label} must be a nonempty trimmed string`)\n }\n}\n\nfunction validateAssignment(row: CanaryAssignmentReceipt, index: number): void {\n if (row === null || typeof row !== 'object' || Array.isArray(row)) {\n throw new ValidationError(`randomized canary: assignment ${index} must be an object`)\n }\n nonEmpty(row.assignmentId, `assignment ${index} id`)\n nonEmpty(row.assignmentSourceId, `assignment ${index} source id`)\n nonEmpty(row.clusterId, `assignment ${index} cluster id`)\n if (row.arm !== 'control' && row.arm !== 'candidate') {\n throw new ValidationError(\n `randomized canary: assignment ${index} arm must be control or candidate`,\n )\n }\n}\n\n/** Digest only assignment facts, so outcome and cost cannot change the roster. */\nexport function randomizedCanaryRosterDigest(rows: readonly CanaryAssignmentReceipt[]): string {\n const seen = new Set<string>()\n const seenSources = new Set<string>()\n const roster = rows.map((row, index) => {\n validateAssignment(row, index)\n if (seen.has(row.assignmentId)) {\n throw new ValidationError(`randomized canary: duplicate assignment id '${row.assignmentId}'`)\n }\n seen.add(row.assignmentId)\n if (seenSources.has(row.assignmentSourceId)) {\n throw new ValidationError(\n `randomized canary: duplicate assignment source id '${row.assignmentSourceId}'`,\n )\n }\n seenSources.add(row.assignmentSourceId)\n return {\n assignmentId: row.assignmentId,\n assignmentSourceId: row.assignmentSourceId,\n clusterId: row.clusterId,\n arm: row.arm,\n }\n })\n roster.sort((a, b) =>\n a.assignmentId < b.assignmentId ? -1 : a.assignmentId > b.assignmentId ? 1 : 0,\n )\n return hashCanonical(roster)\n}\n\n/** Commit to the one complete checked-outcome, trace, turn, and billing snapshot. */\nexport function randomizedCanaryObservationDigest(rows: readonly CanaryObservation[]): string {\n // The roster validation also prevents duplicate assignment IDs.\n randomizedCanaryRosterDigest(rows)\n const snapshot = rows.map((row) => ({\n assignmentId: row.assignmentId,\n checkedOutcome: row.checkedOutcome,\n outcomeSourceId: row.outcomeSourceId,\n billedCostUsd: row.billedCostUsd,\n billingSourceId: row.billingSourceId,\n traceSourceId: row.traceSourceId,\n noExecutionSourceId: row.noExecutionSourceId,\n servedProfileDigest: row.servedProfileDigest,\n servedCodeRevisionDigest: row.servedCodeRevisionDigest,\n outcomeCheckerDigest: row.outcomeCheckerDigest,\n turns: row.turns,\n }))\n snapshot.sort((a, b) =>\n a.assignmentId < b.assignmentId ? -1 : a.assignmentId > b.assignmentId ? 1 : 0,\n )\n return hashCanonical(snapshot)\n}\n\nfunction validateRule(rule: RandomizedCanaryRule): void {\n for (const field of [\n 'experimentId',\n 'populationId',\n 'eligibilityRuleDigest',\n 'randomizationSourceId',\n 'assignmentLedgerAuthorityId',\n 'controlProfileDigest',\n 'candidateProfileDigest',\n 'servedCodeRevisionDigest',\n 'outcomeCheckerDigest',\n 'confirmatoryFamilyId',\n 'familyReservationSourceId',\n 'analysisCutoff',\n ] as const)\n nonEmpty(rule[field], field)\n if (\n !Number.isSafeInteger(rule.confirmatoryFamilySize) ||\n rule.confirmatoryFamilySize < 1 ||\n rule.confirmatoryFamilySize > 1000\n ) {\n throw new ValidationError('randomized canary: confirmatoryFamilySize must be in [1, 1000]')\n }\n if (\n !Number.isSafeInteger(rule.confirmatoryIndex) ||\n rule.confirmatoryIndex < 1 ||\n rule.confirmatoryIndex > rule.confirmatoryFamilySize\n ) {\n throw new ValidationError(\n 'randomized canary: confirmatoryIndex must name a reserved family slot',\n )\n }\n if (rule.assignmentUnit !== 'customer' && rule.assignmentUnit !== 'session') {\n throw new ValidationError('randomized canary: assignmentUnit must be customer or session')\n }\n if (rule.clusterUnit !== 'customer' && rule.clusterUnit !== 'session') {\n throw new ValidationError('randomized canary: clusterUnit must be customer or session')\n }\n if (rule.assignmentUnit === 'customer' && rule.clusterUnit !== 'customer') {\n throw new ValidationError('randomized canary: customer assignments must cluster by customer')\n }\n if (rule.stoppingRule !== 'fixed-time') {\n throw new ValidationError('randomized canary: only fixed-time stopping is supported')\n }\n if (!Number.isFinite(Date.parse(rule.analysisCutoff)) || !rule.analysisCutoff.endsWith('Z')) {\n throw new ValidationError('randomized canary: analysisCutoff must be a UTC timestamp')\n }\n if (!Number.isSafeInteger(rule.outcomeMaturityMs) || rule.outcomeMaturityMs < 0) {\n throw new ValidationError('randomized canary: outcomeMaturityMs must be a nonnegative integer')\n }\n if (!Number.isFinite(rule.minimumLift) || rule.minimumLift < 0 || rule.minimumLift >= 1) {\n throw new ValidationError('randomized canary: minimumLift must be in [0, 1)')\n }\n if (!Number.isSafeInteger(rule.minimumClusters) || rule.minimumClusters < 40) {\n throw new ValidationError('randomized canary: minimumClusters must be at least 40')\n }\n}\n\n/** Seal the fixed decision controls; retaining this digest alone cannot prove preregistration time. */\nexport function sealRandomizedCanaryRule(rule: RandomizedCanaryRule): SealedRandomizedCanaryRule {\n validateRule(rule)\n const captured = structuredClone(rule)\n return { rule: captured, digest: hashCanonical(captured), algo: 'sha256-rfc8785' }\n}\n\n/** Apply one registered analysis to the entire frozen assignment roster. */\nexport function decideRandomizedCanary(\n sealed: SealedRandomizedCanaryRule,\n cohort: CanaryCohortReceipt,\n rows: readonly CanaryObservation[],\n verifyCohort: CanaryCohortVerifier,\n): RandomizedCanaryDecision {\n if (sealed.algo !== 'sha256-rfc8785') {\n throw new ValidationError('randomized canary: unsupported registration digest scheme')\n }\n validateRule(sealed.rule)\n if (hashCanonical(sealed.rule) !== sealed.digest) {\n throw new ValidationError('randomized canary: registration digest mismatch')\n }\n if (cohort === null || typeof cohort !== 'object' || Array.isArray(cohort)) {\n throw new ValidationError('randomized canary: independent cohort receipt is required')\n }\n for (const field of [\n 'assignmentLedgerSourceId',\n 'outcomeLedgerSourceId',\n 'billingLedgerSourceId',\n 'authorityId',\n 'attestationSourceId',\n 'closedAt',\n 'observationFrozenAt',\n 'attestedAt',\n ] as const) {\n nonEmpty(cohort[field], `cohort ${field}`)\n }\n if (cohort.protocolDigest !== sealed.digest) {\n throw new ValidationError('randomized canary: cohort protocol digest mismatch')\n }\n if (cohort.authorityId !== sealed.rule.assignmentLedgerAuthorityId) {\n throw new ValidationError('randomized canary: cohort authority differs from registered ledger')\n }\n for (const field of [\n 'assignmentRosterDigest',\n 'assignmentLedgerTipDigest',\n 'observationSnapshotDigest',\n ] as const) {\n if (!LEDGER_HASH_PATTERN.test(cohort[field])) {\n throw new ValidationError(`randomized canary: cohort ${field} must be a sha256 digest`)\n }\n }\n if (\n !Number.isSafeInteger(cohort.assignmentCount) ||\n cohort.assignmentCount < 1 ||\n rows.length !== cohort.assignmentCount\n ) {\n throw new ValidationError(\n 'randomized canary: assignment count differs from complete ledger receipt',\n )\n }\n if (randomizedCanaryRosterDigest(rows) !== cohort.assignmentRosterDigest) {\n throw new ValidationError('randomized canary: assignment roster digest mismatch')\n }\n if (randomizedCanaryObservationDigest(rows) !== cohort.observationSnapshotDigest) {\n throw new ValidationError('randomized canary: frozen observation snapshot digest mismatch')\n }\n const cutoff = Date.parse(sealed.rule.analysisCutoff)\n const closedAt = Date.parse(cohort.closedAt)\n const frozenAt = Date.parse(cohort.observationFrozenAt)\n const attestedAt = Date.parse(cohort.attestedAt)\n const expectedFreezeAt = cutoff + sealed.rule.outcomeMaturityMs\n if (\n !Number.isFinite(closedAt) ||\n closedAt < cutoff ||\n !cohort.closedAt.endsWith('Z') ||\n !Number.isFinite(frozenAt) ||\n frozenAt !== expectedFreezeAt ||\n closedAt > frozenAt ||\n !cohort.observationFrozenAt.endsWith('Z') ||\n !Number.isFinite(attestedAt) ||\n attestedAt < frozenAt ||\n !cohort.attestedAt.endsWith('Z')\n ) {\n throw new ValidationError(\n 'randomized canary: ledger closure or frozen observation time differs from registered cutoffs',\n )\n }\n if (typeof verifyCohort !== 'function') {\n throw new ValidationError('randomized canary: independent cohort verifier is required')\n }\n const verification = verifyCohort(cohort, sealed)\n if (\n verification?.verified !== true ||\n verification.authorityId !== cohort.authorityId ||\n verification.protocolWitnessedBeforeTraffic !== true ||\n verification.familySlotReservedBeforeTraffic !== true ||\n verification.eligibilityAndDispositionVerified !== true ||\n verification.randomizationVerified !== true ||\n verification.rosterCompleteAtCutoff !== true ||\n verification.outcomeAndBillingSnapshotFrozen !== true ||\n verification.sourceJoinsVerified !== true ||\n verification.armIsolationVerified !== true\n ) {\n throw new ValidationError(\n `randomized canary: cohort attestation or completeness unverified${verification?.verified === false ? `: ${verification.reason}` : ''}`,\n )\n }\n\n const clusters = new Map<string, CanaryObservation[]>()\n const arms = { control: [] as CanaryObservation[], candidate: [] as CanaryObservation[] }\n let missingOutcomes = 0\n let missingBilling = 0\n let missingTurns = 0\n let missingTraces = 0\n let executionDrift = 0\n for (const [index, row] of rows.entries()) {\n if (row.checkedOutcome !== 0 && row.checkedOutcome !== 1 && row.checkedOutcome !== null) {\n throw new ValidationError(\n `randomized canary: assignment ${index} outcome must be 0, 1, or null`,\n )\n }\n if (row.checkedOutcome === null) missingOutcomes++\n if (row.outcomeSourceId === null) {\n if (row.checkedOutcome !== null)\n throw new ValidationError(\n `randomized canary: assignment ${index} has an outcome without its source`,\n )\n } else nonEmpty(row.outcomeSourceId, `assignment ${index} outcome source id`)\n if (row.billedCostUsd === null) missingBilling++\n else if (!Number.isFinite(row.billedCostUsd) || row.billedCostUsd < 0) {\n throw new ValidationError(\n `randomized canary: assignment ${index} billed cost must be nonnegative`,\n )\n }\n if (row.billingSourceId === null) {\n if (row.billedCostUsd !== null)\n throw new ValidationError(\n `randomized canary: assignment ${index} has billed cost without its source`,\n )\n } else nonEmpty(row.billingSourceId, `assignment ${index} billing source id`)\n if (row.turns === null) missingTurns++\n else if (!Number.isSafeInteger(row.turns) || row.turns < 0) {\n throw new ValidationError(\n `randomized canary: assignment ${index} turns must be a nonnegative integer`,\n )\n }\n if (row.traceSourceId !== null)\n nonEmpty(row.traceSourceId, `assignment ${index} trace source id`)\n if (row.noExecutionSourceId !== null)\n nonEmpty(row.noExecutionSourceId, `assignment ${index} no-execution source id`)\n if (row.traceSourceId !== null && row.noExecutionSourceId !== null) {\n throw new ValidationError(\n `randomized canary: assignment ${index} has conflicting trace and no-execution receipts`,\n )\n }\n const noExecution =\n row.noExecutionSourceId !== null &&\n row.turns === 0 &&\n row.billedCostUsd === 0 &&\n row.checkedOutcome === 0\n if (row.traceSourceId === null && !noExecution) missingTraces++\n for (const field of [\n 'servedProfileDigest',\n 'servedCodeRevisionDigest',\n 'outcomeCheckerDigest',\n ] as const) {\n if (row[field] !== null) nonEmpty(row[field], `assignment ${index} ${field}`)\n }\n const expectedProfile =\n row.arm === 'control' ? sealed.rule.controlProfileDigest : sealed.rule.candidateProfileDigest\n if (\n (row.traceSourceId !== null &&\n (row.servedProfileDigest !== expectedProfile ||\n row.servedCodeRevisionDigest !== sealed.rule.servedCodeRevisionDigest)) ||\n (row.checkedOutcome !== null &&\n row.outcomeCheckerDigest !== sealed.rule.outcomeCheckerDigest) ||\n (noExecution && (row.servedProfileDigest !== null || row.servedCodeRevisionDigest !== null))\n ) {\n executionDrift++\n }\n arms[row.arm].push(row)\n const bucket = clusters.get(row.clusterId) ?? []\n bucket.push(row)\n clusters.set(row.clusterId, bucket)\n }\n const controlClusters = [...clusters.values()].filter((bucket) =>\n bucket.some((r) => r.arm === 'control'),\n ).length\n const candidateClusters = [...clusters.values()].filter((bucket) =>\n bucket.some((r) => r.arm === 'candidate'),\n ).length\n if (sealed.rule.assignmentUnit === sealed.rule.clusterUnit) {\n for (const [clusterId, bucket] of clusters) {\n if (bucket.length !== 1) {\n throw new ValidationError(\n `randomized canary: ${sealed.rule.assignmentUnit} cluster '${clusterId}' has multiple assignments`,\n )\n }\n }\n }\n const coverage = (arm: CanaryArm) => ({\n checkedOutcomes: arms[arm].filter((row) => row.checkedOutcome !== null).length,\n billedAssignments: arms[arm].filter((row) => row.billedCostUsd !== null).length,\n turnReceipts: arms[arm].filter((row) => row.turns !== null).length,\n traceReceipts: arms[arm].filter((row) => row.traceSourceId !== null).length,\n })\n const armCoverage = { control: coverage('control'), candidate: coverage('candidate') }\n const sum = (arm: CanaryArm, field: 'checkedOutcome' | 'billedCostUsd' | 'turns'): number =>\n arms[arm].reduce((total, row) => total + (row[field] ?? 0), 0)\n const n0 = arms.control.length\n const n1 = arms.candidate.length\n const outcomesComplete = missingOutcomes === 0 && n0 > 0 && n1 > 0\n const p0 = outcomesComplete ? sum('control', 'checkedOutcome') / n0 : null\n const p1 = outcomesComplete ? sum('candidate', 'checkedOutcome') / n1 : null\n const delta = p0 === null || p1 === null ? null : p1 - p0\n const result: RandomizedCanaryDecision = {\n registrationDigest: sealed.digest,\n cohortReceiptSourceId: cohort.attestationSourceId,\n assignmentRosterDigest: cohort.assignmentRosterDigest,\n estimand: 'assignment-weighted-itt-risk-difference',\n method: 'cluster-robust-t',\n confidence: 0.95,\n familyAdjustedConfidence: 1 - 0.05 / sealed.rule.confirmatoryFamilySize,\n assignments: rows.length,\n controlAssignments: n0,\n candidateAssignments: n1,\n clusters: clusters.size,\n controlClusters,\n candidateClusters,\n coverage: armCoverage,\n missingOutcomes,\n missingBilling,\n missingTurns,\n missingTraces,\n executionDrift,\n controlSuccessRate: p0,\n candidateSuccessRate: p1,\n delta,\n nominal95Interval: null,\n headline95Pass: false,\n familyAdjustedInterval: null,\n familywisePass: false,\n unadjustedPValue: null,\n controlBilledCostUsd:\n armCoverage.control.billedAssignments === n0 ? sum('control', 'billedCostUsd') : null,\n candidateBilledCostUsd:\n armCoverage.candidate.billedAssignments === n1 ? sum('candidate', 'billedCostUsd') : null,\n controlTurns: armCoverage.control.turnReceipts === n0 ? sum('control', 'turns') : null,\n candidateTurns: armCoverage.candidate.turnReceipts === n1 ? sum('candidate', 'turns') : null,\n refusal: null,\n successCriterionMet: false,\n }\n if (missingOutcomes > 0 || missingBilling > 0 || missingTurns > 0 || n0 === 0 || n1 === 0) {\n result.refusal = 'missing-evidence'\n return result\n }\n if (missingTraces > 0) {\n result.refusal = 'missing-trace'\n return result\n }\n if (executionDrift > 0) {\n result.refusal = 'execution-drift'\n return result\n }\n if (\n clusters.size < sealed.rule.minimumClusters ||\n controlClusters < 20 ||\n candidateClusters < 20\n ) {\n result.refusal = 'insufficient-clusters'\n return result\n }\n // A single customer may own many assigned sessions. One dominant customer\n // defeats the many-independent-clusters approximation even when G is large.\n for (const bucket of clusters.values()) {\n if (\n bucket.filter((r) => r.arm === 'control').length / n0 > 0.1 ||\n bucket.filter((r) => r.arm === 'candidate').length / n1 > 0.1\n ) {\n result.refusal = 'dominant-cluster'\n return result\n }\n }\n // OLS risk difference with customer/session cluster sandwich scores. A\n // cluster may contain both arms; its covariance contribution stays intact.\n const scores = [...clusters.values()].map((bucket) =>\n bucket.reduce(\n (score, row) =>\n score +\n (row.arm === 'candidate'\n ? (row.checkedOutcome! - p1!) / n1\n : -(row.checkedOutcome! - p0!) / n0),\n 0,\n ),\n )\n const G = clusters.size\n const variance =\n (((G / (G - 1)) * (rows.length - 1)) / (rows.length - 2)) *\n scores.reduce((total, score) => total + score * score, 0)\n if (!Number.isFinite(variance) || variance <= 0) {\n result.refusal = 'zero-variance'\n return result\n }\n const se = Math.sqrt(variance)\n const t = delta! / se\n const critical95 = studentTQuantile(0.975, G - 1)\n const familyCritical = studentTQuantile(1 - (1 - result.familyAdjustedConfidence) / 2, G - 1)\n result.nominal95Interval = { low: delta! - critical95 * se, high: delta! + critical95 * se }\n result.familyAdjustedInterval = {\n low: delta! - familyCritical * se,\n high: delta! + familyCritical * se,\n }\n result.unadjustedPValue = Math.min(1, 2 * (1 - studentTCdf(Math.abs(t), G - 1)))\n result.headline95Pass = result.nominal95Interval.low > 0\n result.familywisePass = result.familyAdjustedInterval.low > sealed.rule.minimumLift\n result.successCriterionMet = result.headline95Pass && result.familywisePass\n return result\n}\n"],"mappings":"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"}