@tangle-network/agent-eval 0.221.8 → 0.222.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 (579) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/adapters/http.d.ts +3 -5
  3. package/dist/adapters/http.d.ts.map +1 -1
  4. package/dist/adapters/http.js +1 -2
  5. package/dist/{adversarial-smnADNFS.d.ts → adversarial-DnQQFqTR.d.ts} +1 -3
  6. package/dist/adversarial-DnQQFqTR.d.ts.map +1 -0
  7. package/dist/{agent-profile-CNmwfaqq.d.ts → agent-profile-CoD1Dotf.d.ts} +4 -10
  8. package/dist/agent-profile-CoD1Dotf.d.ts.map +1 -0
  9. package/dist/agent-profile-Dngk3LZ0.js +153 -0
  10. package/dist/agent-profile-Dngk3LZ0.js.map +1 -0
  11. package/dist/{agent-profile-cell-BcpFbNd5.d.ts → agent-profile-cell-3kYxUsK2.d.ts} +3 -5
  12. package/dist/agent-profile-cell-3kYxUsK2.d.ts.map +1 -0
  13. package/dist/{agent-profile-cell-B1V1gUZs.js → agent-profile-cell-CT5JYueM.js} +5 -7
  14. package/dist/{agent-profile-cell-B1V1gUZs.js.map → agent-profile-cell-CT5JYueM.js.map} +1 -1
  15. package/dist/{agreement-irr-BhAqjluA.js → agreement-irr-BTjDN0i6.js} +4 -5
  16. package/dist/{agreement-irr-BhAqjluA.js.map → agreement-irr-BTjDN0i6.js.map} +1 -1
  17. package/dist/analyst/index.d.ts +95 -159
  18. package/dist/analyst/index.d.ts.map +1 -1
  19. package/dist/analyst/index.js +28 -39
  20. package/dist/analyst/index.js.map +1 -1
  21. package/dist/{analyze-runs-DfX6dHP0.d.ts → analyze-runs-C-pP1sK9.d.ts} +7 -13
  22. package/dist/analyze-runs-C-pP1sK9.d.ts.map +1 -0
  23. package/dist/{analyze-runs-CHmsykNJ.js → analyze-runs-CTheASYV.js} +23 -32
  24. package/dist/{analyze-runs-CHmsykNJ.js.map → analyze-runs-CTheASYV.js.map} +1 -1
  25. package/dist/{attribute-vocabulary-CcXqHODT.d.ts → attribute-vocabulary-5oo8ykIx.d.ts} +2 -4
  26. package/dist/attribute-vocabulary-5oo8ykIx.d.ts.map +1 -0
  27. package/dist/authenticity/index.d.ts +0 -2
  28. package/dist/authenticity/index.d.ts.map +1 -1
  29. package/dist/authenticity/index.js +1 -2
  30. package/dist/{benchmark-command-Cnjfo0Zh.js → benchmark-command-jYWR2gya.js} +61 -94
  31. package/dist/benchmark-command-jYWR2gya.js.map +1 -0
  32. package/dist/benchmarks/index.d.ts +5 -15
  33. package/dist/benchmarks/index.d.ts.map +1 -1
  34. package/dist/benchmarks/index.js +27 -38
  35. package/dist/benchmarks/index.js.map +1 -1
  36. package/dist/{bounded-process-Cj9YjXbE.js → bounded-process-BZrWXIKW.js} +2 -3
  37. package/dist/{bounded-process-Cj9YjXbE.js.map → bounded-process-BZrWXIKW.js.map} +1 -1
  38. package/dist/builder-eval/index.d.ts +5 -14
  39. package/dist/builder-eval/index.d.ts.map +1 -1
  40. package/dist/builder-eval/index.js +11 -17
  41. package/dist/builder-eval/index.js.map +1 -1
  42. package/dist/{calibration-CTwxpJ-t.js → calibration-6usfVYYo.js} +4 -5
  43. package/dist/{calibration-CTwxpJ-t.js.map → calibration-6usfVYYo.js.map} +1 -1
  44. package/dist/campaign/index.d.ts +9 -9
  45. package/dist/campaign/index.js +15 -14
  46. package/dist/{campaign-uddTlFg5.js → campaign-ddr1N3yD.js} +61 -58
  47. package/dist/campaign-ddr1N3yD.js.map +1 -0
  48. package/dist/{campaign-evidence-DunzcJGv.js → campaign-evidence-DN8rWuBj.js} +20 -322
  49. package/dist/campaign-evidence-DN8rWuBj.js.map +1 -0
  50. package/dist/{canonical-Dq2hOQ8L.js → canonical-CicJlINA.js} +3 -4
  51. package/dist/{canonical-Dq2hOQ8L.js.map → canonical-CicJlINA.js.map} +1 -1
  52. package/dist/{canonical-CFpojCN5.d.ts → canonical-gLeHiqzd.d.ts} +2 -4
  53. package/dist/canonical-gLeHiqzd.d.ts.map +1 -0
  54. package/dist/{cell-spend-DEWR3nj-.js → cell-spend-zxmzg4GH.js} +3 -4
  55. package/dist/{cell-spend-DEWR3nj-.js.map → cell-spend-zxmzg4GH.js.map} +1 -1
  56. package/dist/{chat-client-BNATB3rJ.js → chat-client-CO3uB33i.js} +3 -4
  57. package/dist/{chat-client-BNATB3rJ.js.map → chat-client-CO3uB33i.js.map} +1 -1
  58. package/dist/{chat-json-call-BzWYp18J.js → chat-json-call-8yUv4LFO.js} +4 -5
  59. package/dist/{chat-json-call-BzWYp18J.js.map → chat-json-call-8yUv4LFO.js.map} +1 -1
  60. package/dist/{claim-BPVuyHuy.js → claim-Dod_mjk3.js} +5 -6
  61. package/dist/{claim-BPVuyHuy.js.map → claim-Dod_mjk3.js.map} +1 -1
  62. package/dist/cli.js +179 -23
  63. package/dist/cli.js.map +1 -1
  64. package/dist/{client-hwo3cJjR.d.ts → client-BIFwUg7I.d.ts} +6 -12
  65. package/dist/client-BIFwUg7I.d.ts.map +1 -0
  66. package/dist/{cluster-bootstrap-DEwwhl0C.js → cluster-bootstrap-SbaeM44s.js} +4 -5
  67. package/dist/{cluster-bootstrap-DEwwhl0C.js.map → cluster-bootstrap-SbaeM44s.js.map} +1 -1
  68. package/dist/completion-verifier-7KEfroqx.d.ts +168 -0
  69. package/dist/completion-verifier-7KEfroqx.d.ts.map +1 -0
  70. package/dist/{completion-verifier-asaV1nSj.js → completion-verifier-rqbMh5-4.js} +9 -160
  71. package/dist/completion-verifier-rqbMh5-4.js.map +1 -0
  72. package/dist/contract/index.d.ts +13 -13
  73. package/dist/contract/index.js +41 -60
  74. package/dist/contract/index.js.map +1 -1
  75. package/dist/{cost-ledger-BGZB6yY2.js → cost-ledger-CS8R3IZj.js} +10 -17
  76. package/dist/{cost-ledger-BGZB6yY2.js.map → cost-ledger-CS8R3IZj.js.map} +1 -1
  77. package/dist/{cost-ledger-C1W3ICmP.d.ts → cost-ledger-Czro9wmo.d.ts} +1 -5
  78. package/dist/cost-ledger-Czro9wmo.d.ts.map +1 -0
  79. package/dist/{dataset-DQqhOCPt.d.ts → dataset-DThC1S6G.d.ts} +1 -3
  80. package/dist/dataset-DThC1S6G.d.ts.map +1 -0
  81. package/dist/{decision-point-0nJubuoM.js → decision-point-lhMgODOR.js} +14 -18
  82. package/dist/{decision-point-0nJubuoM.js.map → decision-point-lhMgODOR.js.map} +1 -1
  83. package/dist/{deep-freeze-CurcOQg3.js → deep-freeze-CK8-2W7p.js} +2 -3
  84. package/dist/{deep-freeze-CurcOQg3.js.map → deep-freeze-CK8-2W7p.js.map} +1 -1
  85. package/dist/{default-registry-CLG5YqGS.d.ts → default-registry-B1DstPYg.d.ts} +53 -61
  86. package/dist/default-registry-B1DstPYg.d.ts.map +1 -0
  87. package/dist/{default-registry-BBTDgkDM.js → default-registry-C1tPEjZ4.js} +29 -45
  88. package/dist/{default-registry-BBTDgkDM.js.map → default-registry-C1tPEjZ4.js.map} +1 -1
  89. package/dist/{define-agent-eval-CCbT7Kfr.js → define-agent-eval-BLoP4Lf9.js} +15 -18
  90. package/dist/{define-agent-eval-CCbT7Kfr.js.map → define-agent-eval-BLoP4Lf9.js.map} +1 -1
  91. package/dist/{define-agent-eval-JKt3gMQr.d.ts → define-agent-eval-CAffiFbN.d.ts} +19 -27
  92. package/dist/define-agent-eval-CAffiFbN.d.ts.map +1 -0
  93. package/dist/{descriptive-CVNy48rR.js → descriptive-cPwITVfy.js} +30 -8
  94. package/dist/descriptive-cPwITVfy.js.map +1 -0
  95. package/dist/diagnosis/index.d.ts +5 -15
  96. package/dist/diagnosis/index.d.ts.map +1 -1
  97. package/dist/diagnosis/index.js +13 -19
  98. package/dist/diagnosis/index.js.map +1 -1
  99. package/dist/{dspy-rlm-engine-DN1p_5jx.js → dspy-rlm-engine-jDiWkul6.js} +7 -10
  100. package/dist/{dspy-rlm-engine-DN1p_5jx.js.map → dspy-rlm-engine-jDiWkul6.js.map} +1 -1
  101. package/dist/{emitter-DbMXUIVP.js → emitter-DhQ65mza.js} +3 -4
  102. package/dist/{emitter-DbMXUIVP.js.map → emitter-DhQ65mza.js.map} +1 -1
  103. package/dist/{emitter-DABYYTcH.d.ts → emitter-mAXC5PSN.d.ts} +3 -5
  104. package/dist/emitter-mAXC5PSN.d.ts.map +1 -0
  105. package/dist/{engine-dtRVeuQs.d.ts → engine-CaHaCc3W.d.ts} +10 -18
  106. package/dist/engine-CaHaCc3W.d.ts.map +1 -0
  107. package/dist/{equal-terms-DbPGcVtI.js → equal-terms-K11VHmR3.js} +3 -4
  108. package/dist/{equal-terms-DbPGcVtI.js.map → equal-terms-K11VHmR3.js.map} +1 -1
  109. package/dist/{errors-BcOs5MKW.js → errors-DeEEV9Vx.js} +2 -3
  110. package/dist/{errors-BcOs5MKW.js.map → errors-DeEEV9Vx.js.map} +1 -1
  111. package/dist/{errors-DEE6u6ot.d.ts → errors-E9I2hldP.d.ts} +1 -3
  112. package/dist/errors-E9I2hldP.d.ts.map +1 -0
  113. package/dist/{eval-campaign-DoX5vz3E.js → eval-campaign-Cgixrvf7.js} +8 -9
  114. package/dist/{eval-campaign-DoX5vz3E.js.map → eval-campaign-Cgixrvf7.js.map} +1 -1
  115. package/dist/{evaluation-wdGyZ7jV.js → evaluation-B8H3GYej.js} +4 -6
  116. package/dist/{evaluation-wdGyZ7jV.js.map → evaluation-B8H3GYej.js.map} +1 -1
  117. package/dist/{evaluation-DblGquCB.d.ts → evaluation-BPqUvZ66.d.ts} +4 -6
  118. package/dist/evaluation-BPqUvZ66.d.ts.map +1 -0
  119. package/dist/evaluation.d.ts +1 -1
  120. package/dist/evaluation.js +1 -2
  121. package/dist/{exact-types-Do63KoKn.d.ts → exact-types-D98BKpxo.d.ts} +8 -10
  122. package/dist/exact-types-D98BKpxo.d.ts.map +1 -0
  123. package/dist/{exec-CpbtOXVt.js → exec-C0_AkLUv.js} +3 -5
  124. package/dist/{exec-CpbtOXVt.js.map → exec-C0_AkLUv.js.map} +1 -1
  125. package/dist/{execution-tracks-CpgFPpS5.js → execution-tracks-DaDXYwAq.js} +2 -3
  126. package/dist/{execution-tracks-CpgFPpS5.js.map → execution-tracks-DaDXYwAq.js.map} +1 -1
  127. package/dist/experiment/index.d.ts +9 -37
  128. package/dist/experiment/index.d.ts.map +1 -1
  129. package/dist/experiment/index.js +29 -40
  130. package/dist/experiment/index.js.map +1 -1
  131. package/dist/{exporters-Dk3oEbK_.d.ts → exporters-B5Ze_RKh.d.ts} +4 -4
  132. package/dist/exporters-B5Ze_RKh.d.ts.map +1 -0
  133. package/dist/{exporters-DWvM16LE.js → exporters-ByLcILYU.js} +23 -5
  134. package/dist/exporters-ByLcILYU.js.map +1 -0
  135. package/dist/{external-optimizer-process-DEzJ2CGX.js → external-optimizer-process-BRVmaDFe.js} +5 -6
  136. package/dist/{external-optimizer-process-DEzJ2CGX.js.map → external-optimizer-process-BRVmaDFe.js.map} +1 -1
  137. package/dist/{external-optimizer-subprocess-B_ukPtRD.js → external-optimizer-subprocess-U616hV_l.js} +24 -37
  138. package/dist/{external-optimizer-subprocess-B_ukPtRD.js.map → external-optimizer-subprocess-U616hV_l.js.map} +1 -1
  139. package/dist/{extract-usage-BZLU01kR.js → extract-usage-ISFqhfDz.js} +2 -3
  140. package/dist/{extract-usage-BZLU01kR.js.map → extract-usage-ISFqhfDz.js.map} +1 -1
  141. package/dist/{failure-cluster-DN0t63Z0.d.ts → failure-cluster-DOoa7CBg.d.ts} +3 -7
  142. package/dist/failure-cluster-DOoa7CBg.d.ts.map +1 -0
  143. package/dist/{failure-taxonomy-Bx5oWqaW.js → failure-taxonomy-9eQfXKoW.js} +2 -3
  144. package/dist/{failure-taxonomy-Bx5oWqaW.js.map → failure-taxonomy-9eQfXKoW.js.map} +1 -1
  145. package/dist/{feedback-trajectory-CYVJXolG.d.ts → feedback-trajectory-SBGncrCP.d.ts} +7 -13
  146. package/dist/feedback-trajectory-SBGncrCP.d.ts.map +1 -0
  147. package/dist/{finding-composition-8n0fFgVI.js → finding-composition-DlvE1Qul.js} +4 -6
  148. package/dist/{finding-composition-8n0fFgVI.js.map → finding-composition-DlvE1Qul.js.map} +1 -1
  149. package/dist/{findings-store-Bg4sdS-e.js → findings-store-B75Dspaq.js} +11 -14
  150. package/dist/{findings-store-Bg4sdS-e.js.map → findings-store-B75Dspaq.js.map} +1 -1
  151. package/dist/fuzz.d.ts +3 -17
  152. package/dist/fuzz.d.ts.map +1 -1
  153. package/dist/fuzz.js +30 -29
  154. package/dist/fuzz.js.map +1 -1
  155. package/dist/{hf-dataset-CKxIJQba.js → hf-dataset-DPVQXW5n.js} +362 -21
  156. package/dist/hf-dataset-DPVQXW5n.js.map +1 -0
  157. package/dist/hosted/index.d.ts +2 -6
  158. package/dist/hosted/index.d.ts.map +1 -1
  159. package/dist/hosted/index.js +1 -2
  160. package/dist/{index-CalAsXMR.d.ts → index-B1Bm9oJA.d.ts} +3 -15
  161. package/dist/index-B1Bm9oJA.d.ts.map +1 -0
  162. package/dist/{index-CdEVr8-O.d.ts → index-B7v2QHlD.d.ts} +24 -299
  163. package/dist/index-B7v2QHlD.d.ts.map +1 -0
  164. package/dist/{index-CTIRz-AB.d.ts → index-CUjeTDPv.d.ts} +14 -36
  165. package/dist/index-CUjeTDPv.d.ts.map +1 -0
  166. package/dist/{index-CfJULcW5.d.ts → index-DAk2quYu.d.ts} +18 -38
  167. package/dist/index-DAk2quYu.d.ts.map +1 -0
  168. package/dist/{index-D7fmC-1K.d.ts → index-DUn0GNiZ.d.ts} +183 -36
  169. package/dist/index-DUn0GNiZ.d.ts.map +1 -0
  170. package/dist/{index-CHxwfW5g.d.ts → index-DwUGehqX.d.ts} +3 -9
  171. package/dist/index-DwUGehqX.d.ts.map +1 -0
  172. package/dist/{index-jnuFLxOs.d.ts → index-aDPVYBIM.d.ts} +11 -39
  173. package/dist/index-aDPVYBIM.d.ts.map +1 -0
  174. package/dist/index.d.ts +55 -188
  175. package/dist/index.d.ts.map +1 -1
  176. package/dist/index.js +122 -195
  177. package/dist/index.js.map +1 -1
  178. package/dist/{integrity-D-s2iHiT.js → integrity-B1V6klyO.js} +12 -363
  179. package/dist/integrity-B1V6klyO.js.map +1 -0
  180. package/dist/{integrity-D9lBnv_K.d.ts → integrity-BAdVzT8u.d.ts} +4 -6
  181. package/dist/integrity-BAdVzT8u.d.ts.map +1 -0
  182. package/dist/{integrity-W4CADcFc.js → integrity-DOHt1mwU.js} +3 -4
  183. package/dist/{integrity-W4CADcFc.js.map → integrity-DOHt1mwU.js.map} +1 -1
  184. package/dist/{internal-BTK91Bqt.js → internal-v6XfOeJW.js} +6 -8
  185. package/dist/{internal-BTK91Bqt.js.map → internal-v6XfOeJW.js.map} +1 -1
  186. package/dist/{interval-Dq9gt7jx.js → interval-Bd2f4CRT.js} +6 -8
  187. package/dist/{interval-Dq9gt7jx.js.map → interval-Bd2f4CRT.js.map} +1 -1
  188. package/dist/{interval-ohuOJurX.d.ts → interval-CWyxqDpE.d.ts} +1 -5
  189. package/dist/interval-CWyxqDpE.d.ts.map +1 -0
  190. package/dist/{journal-C7om8Gum.js → journal-C1uLJi0w.js} +115 -121
  191. package/dist/{journal-C7om8Gum.js.map → journal-C1uLJi0w.js.map} +1 -1
  192. package/dist/{json-BhdsJaOQ.js → json-DtvZNAU9.js} +4 -6
  193. package/dist/{json-BhdsJaOQ.js.map → json-DtvZNAU9.js.map} +1 -1
  194. package/dist/json-recovery-DK4MDm5r.js +296 -0
  195. package/dist/json-recovery-DK4MDm5r.js.map +1 -0
  196. package/dist/{judge-calibration-BkXMIWA4.js → judge-calibration-DGqlfWW8.js} +5 -6
  197. package/dist/{judge-calibration-BkXMIWA4.js.map → judge-calibration-DGqlfWW8.js.map} +1 -1
  198. package/dist/{judge-calibration-DFtEMlde.d.ts → judge-calibration-DnrbQaXI.d.ts} +1 -3
  199. package/dist/judge-calibration-DnrbQaXI.d.ts.map +1 -0
  200. package/dist/{judge-gate-BVvmP00P.js → judge-gate-C2BCOt-M.js} +8 -12
  201. package/dist/{judge-gate-BVvmP00P.js.map → judge-gate-C2BCOt-M.js.map} +1 -1
  202. package/dist/judges-BLxg5p8E.js +20 -0
  203. package/dist/judges-BLxg5p8E.js.map +1 -0
  204. package/dist/{kind-factory-Dl0PmNQL.js → kind-factory-VKysp1ds.js} +23 -39
  205. package/dist/{kind-factory-Dl0PmNQL.js.map → kind-factory-VKysp1ds.js.map} +1 -1
  206. package/dist/ledger-core/index.d.ts +2 -2
  207. package/dist/ledger-core/index.js +3 -3
  208. package/dist/ledger-core/lock-holder.d.ts +1 -1
  209. package/dist/ledger-core/lock-holder.js +1 -2
  210. package/dist/{ledger-core-CAxUdDk0.js → ledger-core-CfT-FzPf.js} +5 -6
  211. package/dist/{ledger-core-CAxUdDk0.js.map → ledger-core-CfT-FzPf.js.map} +1 -1
  212. package/dist/{llm-client-b1ysZVIU.js → llm-client-kJ9EOqjt.js} +22 -30
  213. package/dist/{llm-client-b1ysZVIU.js.map → llm-client-kJ9EOqjt.js.map} +1 -1
  214. package/dist/{llm-judge-Cybq29bL.js → llm-judge-cgbhTKQp.js} +108 -164
  215. package/dist/llm-judge-cgbhTKQp.js.map +1 -0
  216. package/dist/{lock-holder-DaJbfpci.d.ts → lock-holder-DoxlZFkQ.d.ts} +1 -3
  217. package/dist/lock-holder-DoxlZFkQ.d.ts.map +1 -0
  218. package/dist/matrix/index.d.ts +3 -3
  219. package/dist/matrix/index.js +2 -2
  220. package/dist/{matrix-DtkZLD_3.d.ts → matrix-CBUzIZs4.d.ts} +4 -12
  221. package/dist/matrix-CBUzIZs4.d.ts.map +1 -0
  222. package/dist/{matrix-B8l-Nsxd.js → matrix-CgpX8wdm.js} +8 -13
  223. package/dist/matrix-CgpX8wdm.js.map +1 -0
  224. package/dist/{mean-BbA_JCzW.js → mean-CdDYG-us.js} +6 -9
  225. package/dist/{mean-BbA_JCzW.js.map → mean-CdDYG-us.js.map} +1 -1
  226. package/dist/meta-eval/index.d.ts +3 -3
  227. package/dist/meta-eval/index.js +17 -21
  228. package/dist/meta-eval/index.js.map +1 -1
  229. package/dist/{metrics-BKaPBtIG.js → metrics-DNCAUtuB.js} +2 -3
  230. package/dist/{metrics-BKaPBtIG.js.map → metrics-DNCAUtuB.js.map} +1 -1
  231. package/dist/{mint-CbdwjTPW.js → mint-D9ZysYtY.js} +7 -8
  232. package/dist/{mint-CbdwjTPW.js.map → mint-D9ZysYtY.js.map} +1 -1
  233. package/dist/{multi-layer-verifier-DEgMUk6v.d.ts → multi-layer-verifier-lM4aVN78.d.ts} +2 -4
  234. package/dist/multi-layer-verifier-lM4aVN78.d.ts.map +1 -0
  235. package/dist/{multiplicity-Sg0U7h8j.js → multiplicity-DAd4xaDC.js} +3 -4
  236. package/dist/{multiplicity-Sg0U7h8j.js.map → multiplicity-DAd4xaDC.js.map} +1 -1
  237. package/dist/{multiplicity-DIWHvysC.d.ts → multiplicity-D_SEsc5j.d.ts} +1 -3
  238. package/dist/multiplicity-D_SEsc5j.d.ts.map +1 -0
  239. package/dist/multishot/golden/index.d.ts +1 -17
  240. package/dist/multishot/golden/index.d.ts.map +1 -1
  241. package/dist/multishot/golden/index.js +10 -17
  242. package/dist/multishot/golden/index.js.map +1 -1
  243. package/dist/multishot/index.d.ts +2 -10
  244. package/dist/multishot/index.d.ts.map +1 -1
  245. package/dist/multishot/index.js +11 -18
  246. package/dist/multishot/index.js.map +1 -1
  247. package/dist/{nonnegative-number-DvdMxg_f.js → nonnegative-number-lEYbOsuh.js} +2 -3
  248. package/dist/{nonnegative-number-DvdMxg_f.js.map → nonnegative-number-lEYbOsuh.js.map} +1 -1
  249. package/dist/openapi.json +1 -1
  250. package/dist/{otel-spans-64hmQqON.js → otel-spans-BsGzTWIK.js} +5 -6
  251. package/dist/{otel-spans-64hmQqON.js.map → otel-spans-BsGzTWIK.js.map} +1 -1
  252. package/dist/{otlp-attributes-D9ptWaIJ.js → otlp-attributes-Boeb7gtH.js} +2 -3
  253. package/dist/{otlp-attributes-D9ptWaIJ.js.map → otlp-attributes-Boeb7gtH.js.map} +1 -1
  254. package/dist/{outcome-observations-FLmRpgYa.js → outcome-observations-D4snOtUb.js} +4 -5
  255. package/dist/{outcome-observations-FLmRpgYa.js.map → outcome-observations-D4snOtUb.js.map} +1 -1
  256. package/dist/{outcome-store-DUcMj-3D.js → outcome-store-TarrcfHG.js} +2 -3
  257. package/dist/{outcome-store-DUcMj-3D.js.map → outcome-store-TarrcfHG.js.map} +1 -1
  258. package/dist/{package-version-D7lQHt_-.js → package-version-CJl_pY9W.js} +2 -3
  259. package/dist/{package-version-D7lQHt_-.js.map → package-version-CJl_pY9W.js.map} +1 -1
  260. package/dist/{paired-arms-B2ttLc0_.js → paired-arms-D-54hO-k.js} +10 -14
  261. package/dist/{paired-arms-B2ttLc0_.js.map → paired-arms-D-54hO-k.js.map} +1 -1
  262. package/dist/{paired-binary-B_nejA44.js → paired-binary-BR0nwHOA.js} +3 -4
  263. package/dist/{paired-binary-B_nejA44.js.map → paired-binary-BR0nwHOA.js.map} +1 -1
  264. package/dist/{paired-promotion-decision-CQMJ5xGN.d.ts → paired-promotion-decision-BDnqepZ1.d.ts} +1 -5
  265. package/dist/paired-promotion-decision-BDnqepZ1.d.ts.map +1 -0
  266. package/dist/{paired-promotion-decision-D0SHb-ZL.js → paired-promotion-decision-FGvHA4p_.js} +5 -7
  267. package/dist/{paired-promotion-decision-D0SHb-ZL.js.map → paired-promotion-decision-FGvHA4p_.js.map} +1 -1
  268. package/dist/{pareto-BiBnQXAE.js → pareto-B9udAt2i.js} +28 -50
  269. package/dist/pareto-B9udAt2i.js.map +1 -0
  270. package/dist/pipelines/index.d.ts +5 -11
  271. package/dist/pipelines/index.d.ts.map +1 -1
  272. package/dist/pipelines/index.js +6 -8
  273. package/dist/pipelines/index.js.map +1 -1
  274. package/dist/{power-and-mde-CQX-0weG.js → power-and-mde-ClI6RWw4.js} +4 -5
  275. package/dist/{power-and-mde-CQX-0weG.js.map → power-and-mde-ClI6RWw4.js.map} +1 -1
  276. package/dist/{predicate-FdKmElA_.js → predicate-BYHA4MBn.js} +2 -3
  277. package/dist/{predicate-FdKmElA_.js.map → predicate-BYHA4MBn.js.map} +1 -1
  278. package/dist/{prime-bridge-transport-6feEglLf.d.ts → prime-bridge-transport-Cfqir_Im.d.ts} +1 -3
  279. package/dist/prime-bridge-transport-Cfqir_Im.d.ts.map +1 -0
  280. package/dist/{prime-bridge-transport-Z3cpKGoV.js → prime-bridge-transport-Csd5SQg7.js} +2 -3
  281. package/dist/{prime-bridge-transport-Z3cpKGoV.js.map → prime-bridge-transport-Csd5SQg7.js.map} +1 -1
  282. package/dist/{prime-protocol-BGxjfhM4.d.ts → prime-protocol-COFkxas6.d.ts} +4 -8
  283. package/dist/prime-protocol-COFkxas6.d.ts.map +1 -0
  284. package/dist/{prime-protocol-BFgGrEMP.js → prime-protocol-CrhpXRz9.js} +4 -6
  285. package/dist/{prime-protocol-BFgGrEMP.js.map → prime-protocol-CrhpXRz9.js.map} +1 -1
  286. package/dist/profile-cell.d.ts +1 -1
  287. package/dist/profile-cell.js +1 -2
  288. package/dist/{promotion-gate-CkVZHagC.d.ts → promotion-gate-CixshGI8.d.ts} +5 -11
  289. package/dist/promotion-gate-CixshGI8.d.ts.map +1 -0
  290. package/dist/{promotion-policy-6A8osGr_.js → promotion-policy-CBYeD4zi.js} +5 -6
  291. package/dist/{promotion-policy-6A8osGr_.js.map → promotion-policy-CBYeD4zi.js.map} +1 -1
  292. package/dist/{proposal-findings-DqLUWsAG.js → proposal-findings-WFQrxnfe.js} +3 -4
  293. package/dist/{proposal-findings-DqLUWsAG.js.map → proposal-findings-WFQrxnfe.js.map} +1 -1
  294. package/dist/{quantile--0yb07pD.js → quantile-CncXP-Ss.js} +2 -3
  295. package/dist/{quantile--0yb07pD.js.map → quantile-CncXP-Ss.js.map} +1 -1
  296. package/dist/{query-B_RZ36an.js → query-CGXzO9d4.js} +5 -6
  297. package/dist/{query-B_RZ36an.js.map → query-CGXzO9d4.js.map} +1 -1
  298. package/dist/{query-Cmv_U8vf.d.ts → query-UD0B08Sb.d.ts} +4 -6
  299. package/dist/query-UD0B08Sb.d.ts.map +1 -0
  300. package/dist/{random-DGEyr3zG.d.ts → random-BN150Q_X.d.ts} +1 -5
  301. package/dist/random-BN150Q_X.d.ts.map +1 -0
  302. package/dist/{random-DDDcC7YU.js → random-DrzcgC7F.js} +3 -4
  303. package/dist/{random-DDDcC7YU.js.map → random-DrzcgC7F.js.map} +1 -1
  304. package/dist/{raw-provider-sink-75w4FWBj.js → raw-provider-sink-DDLkP_eF.js} +3 -4
  305. package/dist/{raw-provider-sink-75w4FWBj.js.map → raw-provider-sink-DDLkP_eF.js.map} +1 -1
  306. package/dist/{record-id-DUgsK5qp.js → record-id-CWZXFh58.js} +2 -3
  307. package/dist/{record-id-DUgsK5qp.js.map → record-id-CWZXFh58.js.map} +1 -1
  308. package/dist/{redact-DXdlFb_U.d.ts → redact-C_wzC4c_.d.ts} +1 -3
  309. package/dist/redact-C_wzC4c_.d.ts.map +1 -0
  310. package/dist/{redact-mtkTiJVk.js → redact-D6APJS1d.js} +3 -5
  311. package/dist/{redact-mtkTiJVk.js.map → redact-D6APJS1d.js.map} +1 -1
  312. package/dist/{registry-BcdJmyoU.d.ts → registry-dhdDoAV8.d.ts} +5 -11
  313. package/dist/registry-dhdDoAV8.d.ts.map +1 -0
  314. package/dist/{release-confidence-CYIFH-fp.js → release-confidence-CTUJz5mM.js} +10 -16
  315. package/dist/release-confidence-CTUJz5mM.js.map +1 -0
  316. package/dist/{render-BhJqXoBH.js → render-pfAZ7IR4.js} +266 -33
  317. package/dist/render-pfAZ7IR4.js.map +1 -0
  318. package/dist/{reporting-html-Kvlc8oMt.js → reporting-html-DMXIjATy.js} +2 -3
  319. package/dist/{reporting-html-Kvlc8oMt.js.map → reporting-html-DMXIjATy.js.map} +1 -1
  320. package/dist/reporting.d.ts +6 -6
  321. package/dist/reporting.js +7 -7
  322. package/dist/{researcher-DKWtoMWk.d.ts → researcher-CLnNJ7Or.d.ts} +8 -12
  323. package/dist/researcher-CLnNJ7Or.d.ts.map +1 -0
  324. package/dist/{reward-nw2xZGZG.js → reward-P0VD_Aft.js} +2 -3
  325. package/dist/{reward-nw2xZGZG.js.map → reward-P0VD_Aft.js.map} +1 -1
  326. package/dist/{reward-BeUgVVC_.d.ts → reward-ST4PXNXF.d.ts} +2 -4
  327. package/dist/reward-ST4PXNXF.d.ts.map +1 -0
  328. package/dist/{reward-hacking-WTxUbtbb.d.ts → reward-hacking-C9hPVT0Q.d.ts} +4 -8
  329. package/dist/reward-hacking-C9hPVT0Q.d.ts.map +1 -0
  330. package/dist/{reward-hacking-ByuETaIb.js → reward-hacking-DZzHZlS1.js} +5 -7
  331. package/dist/{reward-hacking-ByuETaIb.js.map → reward-hacking-DZzHZlS1.js.map} +1 -1
  332. package/dist/rl.d.ts +26 -63
  333. package/dist/rl.d.ts.map +1 -1
  334. package/dist/rl.js +35 -52
  335. package/dist/rl.js.map +1 -1
  336. package/dist/{rolldown-runtime-8H4AJuhK.js → rolldown-runtime-BJohB4LM.js} +1 -2
  337. package/dist/rollout/index.d.ts +6 -6
  338. package/dist/rollout/index.js +7 -7
  339. package/dist/{rollout-Dd1ucT_M.js → rollout-BhkMpAJT.js} +279 -16
  340. package/dist/rollout-BhkMpAJT.js.map +1 -0
  341. package/dist/{terminal-record-CB9BFtjS.js → rollout-nodes-BHR9Q5jP.js} +351 -11
  342. package/dist/rollout-nodes-BHR9Q5jP.js.map +1 -0
  343. package/dist/{round-decimal-COrKglMh.js → round-decimal-ZmjAQPo1.js} +2 -3
  344. package/dist/{round-decimal-COrKglMh.js.map → round-decimal-ZmjAQPo1.js.map} +1 -1
  345. package/dist/{rubric-predictive-validity-Cd5SCtAf.d.ts → rubric-predictive-validity-B3RzbwOx.d.ts} +2 -8
  346. package/dist/rubric-predictive-validity-B3RzbwOx.d.ts.map +1 -0
  347. package/dist/{rubric-predictive-validity-CeKW2GQN.js → rubric-predictive-validity-CQp_M0vy.js} +3 -4
  348. package/dist/{rubric-predictive-validity-CeKW2GQN.js.map → rubric-predictive-validity-CQp_M0vy.js.map} +1 -1
  349. package/dist/{run-record-CysKLB93.js → run-record-CZy4-TnZ.js} +4 -5
  350. package/dist/{run-record-CysKLB93.js.map → run-record-CZy4-TnZ.js.map} +1 -1
  351. package/dist/{run-record-C3awiXPf.d.ts → run-record-D2BFMPGl.d.ts} +5 -7
  352. package/dist/run-record-D2BFMPGl.d.ts.map +1 -0
  353. package/dist/{run-record-DhEJgoPz.js → run-record-DEjx43cI.js} +6 -7
  354. package/dist/{run-record-DhEJgoPz.js.map → run-record-DEjx43cI.js.map} +1 -1
  355. package/dist/{sandbox-harness-BlSOu4LX.d.ts → sandbox-harness-B3Kx1fOA.d.ts} +1 -3
  356. package/dist/sandbox-harness-B3Kx1fOA.d.ts.map +1 -0
  357. package/dist/{schema-D6EVKzTB.d.ts → schema-CkIvnmLU.d.ts} +2 -43
  358. package/dist/schema-CkIvnmLU.d.ts.map +1 -0
  359. package/dist/{schema-Bt2vLFm3.js → schema-D-xu3MU_.js} +2 -3
  360. package/dist/{schema-Bt2vLFm3.js.map → schema-D-xu3MU_.js.map} +1 -1
  361. package/dist/{schema-C-ziyJD7.d.ts → schema-DkFJr3Y8.d.ts} +111 -48
  362. package/dist/schema-DkFJr3Y8.d.ts.map +1 -0
  363. package/dist/{schema-CvhfLjtZ.js → schema-YUIXT8iW.js} +37 -7
  364. package/dist/schema-YUIXT8iW.js.map +1 -0
  365. package/dist/search/index.d.ts +3 -35
  366. package/dist/search/index.d.ts.map +1 -1
  367. package/dist/search/index.js +4 -5
  368. package/dist/{search-kernel-CctpiDd2.d.ts → search-kernel-CBdwFZ05.d.ts} +10 -36
  369. package/dist/search-kernel-CBdwFZ05.d.ts.map +1 -0
  370. package/dist/{search-ledger-CZRqtFbW.js → search-ledger-BsVi-Ngv.js} +17 -26
  371. package/dist/{search-ledger-CZRqtFbW.js.map → search-ledger-BsVi-Ngv.js.map} +1 -1
  372. package/dist/{search-ledger-file-Bd5Tioq6.js → search-ledger-file-DTBD6X-y.js} +6 -8
  373. package/dist/{search-ledger-file-Bd5Tioq6.js.map → search-ledger-file-DTBD6X-y.js.map} +1 -1
  374. package/dist/{search-ledger-types-p2xKfiDJ.d.ts → search-ledger-types-qiYRUo_N.d.ts} +5 -9
  375. package/dist/search-ledger-types-qiYRUo_N.d.ts.map +1 -0
  376. package/dist/{search-shipper-Dn3NLsuH.js → search-shipper-pdg4viK7.js} +8 -13
  377. package/dist/{search-shipper-Dn3NLsuH.js.map → search-shipper-pdg4viK7.js.map} +1 -1
  378. package/dist/{search-summary-D4bwYnAE.js → search-summary-Ct7SrmVc.js} +6 -7
  379. package/dist/{search-summary-D4bwYnAE.js.map → search-summary-Ct7SrmVc.js.map} +1 -1
  380. package/dist/{sequential-CimQrbjv.js → sequential-B1I0tRfL.js} +6 -7
  381. package/dist/{sequential-CimQrbjv.js.map → sequential-B1I0tRfL.js.map} +1 -1
  382. package/dist/{sequential-KwGspfeR.d.ts → sequential-Bb_pdTqG.d.ts} +1 -3
  383. package/dist/sequential-Bb_pdTqG.d.ts.map +1 -0
  384. package/dist/{sequential-BVv1sjsw.js → sequential-Bjs5roiK.js} +2 -3
  385. package/dist/{sequential-BVv1sjsw.js.map → sequential-Bjs5roiK.js.map} +1 -1
  386. package/dist/{sequential-eprocess-DodI6RoF.js → sequential-eprocess-C1YLwFaz.js} +3 -4
  387. package/dist/{sequential-eprocess-DodI6RoF.js.map → sequential-eprocess-C1YLwFaz.js.map} +1 -1
  388. package/dist/{server-ChhXPCgX.js → server-DA6h3co5.js} +11 -17
  389. package/dist/{server-ChhXPCgX.js.map → server-DA6h3co5.js.map} +1 -1
  390. package/dist/{single-run-lock-Dekd8_Wv.js → single-run-lock-BGlW3OSk.js} +3 -4
  391. package/dist/{single-run-lock-Dekd8_Wv.js.map → single-run-lock-BGlW3OSk.js.map} +1 -1
  392. package/dist/{skillopt-optimization-method-sB_-yi1G.js → skillopt-optimization-method-qB1M554K.js} +38 -57
  393. package/dist/{skillopt-optimization-method-sB_-yi1G.js.map → skillopt-optimization-method-qB1M554K.js.map} +1 -1
  394. package/dist/{spans-CVngGij3.d.ts → spans-vZoW__3q.d.ts} +2 -4
  395. package/dist/spans-vZoW__3q.d.ts.map +1 -0
  396. package/dist/{statistical-heldout-BjzSOmLH.d.ts → statistical-heldout-Cei036nE.d.ts} +9 -37
  397. package/dist/statistical-heldout-Cei036nE.d.ts.map +1 -0
  398. package/dist/{statistical-heldout-Bksv92Th.js → statistical-heldout-TP6ndL0B.js} +4 -5
  399. package/dist/{statistical-heldout-Bksv92Th.js.map → statistical-heldout-TP6ndL0B.js.map} +1 -1
  400. package/dist/{steps-DlepJPwD.d.ts → steps-B8fYY_Vo.d.ts} +1 -3
  401. package/dist/steps-B8fYY_Vo.d.ts.map +1 -0
  402. package/dist/{store-B3nWRy3B.d.ts → store-CMs5wGXP.d.ts} +2 -4
  403. package/dist/store-CMs5wGXP.d.ts.map +1 -0
  404. package/dist/{store-BhNuLdJw.js → store-ZykIyQmy.js} +2 -3
  405. package/dist/{store-BhNuLdJw.js.map → store-ZykIyQmy.js.map} +1 -1
  406. package/dist/{store-otlp-CFf27E8_.js → store-otlp-DmLm65XW.js} +8 -13
  407. package/dist/{store-otlp-CFf27E8_.js.map → store-otlp-DmLm65XW.js.map} +1 -1
  408. package/dist/{store-tool-spans-DxsFwtdr.d.ts → store-tool-spans-B3i3fl0A.d.ts} +11 -29
  409. package/dist/store-tool-spans-B3i3fl0A.d.ts.map +1 -0
  410. package/dist/{store-tool-spans-BK_8FjGG.js → store-tool-spans-C2g8UYm-.js} +17 -41
  411. package/dist/{store-tool-spans-BK_8FjGG.js.map → store-tool-spans-C2g8UYm-.js.map} +1 -1
  412. package/dist/storyboard/index.d.ts +1 -5
  413. package/dist/storyboard/index.d.ts.map +1 -1
  414. package/dist/storyboard/index.js +3 -5
  415. package/dist/storyboard/index.js.map +1 -1
  416. package/dist/{summary-report-C8V49Jt3.d.ts → summary-report-0La5vejY.d.ts} +5 -13
  417. package/dist/summary-report-0La5vejY.d.ts.map +1 -0
  418. package/dist/{summary-report-DHDWxe6p.js → summary-report-CPfsrLac.js} +21 -30
  419. package/dist/summary-report-CPfsrLac.js.map +1 -0
  420. package/dist/supervisor-run/index.d.ts +30 -29
  421. package/dist/supervisor-run/index.d.ts.map +1 -1
  422. package/dist/supervisor-run/index.js +6 -7
  423. package/dist/{systemone-CHnqwmYg.d.ts → systemone-Cw2txK5m.d.ts} +12 -24
  424. package/dist/systemone-Cw2txK5m.d.ts.map +1 -0
  425. package/dist/{systemone-protocol-Bl2EI2KQ.d.ts → systemone-protocol-C4t7JH4Y.d.ts} +1 -3
  426. package/dist/systemone-protocol-C4t7JH4Y.d.ts.map +1 -0
  427. package/dist/systemone-protocol.d.ts +1 -1
  428. package/dist/systemone-protocol.js +2 -3
  429. package/dist/{systemone-review-cQ9acAsb.d.ts → systemone-review-BLgxt-4Q.d.ts} +8 -10
  430. package/dist/systemone-review-BLgxt-4Q.d.ts.map +1 -0
  431. package/dist/{systemone-review-DFGtIUcf.js → systemone-review-S49gsy_y.js} +5 -6
  432. package/dist/{systemone-review-DFGtIUcf.js.map → systemone-review-S49gsy_y.js.map} +1 -1
  433. package/dist/systemone.d.ts +4 -4
  434. package/dist/systemone.js +3 -3
  435. package/dist/{task-failure-attributes-oIK3BhCR.js → task-failure-attributes-CC6VuIpk.js} +7 -10
  436. package/dist/{task-failure-attributes-oIK3BhCR.js.map → task-failure-attributes-CC6VuIpk.js.map} +1 -1
  437. package/dist/{tool-groups-b3oU_D88.d.ts → tool-groups-C3K-d3gd.d.ts} +3 -5
  438. package/dist/tool-groups-C3K-d3gd.d.ts.map +1 -0
  439. package/dist/{tool-waste-CkjzWmeY.d.ts → tool-waste-BFG1vwTV.d.ts} +4 -16
  440. package/dist/tool-waste-BFG1vwTV.d.ts.map +1 -0
  441. package/dist/{tool-waste-DLsjS_p-.js → tool-waste-CLJ46AbT.js} +10 -26
  442. package/dist/{tool-waste-DLsjS_p-.js.map → tool-waste-CLJ46AbT.js.map} +1 -1
  443. package/dist/trace-attributes.d.ts +1 -1
  444. package/dist/trace-attributes.js +1 -2
  445. package/dist/{trace-questions-BmT8M6UQ.d.ts → trace-questions-ej5AEJ5X.d.ts} +4 -6
  446. package/dist/trace-questions-ej5AEJ5X.d.ts.map +1 -0
  447. package/dist/trace-repair/index.d.ts +46 -92
  448. package/dist/trace-repair/index.d.ts.map +1 -1
  449. package/dist/trace-repair/index.js +32 -54
  450. package/dist/trace-repair/index.js.map +1 -1
  451. package/dist/traces.d.ts +13 -29
  452. package/dist/traces.d.ts.map +1 -1
  453. package/dist/traces.js +18 -22
  454. package/dist/traces.js.map +1 -1
  455. package/dist/{trajectory-D_7rLrvE.js → trajectory-O3GDHmev.js} +2 -3
  456. package/dist/{trajectory-D_7rLrvE.js.map → trajectory-O3GDHmev.js.map} +1 -1
  457. package/dist/trajectory-replay/index.d.ts +2 -22
  458. package/dist/trajectory-replay/index.d.ts.map +1 -1
  459. package/dist/trajectory-replay/index.js +19 -30
  460. package/dist/trajectory-replay/index.js.map +1 -1
  461. package/dist/{tree-DSqwJpL9.js → tree-DrIChF4a.js} +39 -68
  462. package/dist/{tree-DSqwJpL9.js.map → tree-DrIChF4a.js.map} +1 -1
  463. package/dist/{types-B_IFcKp5.d.ts → types-0KglnQ9o.d.ts} +3 -15
  464. package/dist/types-0KglnQ9o.d.ts.map +1 -0
  465. package/dist/{types-DZ0mYVw9.d.ts → types-0oMg7zee.d.ts} +3 -5
  466. package/dist/types-0oMg7zee.d.ts.map +1 -0
  467. package/dist/{types-CnWmj8NW.js → types-BK0blWhe.js} +3 -4
  468. package/dist/{types-CnWmj8NW.js.map → types-BK0blWhe.js.map} +1 -1
  469. package/dist/{types-CmXY0PQf.d.ts → types-C-aOqgt2.d.ts} +2 -5
  470. package/dist/types-C-aOqgt2.d.ts.map +1 -0
  471. package/dist/{types-M6eF9m-r.d.ts → types-C54Uk_a1.d.ts} +84 -24
  472. package/dist/types-C54Uk_a1.d.ts.map +1 -0
  473. package/dist/{types-BXgASBCL.js → types-DK4vNv5q.js} +2 -3
  474. package/dist/{types-BXgASBCL.js.map → types-DK4vNv5q.js.map} +1 -1
  475. package/dist/{types-6Lfdlshp.d.ts → types-DzCO-S1m.d.ts} +50 -62
  476. package/dist/types-DzCO-S1m.d.ts.map +1 -0
  477. package/dist/{verdict-BGQmxQ8A.js → verdict-C8TcdwfD.js} +3 -4
  478. package/dist/{verdict-BGQmxQ8A.js.map → verdict-C8TcdwfD.js.map} +1 -1
  479. package/dist/{verdict-C24NELtN.d.ts → verdict-D_qiBQ6_.d.ts} +1 -5
  480. package/dist/verdict-D_qiBQ6_.d.ts.map +1 -0
  481. package/dist/{verdict-cache-CL_7tePD.js → verdict-cache-BVH-fl18.js} +3 -4
  482. package/dist/{verdict-cache-CL_7tePD.js.map → verdict-cache-BVH-fl18.js.map} +1 -1
  483. package/dist/wire/index.d.ts +43 -51
  484. package/dist/wire/index.d.ts.map +1 -1
  485. package/dist/wire/index.js +1 -2
  486. package/docs/eval-surface-map.md +15 -0
  487. package/docs/rollout.md +132 -6
  488. package/package.json +18 -18
  489. package/dist/adversarial-smnADNFS.d.ts.map +0 -1
  490. package/dist/agent-profile-CNmwfaqq.d.ts.map +0 -1
  491. package/dist/agent-profile-cell-BcpFbNd5.d.ts.map +0 -1
  492. package/dist/analyze-runs-DfX6dHP0.d.ts.map +0 -1
  493. package/dist/attribute-vocabulary-CcXqHODT.d.ts.map +0 -1
  494. package/dist/benchmark-command-Cnjfo0Zh.js.map +0 -1
  495. package/dist/campaign-evidence-DunzcJGv.js.map +0 -1
  496. package/dist/campaign-uddTlFg5.js.map +0 -1
  497. package/dist/canonical-CFpojCN5.d.ts.map +0 -1
  498. package/dist/client-hwo3cJjR.d.ts.map +0 -1
  499. package/dist/completion-verifier-asaV1nSj.js.map +0 -1
  500. package/dist/cost-ledger-C1W3ICmP.d.ts.map +0 -1
  501. package/dist/dataset-DQqhOCPt.d.ts.map +0 -1
  502. package/dist/default-registry-CLG5YqGS.d.ts.map +0 -1
  503. package/dist/define-agent-eval-JKt3gMQr.d.ts.map +0 -1
  504. package/dist/descriptive-B2iPaT9J.d.ts +0 -89
  505. package/dist/descriptive-B2iPaT9J.d.ts.map +0 -1
  506. package/dist/descriptive-CVNy48rR.js.map +0 -1
  507. package/dist/emitter-DABYYTcH.d.ts.map +0 -1
  508. package/dist/engine-dtRVeuQs.d.ts.map +0 -1
  509. package/dist/errors-DEE6u6ot.d.ts.map +0 -1
  510. package/dist/evaluation-DblGquCB.d.ts.map +0 -1
  511. package/dist/exact-types-Do63KoKn.d.ts.map +0 -1
  512. package/dist/exporters-DWvM16LE.js.map +0 -1
  513. package/dist/exporters-Dk3oEbK_.d.ts.map +0 -1
  514. package/dist/failure-cluster-DN0t63Z0.d.ts.map +0 -1
  515. package/dist/feedback-trajectory-CYVJXolG.d.ts.map +0 -1
  516. package/dist/hf-dataset-CKxIJQba.js.map +0 -1
  517. package/dist/index-CHxwfW5g.d.ts.map +0 -1
  518. package/dist/index-CTIRz-AB.d.ts.map +0 -1
  519. package/dist/index-CalAsXMR.d.ts.map +0 -1
  520. package/dist/index-CdEVr8-O.d.ts.map +0 -1
  521. package/dist/index-CfJULcW5.d.ts.map +0 -1
  522. package/dist/index-D7fmC-1K.d.ts.map +0 -1
  523. package/dist/index-jnuFLxOs.d.ts.map +0 -1
  524. package/dist/integrity-D-s2iHiT.js.map +0 -1
  525. package/dist/integrity-D9lBnv_K.d.ts.map +0 -1
  526. package/dist/interval-ohuOJurX.d.ts.map +0 -1
  527. package/dist/judge-calibration-DFtEMlde.d.ts.map +0 -1
  528. package/dist/llm-judge-Cybq29bL.js.map +0 -1
  529. package/dist/lock-holder-DaJbfpci.d.ts.map +0 -1
  530. package/dist/matrix-B8l-Nsxd.js.map +0 -1
  531. package/dist/matrix-DtkZLD_3.d.ts.map +0 -1
  532. package/dist/mint-CkzpVPdz.d.ts +0 -81
  533. package/dist/mint-CkzpVPdz.d.ts.map +0 -1
  534. package/dist/multi-layer-verifier-DEgMUk6v.d.ts.map +0 -1
  535. package/dist/multiplicity-DIWHvysC.d.ts.map +0 -1
  536. package/dist/paired-promotion-decision-CQMJ5xGN.d.ts.map +0 -1
  537. package/dist/pareto-BiBnQXAE.js.map +0 -1
  538. package/dist/prime-bridge-transport-6feEglLf.d.ts.map +0 -1
  539. package/dist/prime-protocol-BGxjfhM4.d.ts.map +0 -1
  540. package/dist/promotion-gate-CkVZHagC.d.ts.map +0 -1
  541. package/dist/query-Cmv_U8vf.d.ts.map +0 -1
  542. package/dist/random-DGEyr3zG.d.ts.map +0 -1
  543. package/dist/redact-DXdlFb_U.d.ts.map +0 -1
  544. package/dist/registry-BcdJmyoU.d.ts.map +0 -1
  545. package/dist/release-confidence-CYIFH-fp.js.map +0 -1
  546. package/dist/render-BhJqXoBH.js.map +0 -1
  547. package/dist/researcher-DKWtoMWk.d.ts.map +0 -1
  548. package/dist/reward-BeUgVVC_.d.ts.map +0 -1
  549. package/dist/reward-hacking-WTxUbtbb.d.ts.map +0 -1
  550. package/dist/rollout-Dd1ucT_M.js.map +0 -1
  551. package/dist/rubric-predictive-validity-Cd5SCtAf.d.ts.map +0 -1
  552. package/dist/run-record-C3awiXPf.d.ts.map +0 -1
  553. package/dist/sandbox-harness-BlSOu4LX.d.ts.map +0 -1
  554. package/dist/schema-C-ziyJD7.d.ts.map +0 -1
  555. package/dist/schema-CvhfLjtZ.js.map +0 -1
  556. package/dist/schema-D6EVKzTB.d.ts.map +0 -1
  557. package/dist/search-kernel-CctpiDd2.d.ts.map +0 -1
  558. package/dist/search-ledger-types-p2xKfiDJ.d.ts.map +0 -1
  559. package/dist/sequential-KwGspfeR.d.ts.map +0 -1
  560. package/dist/spans-CVngGij3.d.ts.map +0 -1
  561. package/dist/statistical-heldout-BjzSOmLH.d.ts.map +0 -1
  562. package/dist/steps-DlepJPwD.d.ts.map +0 -1
  563. package/dist/store-B3nWRy3B.d.ts.map +0 -1
  564. package/dist/store-tool-spans-DxsFwtdr.d.ts.map +0 -1
  565. package/dist/summary-report-C8V49Jt3.d.ts.map +0 -1
  566. package/dist/summary-report-DHDWxe6p.js.map +0 -1
  567. package/dist/systemone-CHnqwmYg.d.ts.map +0 -1
  568. package/dist/systemone-protocol-Bl2EI2KQ.d.ts.map +0 -1
  569. package/dist/systemone-review-cQ9acAsb.d.ts.map +0 -1
  570. package/dist/terminal-record-CB9BFtjS.js.map +0 -1
  571. package/dist/tool-groups-b3oU_D88.d.ts.map +0 -1
  572. package/dist/tool-waste-CkjzWmeY.d.ts.map +0 -1
  573. package/dist/trace-questions-BmT8M6UQ.d.ts.map +0 -1
  574. package/dist/types-6Lfdlshp.d.ts.map +0 -1
  575. package/dist/types-B_IFcKp5.d.ts.map +0 -1
  576. package/dist/types-CmXY0PQf.d.ts.map +0 -1
  577. package/dist/types-DZ0mYVw9.d.ts.map +0 -1
  578. package/dist/types-M6eF9m-r.d.ts.map +0 -1
  579. package/dist/verdict-C24NELtN.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/multishot/cost.ts","../../src/multishot/default-tools.ts","../../src/multishot/shape-defaults.ts","../../src/multishot/conversation.ts","../../src/multishot/judges.ts","../../src/multishot/multishot.ts","../../src/multishot/matrix.ts"],"sourcesContent":["// Per-model cost estimator for multishot legs whose transport reported token\n// usage but no billed amount.\n\n/**\n * Rough per-model cost estimate from token counts. Underestimates Anthropic,\n * overestimates open-weight models — accurate enough for a cost ceiling, and\n * never presented as a billed amount: a leg metered from this table is\n * recorded with `estimated` provenance.\n */\nexport function estimateMultishotCost(\n model: string,\n usage?: { prompt_tokens?: number; completion_tokens?: number },\n): number {\n if (!usage) return 0\n const inputTok = usage.prompt_tokens ?? 0\n const outputTok = usage.completion_tokens ?? 0\n let inPer1k = 0.003\n let outPer1k = 0.015\n if (model.includes('gpt-4o-mini')) {\n inPer1k = 0.00015\n outPer1k = 0.0006\n } else if (model.includes('gpt-5.4') || model.includes('claude-sonnet')) {\n inPer1k = 0.003\n outPer1k = 0.015\n } else if (model.includes('kimi') || model.includes('glm') || model.includes('deepseek')) {\n inPer1k = 0.0005\n outPer1k = 0.002\n }\n return (inputTok * inPer1k + outputTok * outPer1k) / 1000\n}\n","// Default delegate_research + delegate_code tools and their inline executors.\n//\n// Consumers can override either by passing their own tools + executors to\n// runMultishot. The defaults are sufficient for most domains — point the\n// researcher system prompt at your domain's citation style and the coder\n// at your preferred language.\n\nimport { estimateMultishotCost } from './cost'\nimport type { MultishotToolDefinition, MultishotToolExecutor } from './types'\n\nconst DEFAULT_RESEARCHER_MODEL = 'openai/gpt-4o-mini'\nexport const DEFAULT_CODER_MODEL = 'openai/gpt-4o-mini'\n\nexport interface DefaultResearcherConfig {\n /** Replace the system prompt to bias the researcher toward a domain's\n * citation style. Defaults to a generic \"cite sources by name\" prompt. */\n systemPrompt?: string\n model?: string\n}\n\nexport interface DefaultCoderConfig {\n /** Replace the system prompt to bias the coder toward a language /\n * framework / artifact style. */\n systemPrompt?: string\n model?: string\n}\n\nconst GENERIC_RESEARCHER_SYSTEM =\n 'You are a research specialist. Return a markdown brief with 3-5 findings. Each finding cites a specific source by name. Add a confidence level (high/medium/low) per finding. No fluff, no preamble.'\n\nconst GENERIC_CODER_SYSTEM =\n 'You are an expert engineer. Output ONE fenced code block containing the complete solution. Inline-comment non-obvious decisions. No explanation outside the block.'\n\nconst DEFAULT_DELEGATE_RESEARCH_TOOL: MultishotToolDefinition = {\n type: 'function',\n function: {\n name: 'delegate_research',\n description:\n 'Research a topic deeply via specialist. Returns evidence-bearing items with citations. Use for audience research, competitive intel, regulatory landscape, market data, citation-grounded analysis.',\n parameters: {\n type: 'object',\n properties: {\n question: { type: 'string', description: 'Specific question to research' },\n scope: {\n type: 'string',\n description: 'Optional scope: time window, geography, jurisdiction, segment',\n },\n },\n required: ['question'],\n },\n },\n}\n\nconst DEFAULT_DELEGATE_CODE_TOOL: MultishotToolDefinition = {\n type: 'function',\n function: {\n name: 'delegate_code',\n description:\n 'Generate a runnable script, template, pipeline, or tool via specialist. Returns complete working code or structured markdown. Use for content pipelines, calc snippets, dashboards, compliance checklists, deadline trackers.',\n parameters: {\n type: 'object',\n properties: {\n goal: { type: 'string', description: 'What the code must accomplish' },\n language: {\n type: 'string',\n description: 'Optional language preference (default: TypeScript)',\n },\n },\n required: ['goal'],\n },\n },\n}\n\nfunction createResearchExecutor(config: DefaultResearcherConfig = {}): MultishotToolExecutor {\n const systemPrompt = config.systemPrompt ?? GENERIC_RESEARCHER_SYSTEM\n const model = config.model ?? DEFAULT_RESEARCHER_MODEL\n return async (args, ctx) => {\n const question = String(args.question ?? '')\n const scope = args.scope ? String(args.scope) : undefined\n const { message, usage, costUsd } = await ctx.transport({\n model,\n temperature: 0.3,\n maxTokens: 1800,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: `Research: ${question}${scope ? `\\nScope: ${scope}` : ''}` },\n ],\n signal: ctx.signal,\n })\n return {\n content: message.content ?? '',\n costUsd: costUsd ?? estimateMultishotCost(model, usage),\n }\n }\n}\n\nfunction createCodeExecutor(config: DefaultCoderConfig = {}): MultishotToolExecutor {\n const systemPrompt = config.systemPrompt ?? GENERIC_CODER_SYSTEM\n const model = config.model ?? DEFAULT_CODER_MODEL\n return async (args, ctx) => {\n const goal = String(args.goal ?? '')\n const language = args.language ? String(args.language) : 'TypeScript'\n const { message, usage, costUsd } = await ctx.transport({\n model,\n temperature: 0.2,\n maxTokens: 2000,\n messages: [\n { role: 'system', content: `${systemPrompt}\\n\\nLanguage: ${language}` },\n { role: 'user', content: `Produce: ${goal}` },\n ],\n signal: ctx.signal,\n })\n return {\n content: message.content ?? '',\n costUsd: costUsd ?? estimateMultishotCost(model, usage),\n }\n }\n}\n\nexport interface DefaultToolsConfig {\n research?: DefaultResearcherConfig\n code?: DefaultCoderConfig\n /** When true (default), each tool result is recorded as a typed artifact:\n * research → type='research', code → type='code'. */\n recordArtifacts?: boolean\n}\n\nexport interface DefaultToolsBundle {\n tools: MultishotToolDefinition[]\n executors: Record<string, MultishotToolExecutor>\n artifactTypeFor: (toolName: string) => string | undefined\n}\n\nexport function defaultDelegationTools(config: DefaultToolsConfig = {}): DefaultToolsBundle {\n return {\n tools: [DEFAULT_DELEGATE_RESEARCH_TOOL, DEFAULT_DELEGATE_CODE_TOOL],\n executors: {\n delegate_research: createResearchExecutor(config.research),\n delegate_code: createCodeExecutor(config.code),\n },\n artifactTypeFor: (name) =>\n name === 'delegate_research' ? 'research' : name === 'delegate_code' ? 'code' : undefined,\n }\n}\n","// Profile-derived defaults for MultishotShape — the pure-profile path.\n//\n// `MultishotShape`'s callbacks were REQUIRED beside `profile: AgentProfile`,\n// which mixed the abstractions: the node under test was a profile, but the\n// simulated user's role could only be expressed as code. These defaults make\n// the callbacks optional — a pure-profile call works, and the derived prompts\n// are plain data (a pure function of profile + persona payload), so an\n// optimizer can sweep them (tangle-network/agent-runtime#694).\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { MultishotPersona, MultishotShape } from './types'\n\n/** Persona payload rendered as stable `- key: value` lines. `id` is identity,\n * not voice, and structured values are serialized so nothing is dropped. */\nfunction renderPersonaFacts(persona: MultishotPersona): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(persona)) {\n if (key === 'id' || value === undefined) continue\n const rendered =\n typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n ? String(value)\n : JSON.stringify(value)\n lines.push(`- ${key}: ${rendered}`)\n }\n return lines.join('\\n')\n}\n\n/** Default opening user message: the persona introduces itself with its whole\n * payload and asks the agent (as described by the profile) to take over. */\nfunction defaultMultishotOpener(profile: AgentProfile, persona: MultishotPersona): string {\n const facts = renderPersonaFacts(persona)\n const agentDescription = profile.description ?? profile.name ?? 'the agent'\n return [\n `Hi — I'm reaching out to ${agentDescription} for help. My situation:`,\n facts.length > 0 ? facts : `- (no details provided beyond id: ${persona.id})`,\n '',\n 'Tell me what you need from me, and get started on my case.',\n ].join('\\n')\n}\n\n/** Default driver system prompt: roleplay the persona from its payload, stay\n * in character, push back on vague answers, and never go silent. */\nfunction defaultMultishotDriverSystemPrompt(\n profile: AgentProfile,\n persona: MultishotPersona,\n): string {\n const facts = renderPersonaFacts(persona)\n const agentDescription = profile.description ?? profile.name ?? 'an AI agent'\n return [\n `You are role-playing a real person (persona \"${persona.id}\") talking to ${agentDescription}.`,\n facts.length > 0 ? `Who you are:\\n${facts}` : '',\n '',\n 'How to behave:',\n '- Stay in character: first person, realistic voice, concrete details from your situation.',\n '- Judge every reply by whether it actually moves YOUR case forward. Push back on vague, hedged, or generic answers and demand specifics.',\n \"- Answer the agent's questions with information consistent with who you are; invent plausible details rather than stalling.\",\n '- Never go silent: always produce a substantive next message.',\n '- Output ONLY your next message to the agent — no meta-commentary, no stage directions.',\n ]\n .filter((block) => block.length > 0)\n .join('\\n')\n}\n\n/** The fully-resolved shape for a profile: caller overrides win, the\n * profile-derived defaults fill the rest. */\nexport function defaultShapeFromProfile<TPersona extends MultishotPersona>(\n profile: AgentProfile,\n shape?: MultishotShape<TPersona>,\n): Required<MultishotShape<TPersona>> {\n return {\n buildOpener: shape?.buildOpener ?? ((persona) => defaultMultishotOpener(profile, persona)),\n buildDriverSystemPrompt:\n shape?.buildDriverSystemPrompt ??\n ((persona) => defaultMultishotDriverSystemPrompt(profile, persona)),\n }\n}\n","// The multishot conversation's two legs, separable from the loop that orders\n// them.\n//\n// `runMultishot` orders the legs as a plain turn loop. A caller that orders\n// them another way — a Runtime flow graph, a scheduler, a replay harness —\n// drives the same legs through `runMultishotConversation`, so the transcript,\n// artifacts, tool-call count, driver point of view and cost accounting stay\n// this package's single implementation.\n//\n// agent-eval owns no model transport: every leg runs on a MultishotTransport\n// the caller supplies, so no provider credential enters this package.\n\nimport { withCellSpend } from '../matrix'\nimport { estimateMultishotCost } from './cost'\nimport { defaultDelegationTools } from './default-tools'\nimport type { RunMultishotOptions } from './multishot'\nimport { defaultShapeFromProfile } from './shape-defaults'\nimport {\n type MultishotArtifact,\n MultishotDriverEmptyError,\n MultishotFatalToolError,\n type MultishotMessage,\n type MultishotPersona,\n type MultishotResult,\n} from './types'\n\n/** Prompt and completion tokens one leg reported. */\nexport interface MultishotLegTokens {\n input: number\n output: number\n}\n\n/** What one leg spent: its tokens and the USD it added to the conversation's\n * cost (provider-reported, else estimated from usage; tool executor spend\n * included). */\nexport interface MultishotLegSpend {\n tokens: MultishotLegTokens\n usd: number\n}\n\n/** One conversation's state and legs. Each leg appends to the shared\n * transcript; the caller decides the order in which legs run. */\nexport interface MultishotConversation {\n /** Agent turns the conversation is configured for (`opts.maxTurns ?? 10`). */\n readonly maxTurns: number\n /** The model the agent leg runs on. */\n readonly agentModel: string\n /** The primary simulated-user model. */\n readonly driverModel: string\n /** The persona's first message, already in the transcript. */\n readonly opener: string\n /** The simulated user's system prompt. */\n readonly driverSystemPrompt: string\n /** One agent turn: inference, inline tool execution and follow-up inference,\n * until the agent answers without tools. Throws on abort, on a fatal tool\n * error and on the per-turn tool dispatch cap. */\n agentTurn(turn: number): Promise<MultishotLegSpend>\n /** The simulated user's reply to the transcript so far, appended for the\n * next agent turn. Retries an empty reply once per model, rotates through\n * the fallback models, then throws `MultishotDriverEmptyError`. */\n driverTurn(turn: number): Promise<MultishotLegSpend & { content: string }>\n}\n\n/** Orders the legs of one conversation. Resolves when the conversation is done. */\nexport type MultishotConversationDriver = (conversation: MultishotConversation) => Promise<void>\n\ninterface ConversationMeter {\n costUsd: number\n startedAt: number\n /** True once a call contributed a fabricated `0` — no provider cost and no\n * usage to price. `costUsd` is a subtotal from that point on. */\n uncaptured: boolean\n}\n\n/**\n * Run one multishot conversation whose leg order `drive` decides.\n *\n * Returns the conversation's `MultishotResult`. When any leg or `drive` throws,\n * the error is rethrown carrying the spend so far (`withCellSpend`), so a\n * matrix bills the failed cell for the turns it already paid for.\n */\nexport async function runMultishotConversation<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n drive: MultishotConversationDriver,\n): Promise<MultishotResult> {\n const meter: ConversationMeter = { costUsd: 0, startedAt: Date.now(), uncaptured: false }\n try {\n const state = openConversation(opts, meter)\n await drive(state.conversation)\n return {\n transcript: state.transcript,\n artifacts: state.artifacts,\n toolCalls: state.toolCalls(),\n durationMs: Date.now() - meter.startedAt,\n costUsd: meter.costUsd,\n // A shot that priced every call reports a complete estimate. One that had\n // a call the router priced at nothing reports a subtotal, so the cell is\n // recorded as under-counted rather than as a complete estimate.\n costProvenance: meter.uncaptured\n ? { kind: 'uncaptured', usd: null }\n : { kind: 'estimated', usd: meter.costUsd },\n }\n } catch (err) {\n throw withCellSpend(err, {\n costUsd: meter.costUsd,\n durationMs: Date.now() - meter.startedAt,\n kind: meter.uncaptured ? 'uncaptured' : 'estimated',\n })\n }\n}\n\nfunction openConversation<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n meter: ConversationMeter,\n): {\n conversation: MultishotConversation\n transcript: MultishotMessage[]\n artifacts: MultishotArtifact[]\n toolCalls: () => number\n} {\n const maxTurns = opts.maxTurns ?? 10\n const maxToolDispatches = opts.maxToolDispatches ?? 4\n const agentModel = opts.agentModel ?? 'openai/gpt-5.4'\n const driverModel = opts.driverModel ?? 'openai/gpt-4o-mini'\n const driverModels = [driverModel, ...(opts.driverFallbackModels ?? [])]\n const agentMaxTokens = opts.agentMaxTokens ?? 2500\n const toolFollowupMaxTokens = opts.toolFollowupMaxTokens ?? 2000\n const driverMaxTokens = opts.driverMaxTokens ?? 600\n\n const bundle =\n opts.tools && opts.toolExecutors\n ? {\n tools: opts.tools,\n executors: opts.toolExecutors,\n artifactTypeFor: opts.artifactTypeFor ?? (() => undefined),\n }\n : defaultDelegationTools()\n const tools = opts.tools ?? bundle.tools\n const executors = opts.toolExecutors ?? bundle.executors\n const artifactTypeFor = opts.artifactTypeFor ?? bundle.artifactTypeFor\n\n const agentTransport = opts.agentTransport\n const driverTransport = opts.driverTransport\n const toolTransport = opts.toolTransport ?? agentTransport\n\n const shape = defaultShapeFromProfile(opts.profile, opts.shape)\n\n const transcript: MultishotMessage[] = []\n const artifacts: MultishotArtifact[] = []\n let toolCalls = 0\n\n const opener = shape.buildOpener(opts.persona)\n transcript.push({ role: 'user', content: opener })\n\n const systemPrompt = [opts.profile.prompt?.systemPrompt, opts.profile.prompt?.appendSystemPrompt]\n .filter((value): value is string => Boolean(value))\n .join('\\n\\n')\n const agentMessages: Array<Record<string, unknown>> = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: opener },\n ]\n const driverSystemPrompt = shape.buildDriverSystemPrompt(opts.persona)\n\n async function agentTurn(turn: number): Promise<MultishotLegSpend> {\n if (opts.signal?.aborted) throw new Error('multishot aborted')\n const usdBefore = meter.costUsd\n const tokens = { input: 0, output: 0 }\n let dispatchesThisTurn = 0\n while (true) {\n const {\n message: agentMsg,\n usage: agentUsage,\n costUsd: agentCostUsd,\n } = await agentTransport({\n model: agentModel,\n messages: agentMessages,\n tools,\n temperature: 0.7,\n maxTokens: dispatchesThisTurn === 0 ? agentMaxTokens : toolFollowupMaxTokens,\n signal: opts.signal,\n })\n meter.costUsd += agentCostUsd ?? estimateMultishotCost(agentModel, agentUsage)\n if (agentCostUsd === undefined && agentUsage === undefined) meter.uncaptured = true\n tokens.input += agentUsage?.prompt_tokens ?? 0\n tokens.output += agentUsage?.completion_tokens ?? 0\n\n const agentText = (agentMsg.content ?? '').trim()\n const agentToolCalls = (agentMsg.tool_calls ?? []).map((tc) => ({\n id: tc.id,\n name: tc.function.name,\n args: (() => {\n try {\n return JSON.parse(tc.function.arguments) as Record<string, unknown>\n } catch {\n return {} as Record<string, unknown>\n }\n })(),\n }))\n\n agentMessages.push({\n role: 'assistant',\n content: agentText || null,\n ...(agentMsg.tool_calls?.length ? { tool_calls: agentMsg.tool_calls } : {}),\n })\n transcript.push({\n role: 'assistant',\n content: agentText,\n toolCalls: agentToolCalls.length > 0 ? agentToolCalls : undefined,\n })\n\n if (agentToolCalls.length === 0) break\n dispatchesThisTurn += agentToolCalls.length\n if (dispatchesThisTurn > maxToolDispatches) {\n throw new Error(\n `multishot: tool dispatch cap exceeded (${dispatchesThisTurn}/${maxToolDispatches}) on turn ${turn}`,\n )\n }\n\n for (const tc of agentToolCalls) {\n toolCalls++\n let toolResult = ''\n try {\n const executor = executors[tc.name]\n if (!executor) {\n toolResult = JSON.stringify({ error: `unknown tool ${tc.name}` })\n } else {\n const r = await executor(tc.args, { transport: toolTransport, signal: opts.signal })\n toolResult = r.content\n meter.costUsd += r.costUsd\n const artifactType = artifactTypeFor(tc.name)\n if (artifactType) {\n artifacts.push({\n type: artifactType,\n turn,\n invocation: { name: tc.name, args: tc.args },\n content: toolResult,\n })\n }\n }\n } catch (err) {\n if (err instanceof MultishotFatalToolError) throw err\n toolResult = JSON.stringify({ error: err instanceof Error ? err.message : String(err) })\n }\n agentMessages.push({ role: 'tool', tool_call_id: tc.id, content: toolResult || 'done' })\n transcript.push({ role: 'tool', content: toolResult || 'done', toolCallId: tc.id })\n }\n }\n return { tokens, usd: meter.costUsd - usdBefore }\n }\n\n // Every driver attempt is charged, including the empty ones that force a\n // retry and the ones that precede `MultishotDriverEmptyError`: those calls\n // billed the provider whether or not their content was usable.\n async function driverTurn(turn: number): Promise<MultishotLegSpend & { content: string }> {\n const usdBefore = meter.costUsd\n // Driver point of view: the agent's `assistant` messages become `user`\n // (the agent talking TO the driver); the driver's prior `user` messages\n // become `assistant` (the driver's prior responses).\n const driverMessages: Array<Record<string, unknown>> = [\n { role: 'system', content: driverSystemPrompt },\n ]\n for (const msg of transcript) {\n if (msg.role === 'tool') continue\n const content = driverVisibleContent(msg)\n if (!content) continue\n if (msg.role === 'assistant') driverMessages.push({ role: 'user', content })\n else if (msg.role === 'user') driverMessages.push({ role: 'assistant', content })\n }\n\n // The driver must never go silent. Retry once on empty content; then fail loud.\n const tokens = { input: 0, output: 0 }\n for (const model of driverModels) {\n for (let attempt = 0; attempt < 2; attempt++) {\n const { message, usage, costUsd } = await driverTransport({\n model,\n messages: driverMessages,\n temperature: 0.9,\n maxTokens: driverMaxTokens,\n signal: opts.signal,\n })\n meter.costUsd += costUsd ?? estimateMultishotCost(model, usage)\n if (costUsd === undefined && usage === undefined) meter.uncaptured = true\n tokens.input += usage?.prompt_tokens ?? 0\n tokens.output += usage?.completion_tokens ?? 0\n const content = (message.content ?? '').trim()\n if (content.length > 0) {\n agentMessages.push({ role: 'user', content })\n transcript.push({ role: 'user', content })\n return { content, tokens, usd: meter.costUsd - usdBefore }\n }\n }\n }\n throw new MultishotDriverEmptyError(turn)\n }\n\n return {\n conversation: {\n maxTurns,\n agentModel,\n driverModel,\n opener,\n driverSystemPrompt,\n agentTurn,\n driverTurn,\n },\n transcript,\n artifacts,\n toolCalls: () => toolCalls,\n }\n}\n\n/** Silent tool-calling agent turns surface to the driver as\n * \"Agent called tools: …\" so the simulated user can react to them. */\nfunction driverVisibleContent(msg: MultishotMessage): string | null {\n const text = msg.content.trim()\n if (text.length > 0) return text\n if (msg.role !== 'assistant' || !msg.toolCalls?.length) return null\n\n const toolNames = msg.toolCalls.map((call) => call.name.trim()).filter(Boolean)\n if (toolNames.length === 0) return 'Agent called tools.'\n return `Agent called ${toolNames.length === 1 ? 'tool' : 'tools'}: ${toolNames.join(', ')}.`\n}\n","// Generic judge runner — domain consumers configure dimensions + prompts.\n//\n// Three judge slots are conventional for multishot eval:\n// - conversation (scores the full transcript)\n// - codeReview (scores each code artifact)\n// - contentQuality (scores each non-code artifact)\n//\n// But the runJudge primitive is fully generic: any input maps to a score plus\n// explicit observed, estimated, or uncaptured cost.\n\nimport type { JudgeDimension, JudgeScore } from '../campaign/types'\nimport type { CostProvenance } from '../cost-ledger'\nimport type { LlmCallMetadata, LlmUsage } from '../llm-client'\nimport { estimateCost, isModelPriced } from '../metrics'\nimport type { MultishotTransport, MultishotTransportResponse } from './types'\n\n// Canonical declaration lives in campaign/types.ts. Multishot emits the same\n// shape on its producer-defined 0-10 scale.\nexport type { JudgeDimension, JudgeScore } from '../campaign/types'\n\nexport const DEFAULT_JUDGE_MODEL = 'openai/gpt-4o-mini'\n\nexport interface MultishotJudgeConfig<TInput> {\n /** Display name (for trace + log). */\n name: string\n /** Caller-owned execution for this judge's call. agent-eval issues no\n * provider request and holds no credential. */\n transport: MultishotTransport\n /** Model used for this judge. */\n model?: string\n /** 0-10 scored dimensions. */\n dimensions: JudgeDimension[]\n /** Judge system prompt — sets persona + JSON-only constraint. */\n systemPrompt: string\n /** Build the user prompt from the typed input. Must include \"Respond with\n * ONLY this JSON: { ... }\" listing each dimension key. */\n buildPrompt: (input: TInput) => string\n /** Maximum output tokens for the judge response. Defaults to 1500. */\n maxTokens?: number\n}\n\nexport interface JudgeRunResult {\n /** Semantic result; failed scores remain non-throwing so matrix aggregation can exclude them. */\n score: JudgeScore\n /** Cost of the completed call, separate from diagnostic provider metadata. */\n cost: CostProvenance\n}\n\nexport async function runJudge<TInput>(\n judge: MultishotJudgeConfig<TInput>,\n input: TInput,\n): Promise<JudgeRunResult> {\n const model = judge.model ?? DEFAULT_JUDGE_MODEL\n const prompt = judge.buildPrompt(input)\n let raw = ''\n let llmCall: LlmCallMetadata\n let cost: CostProvenance\n const startedAt = Date.now()\n try {\n const response = await judge.transport({\n model,\n temperature: 0,\n maxTokens: judge.maxTokens ?? 1500,\n messages: [\n { role: 'system', content: judge.systemPrompt },\n { role: 'user', content: prompt },\n ],\n })\n const call = judgeCallMetadata(response, model, Date.now() - startedAt)\n llmCall = call.llmCall\n cost = call.cost\n raw = (response.message.content ?? '').trim()\n } catch (err) {\n // failed:true lets consumers reading `.composite` keep working while\n // aggregators exclude this score from means instead of averaging a zero.\n return {\n score: {\n dimensions: {},\n composite: 0,\n failed: true,\n notes: `judge ${judge.name} call failed: ${err instanceof Error ? err.message : String(err)}`,\n llmCall: unknownJudgeCall(model, Date.now() - startedAt),\n },\n cost: { kind: 'uncaptured', usd: null },\n }\n }\n\n let parsed: Record<string, unknown> | null = null\n try {\n const cleaned = raw\n .replace(/^```json\\s*/i, '')\n .replace(/```\\s*$/, '')\n .trim()\n parsed = JSON.parse(cleaned) as Record<string, unknown>\n } catch {\n return {\n score: {\n dimensions: {},\n composite: 0,\n failed: true,\n notes: `judge ${judge.name} returned non-JSON: ${raw.slice(0, 200)}`,\n llmCall,\n },\n cost,\n }\n }\n\n const dimensions: Record<string, number> = {}\n let sum = 0\n for (const dim of judge.dimensions) {\n const v = Number(parsed[dim.key] ?? 0)\n const clamped = Number.isFinite(v) ? Math.max(0, Math.min(10, v)) : 0\n dimensions[dim.key] = clamped\n sum += clamped\n }\n return {\n score: {\n dimensions,\n composite: judge.dimensions.length === 0 ? 0 : sum / judge.dimensions.length,\n notes: typeof parsed.notes === 'string' ? parsed.notes : '',\n llmCall,\n },\n cost,\n }\n}\n\nfunction judgeCallMetadata(\n response: MultishotTransportResponse,\n requestedModel: string,\n durationMs: number,\n): {\n llmCall: LlmCallMetadata\n cost: CostProvenance\n} {\n const usage = canonicalUsage(response.usage)\n // The transport reports the served identity when it observed one. Falling\n // back to the requested id keeps attribution honest for a transport that\n // reported none; it is not proof that model answered.\n const model = response.model ?? requestedModel\n return {\n llmCall: {\n usage,\n costUsd: response.costUsd ?? null,\n model,\n durationMs,\n },\n cost:\n response.costUsd !== undefined\n ? { kind: 'observed', usd: response.costUsd }\n : usage.captured === false || !isModelPriced(model)\n ? { kind: 'uncaptured', usd: null }\n : {\n kind: 'estimated',\n usd: estimateCost(usage.promptTokens, usage.completionTokens, model),\n },\n }\n}\n\nfunction canonicalUsage(usage: MultishotTransportResponse['usage']): LlmUsage {\n const promptTokens = tokenCount(usage?.prompt_tokens)\n const completionTokens = tokenCount(usage?.completion_tokens)\n const captured = promptTokens !== undefined && completionTokens !== undefined\n return {\n promptTokens: promptTokens ?? 0,\n completionTokens: completionTokens ?? 0,\n totalTokens: (promptTokens ?? 0) + (completionTokens ?? 0),\n captured,\n }\n}\n\nfunction unknownJudgeCall(model: string, durationMs: number): LlmCallMetadata {\n return {\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0, captured: false },\n costUsd: null,\n model,\n durationMs,\n }\n}\n\nfunction tokenCount(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined\n}\n\n/** Convenience: stringified dimension list for inclusion in a judge prompt.\n * Returns lines like `- audience_fit: Does this match what the audience cares about? (0-10)`. */\nexport function renderDimensions(dims: readonly JudgeDimension[]): string {\n return dims.map((d) => `- ${d.key}: ${d.description}`).join('\\n')\n}\n\n/** Convenience: build the \"Respond with ONLY this JSON\" footer for a judge prompt. */\nexport function renderJsonFooter(dims: readonly JudgeDimension[]): string {\n const fields = dims.map((d) => `\"${d.key}\":N`).join(',')\n return `Respond with ONLY this JSON (no markdown, no preamble):\\n{${fields},\"notes\":\"1-2 sentence critique\"}`\n}\n","// Multi-turn driver-agent simulation with inline tool execution.\n//\n// The driver = LLM acting as the persona (reactive, non-deterministic).\n// The agent = the product agent under test, executed by the caller-supplied\n// transport with the profile's systemPrompt + the configured tools.\n// Tool calls execute inline via the configured executors and feed back\n// into the agent's message log so the agent integrates the result.\n//\n// agent-eval owns no model transport: every leg runs on a MultishotTransport\n// the caller supplies, so no provider credential enters this package.\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport { runMultishotConversation } from './conversation'\nimport type {\n MultishotPersona,\n MultishotResult,\n MultishotShape,\n MultishotToolDefinition,\n MultishotToolExecutor,\n MultishotTransport,\n} from './types'\n\nexport interface RunMultishotOptions<TPersona extends MultishotPersona> {\n profile: AgentProfile\n persona: TPersona\n /** Persona-shaping callbacks. Optional — omitted callbacks are derived from\n * the profile + persona payload, so a pure-profile call works. */\n shape?: MultishotShape<TPersona>\n /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */\n tools?: MultishotToolDefinition[]\n /** Map from tool name → executor invoked inline when the agent emits a tool_call. */\n toolExecutors?: Record<string, MultishotToolExecutor>\n /** Map from tool name → artifact type label written into MultishotArtifact.type.\n * Tools without a mapping still execute, but their results aren't surfaced as\n * typed artifacts (only as tool messages in the transcript). */\n artifactTypeFor?: (toolName: string) => string | undefined\n maxTurns?: number\n agentModel?: string\n driverModel?: string\n /** Fallback driver models tried when the primary simulated-user model returns empty twice. */\n driverFallbackModels?: string[]\n /** Maximum output tokens for the first agent call in each assistant turn. */\n agentMaxTokens?: number\n /** Maximum output tokens for agent follow-up calls after tool results. */\n toolFollowupMaxTokens?: number\n /** Maximum output tokens for each simulated-user driver response. */\n driverMaxTokens?: number\n /** Maximum tool calls the agent may dispatch inside one assistant turn. */\n maxToolDispatches?: number\n /** Caller-owned execution for the agent leg. Every agent inference step\n * runs through this function; `agentModel` names the model it receives. */\n agentTransport: MultishotTransport\n /** Caller-owned execution for the simulated-user driver leg. Driver model\n * fallback rotation still applies — the transport receives each candidate\n * model in turn. */\n driverTransport: MultishotTransport\n /** Caller-owned execution for the specialist leg the tool executors run.\n * Defaults to `agentTransport`. */\n toolTransport?: MultishotTransport\n signal?: AbortSignal\n}\n\n/** One multishot shot — the conversation engine `runMultishotMatrix` invokes\n * once per cell. `runMultishot` is the default implementation.\n *\n * An alternative engine (a graph-backed conversation, a replay of a recorded\n * transcript, a sandbox-hosted agent) implements this exact signature and\n * reaches the matrix through `RunMultishotMatrixOptions.runShot`. The matrix\n * keeps every other cell mechanic — cell fan-out, concurrency, the cost\n * ceiling, the judge slots, the cell composite, and the per-cell writers — so\n * swapping the engine needs no copy of the cell body. */\nexport type MultishotShot<TPersona extends MultishotPersona> = (\n opts: RunMultishotOptions<TPersona>,\n) => Promise<MultishotResult>\n\n/** The package's reference conversation engine, and the referent of three\n * things that stop working without it.\n *\n * 1. `runMultishotMatrix` runs it as the per-cell engine when the caller names\n * no `runShot`, so the matrix always has an engine to run.\n * 2. `golden.test.ts` proves the frozen records against it on every run, and\n * perturbs it to prove the records detect a change. Records checked only\n * against a replay of themselves prove nothing.\n * 3. The repo's recording command names it as `--engine`. The script defaults\n * no engine, so a version records whichever one the caller names — and a\n * record set minted from a consumer's engine would let a product's wiring\n * define this package's frozen contract.\n *\n * An alternative engine reaches the matrix through `runShot` and reaches the\n * records through `assertMultishotGoldenScenario`. Neither seam removes the\n * three roles above. */\nexport async function runMultishot<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n): Promise<MultishotResult> {\n return runMultishotConversation(opts, async (conversation) => {\n for (let turn = 0; turn < conversation.maxTurns; turn++) {\n await conversation.agentTurn(turn)\n if (turn < conversation.maxTurns - 1) await conversation.driverTurn(turn)\n }\n })\n}\n","// Multishot matrix wrapper — sweeps profiles × personas × reps, runs\n// the driver-agent loop per cell, applies up to three configured judges,\n// persists per-cell artifacts, and aggregates by axis.\n//\n// Uses runAgentMatrix from @tangle-network/agent-eval/matrix under the\n// hood so cell scheduling + concurrency + cost ceiling are unified with\n// other matrix consumers.\n\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { CostProvenance } from '../cost-ledger'\nimport type { MatrixResult } from '../matrix'\nimport { runAgentMatrix, withCellSpend } from '../matrix'\nimport { type MultishotJudgeConfig, type JudgeScore, runJudge } from './judges'\nimport { type MultishotShot, runMultishot } from './multishot'\nimport {\n assertMultishotShotResult,\n type MultishotArtifact,\n type MultishotMessage,\n type MultishotPersona,\n type MultishotShape,\n type MultishotToolDefinition,\n type MultishotToolExecutor,\n type MultishotTransport,\n} from './types'\n\nexport interface ConversationJudgeInput<TPersona extends MultishotPersona> {\n transcript: MultishotMessage[]\n persona: TPersona\n}\n\nexport interface ArtifactJudgeInput<TPersona extends MultishotPersona> {\n artifact: MultishotArtifact\n persona: TPersona\n}\n\nexport interface MultishotJudges<TPersona extends MultishotPersona> {\n /** Scores the full transcript end-to-end (always runs). */\n conversation: MultishotJudgeConfig<ConversationJudgeInput<TPersona>>\n /** Scores each code-type artifact. Optional — omit when domain has no code artifacts. */\n codeReview?: MultishotJudgeConfig<ArtifactJudgeInput<TPersona>>\n /** Scores each non-code (research/content/template) artifact. Optional. */\n contentQuality?: MultishotJudgeConfig<ArtifactJudgeInput<TPersona>>\n /** Which artifact types route to codeReview. Defaults to ['code']. */\n codeArtifactTypes?: string[]\n /** Which artifact types route to contentQuality. Defaults to ['research']. */\n contentArtifactTypes?: string[]\n}\n\nexport interface CellCompositeScore {\n composite: number\n conversation: JudgeScore\n codeReview?: {\n perArtifact: Array<JudgeScore & { turn: number; type: string }>\n composite: number\n }\n contentQuality?: {\n perArtifact: Array<JudgeScore & { turn: number; type: string }>\n composite: number\n }\n}\n\nexport interface RunMultishotMatrixOptions<TPersona extends MultishotPersona> {\n /** AgentProfile axis (matrix primary). */\n profiles: Array<{ id: string; value: AgentProfile }>\n /** Persona axis. */\n personas: TPersona[]\n /** Persona-shaping callbacks. Optional — omitted callbacks are derived per\n * cell from that cell's profile + persona payload (pure-profile path). */\n shape?: MultishotShape<TPersona>\n /** Judge configurations. */\n judges: MultishotJudges<TPersona>\n /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */\n tools?: MultishotToolDefinition[]\n /** Map from tool name → inline executor. Must align with `tools`. */\n toolExecutors?: Record<string, MultishotToolExecutor>\n /** Tool name → artifact type label. Defaults to research/code mapping. */\n artifactTypeFor?: (toolName: string) => string | undefined\n /** Where per-cell artifacts land. Cells write to `<runDir>/<profileId>/<personaId>/rep-N/`. */\n runDir: string\n /** Replicates per (profile, persona) cell. */\n reps?: number\n /** Max conversation turns per cell. */\n maxTurns?: number\n /** Maximum tool calls the agent may dispatch inside one assistant turn. */\n maxToolDispatches?: number\n /** Max concurrent cells. */\n maxConcurrency?: number\n /** Total $ ceiling across the matrix; cells aborted past this. */\n costCeiling?: number\n /** Upper bound on what one cell can spend. A cell whose cost is a subtotal\n * is charged this bound against `costCeiling` instead of its known amount,\n * so hidden spend cannot walk the run past its budget. */\n maxCellCostUsd?: number\n /** Agent model. */\n agentModel?: string\n /** Driver model. */\n driverModel?: string\n /** Fallback driver models tried when the primary simulated-user model returns empty twice. */\n driverFallbackModels?: string[]\n /** Maximum output tokens for the first agent call in each assistant turn. */\n agentMaxTokens?: number\n /** Maximum output tokens for agent follow-up calls after tool results. */\n toolFollowupMaxTokens?: number\n /** Maximum output tokens for each simulated-user driver response. */\n driverMaxTokens?: number\n /** Maximum output tokens for each judge response. */\n judgeMaxTokens?: number\n /** Caller-owned execution for the agent leg of every cell (see\n * RunMultishotOptions.agentTransport). Judges are unaffected; each judge\n * carries its own transport in MultishotJudges. */\n agentTransport: MultishotTransport\n /** Caller-owned execution for the simulated-user driver leg of every cell. */\n driverTransport: MultishotTransport\n /** Caller-owned execution for the specialist leg the tool executors run in\n * every cell. Defaults to `agentTransport`. */\n toolTransport?: MultishotTransport\n /** Conversation engine for every cell. Defaults to `runMultishot`.\n *\n * The matrix owns everything around the shot — cell fan-out, concurrency,\n * the cost ceiling, the judge slots, the cell composite, the per-cell\n * artifact writers and the run summary — and forwards the whole cell input\n * to this function, so an alternative engine replaces ONLY the\n * conversation. Every option on this interface that `runMultishot` accepts\n * reaches the shot unchanged. `RunMultishotOptions.signal` has no\n * matrix-level counterpart and is not forwarded; a shot owns its own\n * cancellation.\n *\n * A shot that resolves with a value outside `MultishotResult` throws\n * `MultishotShotResultError` for that cell. The default engine is never\n * used as a fallback. */\n runShot?: MultishotShot<TPersona>\n}\n\n/** Per-cell output the multishot matrix records in `MatrixResult.cells`.\n * A consumer that supplies its own `runShot` reads the matrix through this\n * type instead of declaring a structural copy. */\nexport interface MultishotCellOutput {\n turns: number\n toolCalls: number\n artifactCount: number\n}\n\ninterface ArtifactJudgeRun {\n score: JudgeScore & { turn: number; type: string }\n cost: CostProvenance\n}\n\n/** Mean composite over non-failed scores. `0` when the list is empty (a\n * configured judge with nothing to score contributes 0, matching the cell\n * composite's long-standing semantics); `null` when scores exist but every\n * one failed — no signal, so the slot must be EXCLUDED from the cell mean\n * rather than dragging it to zero. */\nfunction meanCompositeExcludingFailed(scores: ReadonlyArray<JudgeScore>): number | null {\n if (scores.length === 0) return 0\n const live = scores.filter((s) => !s.failed)\n if (live.length === 0) return null\n return live.reduce((sum, s) => sum + s.composite, 0) / live.length\n}\n\nexport interface CellCompositeInput {\n conversation: JudgeScore\n /** Present iff the codeReview judge is configured. */\n codeReviews?: ReadonlyArray<JudgeScore>\n /** Present iff the contentQuality judge is configured. */\n contentReviews?: ReadonlyArray<JudgeScore>\n}\n\n/** Cell composite = mean over configured judge slots, excluding failed\n * scores: a failed conversation judge or an all-failed artifact slot carries\n * no signal and is dropped from the mean. `composite` is 0 only when EVERY\n * configured slot failed (`allJudgesFailed` distinguishes that from a real\n * zero). Pure — exported for deterministic testing. */\nexport function computeCellComposite(input: CellCompositeInput): {\n composite: number\n codeComposite: number\n contentComposite: number\n allJudgesFailed: boolean\n} {\n const contributions: number[] = []\n if (!input.conversation.failed) contributions.push(input.conversation.composite)\n\n const codeMean = input.codeReviews ? meanCompositeExcludingFailed(input.codeReviews) : undefined\n if (typeof codeMean === 'number') contributions.push(codeMean)\n const contentMean = input.contentReviews\n ? meanCompositeExcludingFailed(input.contentReviews)\n : undefined\n if (typeof contentMean === 'number') contributions.push(contentMean)\n\n return {\n composite:\n contributions.length === 0\n ? 0\n : contributions.reduce((s, v) => s + v, 0) / contributions.length,\n codeComposite: codeMean ?? 0,\n contentComposite: contentMean ?? 0,\n allJudgesFailed: contributions.length === 0,\n }\n}\n\nexport interface RunMultishotMatrixResult {\n matrix: MatrixResult<MultishotCellOutput>\n}\n\nexport async function runMultishotMatrix<TPersona extends MultishotPersona>(\n opts: RunMultishotMatrixOptions<TPersona>,\n): Promise<RunMultishotMatrixResult> {\n const codeTypes = new Set(opts.judges.codeArtifactTypes ?? ['code'])\n const contentTypes = new Set(opts.judges.contentArtifactTypes ?? ['research'])\n const runShot: MultishotShot<TPersona> = opts.runShot ?? runMultishot\n mkdirSync(opts.runDir, { recursive: true })\n\n const matrix = await runAgentMatrix<MultishotCellOutput>({\n axes: [\n { name: 'profile', values: opts.profiles },\n { name: 'persona', values: opts.personas.map((p) => ({ id: p.id, value: p })) },\n ],\n reps: opts.reps ?? 1,\n maxConcurrency: opts.maxConcurrency ?? 2,\n costCeiling: opts.costCeiling,\n maxCellCostUsd: opts.maxCellCostUsd,\n async runCell(cell) {\n const cellStartedAt = Date.now()\n const profile = cell.axes.profile?.value as AgentProfile\n const persona = cell.axes.persona?.value as TPersona\n const profileId = String(cell.axes.profile?.id ?? 'unknown')\n const personaId = String(cell.axes.persona?.id ?? 'unknown')\n\n // A shot that throws declares its own spend (see `runMultishot`). Rethrow\n // it untouched: a shot that declared nothing spent an unknown amount, and\n // claiming a number here would report a fabricated total.\n const sim = await runShot({\n profile,\n persona,\n shape: opts.shape,\n tools: opts.tools,\n toolExecutors: opts.toolExecutors,\n artifactTypeFor: opts.artifactTypeFor,\n maxTurns: opts.maxTurns,\n maxToolDispatches: opts.maxToolDispatches,\n agentModel: opts.agentModel,\n driverModel: opts.driverModel,\n driverFallbackModels: opts.driverFallbackModels,\n agentMaxTokens: opts.agentMaxTokens,\n toolFollowupMaxTokens: opts.toolFollowupMaxTokens,\n driverMaxTokens: opts.driverMaxTokens,\n agentTransport: opts.agentTransport,\n driverTransport: opts.driverTransport,\n toolTransport: opts.toolTransport,\n })\n // Everything from here on runs with the shot's spend already committed.\n // A throw past this line must carry it, or the money leaves the matrix's\n // cumulative sum and the cost ceiling under-counts the run.\n const shotCostUsd = shotCostSubtotal(sim)\n // A shot that says nothing about provenance is taken at its word, which\n // is how every engine written before the field behaved.\n const shotCostComplete = sim?.costProvenance?.kind !== 'uncaptured'\n let judgeCostUsd = 0\n let judgeCostComplete = false\n // Where the cell is, so a throw declares the right completeness: before\n // the judges only the shot has spent, while they are in flight their\n // spend is unknown, and after they settle their receipts decide.\n let phase: 'validate' | 'judging' | 'scoring' = 'validate'\n try {\n assertMultishotShotResult(sim)\n\n const codeArtifacts = sim.artifacts.filter((a) => codeTypes.has(a.type))\n const contentArtifacts = sim.artifacts.filter((a) => contentTypes.has(a.type))\n\n phase = 'judging'\n const [conversationRun, codeReviewRuns, contentReviewRuns] = await Promise.all([\n runJudge(withJudgeMaxTokens(opts.judges.conversation, opts.judgeMaxTokens), {\n transcript: sim.transcript,\n persona,\n }),\n opts.judges.codeReview\n ? Promise.all(\n codeArtifacts.map((artifact) =>\n runJudge(withJudgeMaxTokens(opts.judges.codeReview!, opts.judgeMaxTokens), {\n artifact,\n persona,\n }).then((result) => ({\n score: {\n ...result.score,\n turn: artifact.turn,\n type: artifact.type,\n },\n cost: result.cost,\n })),\n ),\n )\n : Promise.resolve([] as ArtifactJudgeRun[]),\n opts.judges.contentQuality\n ? Promise.all(\n contentArtifacts.map((artifact) =>\n runJudge(withJudgeMaxTokens(opts.judges.contentQuality!, opts.judgeMaxTokens), {\n artifact,\n persona,\n }).then((result) => ({\n score: {\n ...result.score,\n turn: artifact.turn,\n type: artifact.type,\n },\n cost: result.cost,\n })),\n ),\n )\n : Promise.resolve([] as ArtifactJudgeRun[]),\n ])\n const judgeRuns = [conversationRun, ...codeReviewRuns, ...contentReviewRuns]\n judgeCostUsd = judgeRuns.reduce((sum, run) => sum + (run.cost.usd ?? 0), 0)\n judgeCostComplete = judgeRuns.every((run) => run.cost.kind !== 'uncaptured')\n phase = 'scoring'\n\n const conversation = conversationRun.score\n const codeReviews = codeReviewRuns.map((run) => run.score)\n const contentReviews = contentReviewRuns.map((run) => run.score)\n\n const { composite, codeComposite, contentComposite, allJudgesFailed } =\n computeCellComposite({\n conversation,\n codeReviews: opts.judges.codeReview ? codeReviews : undefined,\n contentReviews: opts.judges.contentQuality ? contentReviews : undefined,\n })\n\n const cellScore: CellCompositeScore = { composite, conversation }\n if (opts.judges.codeReview)\n cellScore.codeReview = { perArtifact: codeReviews, composite: codeComposite }\n if (opts.judges.contentQuality)\n cellScore.contentQuality = { perArtifact: contentReviews, composite: contentComposite }\n\n const cellDir = join(opts.runDir, profileId, personaId, `rep-${cell.rep}`)\n mkdirSync(cellDir, { recursive: true })\n writeFileSync(join(cellDir, 'transcript.json'), JSON.stringify(sim.transcript, null, 2))\n writeFileSync(join(cellDir, 'artifacts.json'), JSON.stringify(sim.artifacts, null, 2))\n writeFileSync(join(cellDir, 'scores.json'), JSON.stringify(cellScore, null, 2))\n\n const notes = [`convo=${conversation.composite.toFixed(1)}`]\n if (opts.judges.codeReview) notes.push(`code=${codeComposite.toFixed(1)}`)\n if (opts.judges.contentQuality) notes.push(`content=${contentComposite.toFixed(1)}`)\n if (allJudgesFailed) notes.push('all-judges-failed')\n if (!judgeCostComplete) notes.push('judge-cost-incomplete')\n\n return {\n output: {\n turns: sim.transcript.length,\n toolCalls: sim.toolCalls,\n artifactCount: sim.artifacts.length,\n },\n verdict: { valid: composite >= 5, score: composite, notes: notes.join(' ') },\n costUsd: sim.costUsd + judgeCostUsd,\n // Either leg can leave the cell total a subtotal: a judge whose cost\n // the router never reported, or a shot that declared its own spend\n // uncaptured. The matrix counts the known part toward the ceiling and\n // reports the cell as under-counted rather than presenting the sum as\n // complete.\n costProvenance:\n judgeCostComplete && shotCostComplete\n ? { kind: 'estimated', usd: sim.costUsd + judgeCostUsd }\n : { kind: 'uncaptured', usd: null },\n durationMs: sim.durationMs,\n }\n } catch (err) {\n // No usable shot subtotal means the cell's spend is genuinely unknown;\n // rethrow untouched so the matrix records it as uncaptured instead of\n // billing a number this frame cannot support.\n if (shotCostUsd === undefined) throw err\n throw withCellSpend(err, {\n costUsd: shotCostUsd + judgeCostUsd,\n durationMs: Date.now() - cellStartedAt,\n // The judges bill before they settle, so a throw among them leaves a\n // subtotal. Before they start, and after they settle with every\n // receipt captured, the amount is the cell's whole spend — unless the\n // shot already declared its own part incomplete.\n kind:\n shotCostComplete && (phase === 'validate' || (phase === 'scoring' && judgeCostComplete))\n ? 'estimated'\n : 'uncaptured',\n })\n }\n },\n })\n\n // Persist top-level summary.\n const summary = {\n cells: matrix.summary.totalCells,\n passRate: matrix.summary.overallPassRate,\n meanScore: matrix.summary.overallMeanScore,\n totalCostUsd: matrix.summary.totalCostUsd,\n costUncapturedCells: matrix.summary.costUncapturedCells,\n ceilingChargedUsd: matrix.summary.ceilingChargedUsd,\n durationMs: matrix.summary.durationMs,\n runsExecuted: matrix.summary.runsExecuted,\n cellsSkipped: matrix.summary.cellsSkipped,\n byProfile: matrix.byAxis.profile,\n byPersona: matrix.byAxis.persona,\n }\n writeFileSync(join(opts.runDir, 'summary.json'), JSON.stringify(summary, null, 2))\n\n // A reader of the on-disk summary must not take the cost line as the run's\n // whole spend when some cells reported only a subtotal.\n const uncaptured = matrix.summary.costUncapturedCells\n const costLabel = uncaptured > 0 ? 'Cost (at least)' : 'Cost'\n\n const md: string[] = [\n `# Multishot matrix`,\n ``,\n `**Cells**: ${matrix.summary.totalCells} | **Pass rate**: ${(matrix.summary.overallPassRate * 100).toFixed(0)}% | **Mean**: ${matrix.summary.overallMeanScore.toFixed(2)} | **${costLabel}**: $${matrix.summary.totalCostUsd.toFixed(2)} | **Duration**: ${(matrix.summary.durationMs / 1000).toFixed(0)}s`,\n ``,\n ...(uncaptured > 0\n ? [\n `> ${uncaptured} of ${matrix.summary.runsExecuted} cells reported a cost subtotal, not a total. Real spend is higher than every cost figure below.`,\n ``,\n ]\n : []),\n `## By profile`,\n ``,\n '| profile | pass | mean | cost |',\n '|---|---|---|---|',\n ...Object.entries(matrix.byAxis.profile ?? {}).map(\n ([id, s]) =>\n `| ${id} | ${(s.passRate * 100).toFixed(0)}% | ${s.meanScore.toFixed(2)} | $${s.totalCostUsd.toFixed(2)} |`,\n ),\n ``,\n `## By persona`,\n ``,\n '| persona | pass | mean | cost |',\n '|---|---|---|---|',\n ...Object.entries(matrix.byAxis.persona ?? {}).map(\n ([id, s]) =>\n `| ${id} | ${(s.passRate * 100).toFixed(0)}% | ${s.meanScore.toFixed(2)} | $${s.totalCostUsd.toFixed(2)} |`,\n ),\n ``,\n ]\n writeFileSync(join(opts.runDir, 'summary.md'), md.join('\\n'))\n\n return { matrix }\n}\n\n/** The shot's own spend, when the value it resolved with reports a usable\n * amount. `undefined` when it does not — a malformed shot result is exactly\n * the case where the number cannot be trusted, and billing a wrong figure is\n * worse than recording the cell as uncaptured. */\nfunction shotCostSubtotal(\n sim: { costUsd?: unknown; costProvenance?: CostProvenance } | null | undefined,\n): number | undefined {\n const value = sim?.costUsd\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined\n}\n\nfunction withJudgeMaxTokens<TInput>(\n judge: MultishotJudgeConfig<TInput>,\n maxTokens: number | undefined,\n): MultishotJudgeConfig<TInput> {\n if (maxTokens === undefined || judge.maxTokens !== undefined) return judge\n return { ...judge, maxTokens }\n}\n"],"mappings":";;;;;;;;;;;;;AASA,SAAgB,sBACd,OACA,OACQ;CACR,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,WAAW,MAAM,iBAAiB;CACxC,MAAM,YAAY,MAAM,qBAAqB;CAC7C,IAAI,UAAU;CACd,IAAI,WAAW;CACf,IAAI,MAAM,SAAS,aAAa,GAAG;EACjC,UAAU;EACV,WAAW;CACb,OAAO,IAAI,MAAM,SAAS,SAAS,KAAK,MAAM,SAAS,eAAe,GAAG;EACvE,UAAU;EACV,WAAW;CACb,OAAO,IAAI,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,UAAU,GAAG;EACxF,UAAU;EACV,WAAW;CACb;CACA,QAAQ,WAAW,UAAU,YAAY,YAAY;AACvD;;;ACnBA,MAAM,2BAA2B;AACjC,MAAa,sBAAsB;AAgBnC,MAAM,4BACJ;AAEF,MAAM,uBACJ;AAEF,MAAM,iCAA0D;CAC9D,MAAM;CACN,UAAU;EACR,MAAM;EACN,aACE;EACF,YAAY;GACV,MAAM;GACN,YAAY;IACV,UAAU;KAAE,MAAM;KAAU,aAAa;IAAgC;IACzE,OAAO;KACL,MAAM;KACN,aAAa;IACf;GACF;GACA,UAAU,CAAC,UAAU;EACvB;CACF;AACF;AAEA,MAAM,6BAAsD;CAC1D,MAAM;CACN,UAAU;EACR,MAAM;EACN,aACE;EACF,YAAY;GACV,MAAM;GACN,YAAY;IACV,MAAM;KAAE,MAAM;KAAU,aAAa;IAAgC;IACrE,UAAU;KACR,MAAM;KACN,aAAa;IACf;GACF;GACA,UAAU,CAAC,MAAM;EACnB;CACF;AACF;AAEA,SAAS,uBAAuB,SAAkC,CAAC,GAA0B;CAC3F,MAAM,eAAe,OAAO,gBAAgB;CAC5C,MAAM,QAAQ,OAAO,SAAS;CAC9B,OAAO,OAAO,MAAM,QAAQ;EAC1B,MAAM,WAAW,OAAO,KAAK,YAAY,EAAE;EAC3C,MAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI,KAAA;EAChD,MAAM,EAAE,SAAS,OAAO,YAAY,MAAM,IAAI,UAAU;GACtD;GACA,aAAa;GACb,WAAW;GACX,UAAU,CACR;IAAE,MAAM;IAAU,SAAS;GAAa,GACxC;IAAE,MAAM;IAAQ,SAAS,aAAa,WAAW,QAAQ,YAAY,UAAU;GAAK,CACtF;GACA,QAAQ,IAAI;EACd,CAAC;EACD,OAAO;GACL,SAAS,QAAQ,WAAW;GAC5B,SAAS,WAAW,sBAAsB,OAAO,KAAK;EACxD;CACF;AACF;AAEA,SAAS,mBAAmB,SAA6B,CAAC,GAA0B;CAClF,MAAM,eAAe,OAAO,gBAAgB;CAC5C,MAAM,QAAQ,OAAO,SAAA;CACrB,OAAO,OAAO,MAAM,QAAQ;EAC1B,MAAM,OAAO,OAAO,KAAK,QAAQ,EAAE;EACnC,MAAM,WAAW,KAAK,WAAW,OAAO,KAAK,QAAQ,IAAI;EACzD,MAAM,EAAE,SAAS,OAAO,YAAY,MAAM,IAAI,UAAU;GACtD;GACA,aAAa;GACb,WAAW;GACX,UAAU,CACR;IAAE,MAAM;IAAU,SAAS,GAAG,aAAa,gBAAgB;GAAW,GACtE;IAAE,MAAM;IAAQ,SAAS,YAAY;GAAO,CAC9C;GACA,QAAQ,IAAI;EACd,CAAC;EACD,OAAO;GACL,SAAS,QAAQ,WAAW;GAC5B,SAAS,WAAW,sBAAsB,OAAO,KAAK;EACxD;CACF;AACF;AAgBA,SAAgB,uBAAuB,SAA6B,CAAC,GAAuB;CAC1F,OAAO;EACL,OAAO,CAAC,gCAAgC,0BAA0B;EAClE,WAAW;GACT,mBAAmB,uBAAuB,OAAO,QAAQ;GACzD,eAAe,mBAAmB,OAAO,IAAI;EAC/C;EACA,kBAAkB,SAChB,SAAS,sBAAsB,aAAa,SAAS,kBAAkB,SAAS,KAAA;CACpF;AACF;;;;;ACjIA,SAAS,mBAAmB,SAAmC;CAC7D,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAAG;EAClD,IAAI,QAAQ,QAAQ,UAAU,KAAA,GAAW;EACzC,MAAM,WACJ,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,YACvE,OAAO,KAAK,IACZ,KAAK,UAAU,KAAK;EAC1B,MAAM,KAAK,KAAK,IAAI,IAAI,UAAU;CACpC;CACA,OAAO,MAAM,KAAK,IAAI;AACxB;;;AAIA,SAAS,uBAAuB,SAAuB,SAAmC;CACxF,MAAM,QAAQ,mBAAmB,OAAO;CAExC,OAAO;EACL,4BAFuB,QAAQ,eAAe,QAAQ,QAAQ,YAEjB;EAC7C,MAAM,SAAS,IAAI,QAAQ,qCAAqC,QAAQ,GAAG;EAC3E;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;;;AAIA,SAAS,mCACP,SACA,SACQ;CACR,MAAM,QAAQ,mBAAmB,OAAO;CACxC,MAAM,mBAAmB,QAAQ,eAAe,QAAQ,QAAQ;CAChE,OAAO;EACL,gDAAgD,QAAQ,GAAG,gBAAgB,iBAAiB;EAC5F,MAAM,SAAS,IAAI,iBAAiB,UAAU;EAC9C;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CACE,QAAQ,UAAU,MAAM,SAAS,CAAC,CAAC,CACnC,KAAK,IAAI;AACd;;;AAIA,SAAgB,wBACd,SACA,OACoC;CACpC,OAAO;EACL,aAAa,OAAO,iBAAiB,YAAY,uBAAuB,SAAS,OAAO;EACxF,yBACE,OAAO,6BACL,YAAY,mCAAmC,SAAS,OAAO;CACrE;AACF;;;;;;;;;;ACMA,eAAsB,yBACpB,MACA,OAC0B;CAC1B,MAAM,QAA2B;EAAE,SAAS;EAAG,WAAW,KAAK,IAAI;EAAG,YAAY;CAAM;CACxF,IAAI;EACF,MAAM,QAAQ,iBAAiB,MAAM,KAAK;EAC1C,MAAM,MAAM,MAAM,YAAY;EAC9B,OAAO;GACL,YAAY,MAAM;GAClB,WAAW,MAAM;GACjB,WAAW,MAAM,UAAU;GAC3B,YAAY,KAAK,IAAI,IAAI,MAAM;GAC/B,SAAS,MAAM;GAIf,gBAAgB,MAAM,aAClB;IAAE,MAAM;IAAc,KAAK;GAAK,IAChC;IAAE,MAAM;IAAa,KAAK,MAAM;GAAQ;EAC9C;CACF,SAAS,KAAK;EACZ,MAAM,cAAc,KAAK;GACvB,SAAS,MAAM;GACf,YAAY,KAAK,IAAI,IAAI,MAAM;GAC/B,MAAM,MAAM,aAAa,eAAe;EAC1C,CAAC;CACH;AACF;AAEA,SAAS,iBACP,MACA,OAMA;CACA,MAAM,WAAW,KAAK,YAAY;CAClC,MAAM,oBAAoB,KAAK,qBAAqB;CACpD,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,cAAc,KAAK,eAAe;CACxC,MAAM,eAAe,CAAC,aAAa,GAAI,KAAK,wBAAwB,CAAC,CAAE;CACvE,MAAM,iBAAiB,KAAK,kBAAkB;CAC9C,MAAM,wBAAwB,KAAK,yBAAyB;CAC5D,MAAM,kBAAkB,KAAK,mBAAmB;CAEhD,MAAM,SACJ,KAAK,SAAS,KAAK,gBACf;EACE,OAAO,KAAK;EACZ,WAAW,KAAK;EAChB,iBAAiB,KAAK,0BAA0B,KAAA;CAClD,IACA,uBAAuB;CAC7B,MAAM,QAAQ,KAAK,SAAS,OAAO;CACnC,MAAM,YAAY,KAAK,iBAAiB,OAAO;CAC/C,MAAM,kBAAkB,KAAK,mBAAmB,OAAO;CAEvD,MAAM,iBAAiB,KAAK;CAC5B,MAAM,kBAAkB,KAAK;CAC7B,MAAM,gBAAgB,KAAK,iBAAiB;CAE5C,MAAM,QAAQ,wBAAwB,KAAK,SAAS,KAAK,KAAK;CAE9D,MAAM,aAAiC,CAAC;CACxC,MAAM,YAAiC,CAAC;CACxC,IAAI,YAAY;CAEhB,MAAM,SAAS,MAAM,YAAY,KAAK,OAAO;CAC7C,WAAW,KAAK;EAAE,MAAM;EAAQ,SAAS;CAAO,CAAC;CAKjD,MAAM,gBAAgD,CACpD;EAAE,MAAM;EAAU,SAJC,CAAC,KAAK,QAAQ,QAAQ,cAAc,KAAK,QAAQ,QAAQ,kBAAkB,CAAC,CAC9F,QAAQ,UAA2B,QAAQ,KAAK,CAAC,CAAC,CAClD,KAAK,MAEgC;CAAE,GACxC;EAAE,MAAM;EAAQ,SAAS;CAAO,CAClC;CACA,MAAM,qBAAqB,MAAM,wBAAwB,KAAK,OAAO;CAErE,eAAe,UAAU,MAA0C;EACjE,IAAI,KAAK,QAAQ,SAAS,MAAM,IAAI,MAAM,mBAAmB;EAC7D,MAAM,YAAY,MAAM;EACxB,MAAM,SAAS;GAAE,OAAO;GAAG,QAAQ;EAAE;EACrC,IAAI,qBAAqB;EACzB,OAAO,MAAM;GACX,MAAM,EACJ,SAAS,UACT,OAAO,YACP,SAAS,iBACP,MAAM,eAAe;IACvB,OAAO;IACP,UAAU;IACV;IACA,aAAa;IACb,WAAW,uBAAuB,IAAI,iBAAiB;IACvD,QAAQ,KAAK;GACf,CAAC;GACD,MAAM,WAAW,gBAAgB,sBAAsB,YAAY,UAAU;GAC7E,IAAI,iBAAiB,KAAA,KAAa,eAAe,KAAA,GAAW,MAAM,aAAa;GAC/E,OAAO,SAAS,YAAY,iBAAiB;GAC7C,OAAO,UAAU,YAAY,qBAAqB;GAElD,MAAM,aAAa,SAAS,WAAW,GAAA,CAAI,KAAK;GAChD,MAAM,kBAAkB,SAAS,cAAc,CAAC,EAAA,CAAG,KAAK,QAAQ;IAC9D,IAAI,GAAG;IACP,MAAM,GAAG,SAAS;IAClB,aAAa;KACX,IAAI;MACF,OAAO,KAAK,MAAM,GAAG,SAAS,SAAS;KACzC,QAAQ;MACN,OAAO,CAAC;KACV;IACF,EAAA,CAAG;GACL,EAAE;GAEF,cAAc,KAAK;IACjB,MAAM;IACN,SAAS,aAAa;IACtB,GAAI,SAAS,YAAY,SAAS,EAAE,YAAY,SAAS,WAAW,IAAI,CAAC;GAC3E,CAAC;GACD,WAAW,KAAK;IACd,MAAM;IACN,SAAS;IACT,WAAW,eAAe,SAAS,IAAI,iBAAiB,KAAA;GAC1D,CAAC;GAED,IAAI,eAAe,WAAW,GAAG;GACjC,sBAAsB,eAAe;GACrC,IAAI,qBAAqB,mBACvB,MAAM,IAAI,MACR,0CAA0C,mBAAmB,GAAG,kBAAkB,YAAY,MAChG;GAGF,KAAK,MAAM,MAAM,gBAAgB;IAC/B;IACA,IAAI,aAAa;IACjB,IAAI;KACF,MAAM,WAAW,UAAU,GAAG;KAC9B,IAAI,CAAC,UACH,aAAa,KAAK,UAAU,EAAE,OAAO,gBAAgB,GAAG,OAAO,CAAC;UAC3D;MACL,MAAM,IAAI,MAAM,SAAS,GAAG,MAAM;OAAE,WAAW;OAAe,QAAQ,KAAK;MAAO,CAAC;MACnF,aAAa,EAAE;MACf,MAAM,WAAW,EAAE;MACnB,MAAM,eAAe,gBAAgB,GAAG,IAAI;MAC5C,IAAI,cACF,UAAU,KAAK;OACb,MAAM;OACN;OACA,YAAY;QAAE,MAAM,GAAG;QAAM,MAAM,GAAG;OAAK;OAC3C,SAAS;MACX,CAAC;KAEL;IACF,SAAS,KAAK;KACZ,IAAI,eAAe,yBAAyB,MAAM;KAClD,aAAa,KAAK,UAAU,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;IACzF;IACA,cAAc,KAAK;KAAE,MAAM;KAAQ,cAAc,GAAG;KAAI,SAAS,cAAc;IAAO,CAAC;IACvF,WAAW,KAAK;KAAE,MAAM;KAAQ,SAAS,cAAc;KAAQ,YAAY,GAAG;IAAG,CAAC;GACpF;EACF;EACA,OAAO;GAAE;GAAQ,KAAK,MAAM,UAAU;EAAU;CAClD;CAKA,eAAe,WAAW,MAAgE;EACxF,MAAM,YAAY,MAAM;EAIxB,MAAM,iBAAiD,CACrD;GAAE,MAAM;GAAU,SAAS;EAAmB,CAChD;EACA,KAAK,MAAM,OAAO,YAAY;GAC5B,IAAI,IAAI,SAAS,QAAQ;GACzB,MAAM,UAAU,qBAAqB,GAAG;GACxC,IAAI,CAAC,SAAS;GACd,IAAI,IAAI,SAAS,aAAa,eAAe,KAAK;IAAE,MAAM;IAAQ;GAAQ,CAAC;QACtE,IAAI,IAAI,SAAS,QAAQ,eAAe,KAAK;IAAE,MAAM;IAAa;GAAQ,CAAC;EAClF;EAGA,MAAM,SAAS;GAAE,OAAO;GAAG,QAAQ;EAAE;EACrC,KAAK,MAAM,SAAS,cAClB,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW;GAC5C,MAAM,EAAE,SAAS,OAAO,YAAY,MAAM,gBAAgB;IACxD;IACA,UAAU;IACV,aAAa;IACb,WAAW;IACX,QAAQ,KAAK;GACf,CAAC;GACD,MAAM,WAAW,WAAW,sBAAsB,OAAO,KAAK;GAC9D,IAAI,YAAY,KAAA,KAAa,UAAU,KAAA,GAAW,MAAM,aAAa;GACrE,OAAO,SAAS,OAAO,iBAAiB;GACxC,OAAO,UAAU,OAAO,qBAAqB;GAC7C,MAAM,WAAW,QAAQ,WAAW,GAAA,CAAI,KAAK;GAC7C,IAAI,QAAQ,SAAS,GAAG;IACtB,cAAc,KAAK;KAAE,MAAM;KAAQ;IAAQ,CAAC;IAC5C,WAAW,KAAK;KAAE,MAAM;KAAQ;IAAQ,CAAC;IACzC,OAAO;KAAE;KAAS;KAAQ,KAAK,MAAM,UAAU;IAAU;GAC3D;EACF;EAEF,MAAM,IAAI,0BAA0B,IAAI;CAC1C;CAEA,OAAO;EACL,cAAc;GACZ;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA;EACA;EACA,iBAAiB;CACnB;AACF;;;AAIA,SAAS,qBAAqB,KAAsC;CAClE,MAAM,OAAO,IAAI,QAAQ,KAAK;CAC9B,IAAI,KAAK,SAAS,GAAG,OAAO;CAC5B,IAAI,IAAI,SAAS,eAAe,CAAC,IAAI,WAAW,QAAQ,OAAO;CAE/D,MAAM,YAAY,IAAI,UAAU,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;CAC9E,IAAI,UAAU,WAAW,GAAG,OAAO;CACnC,OAAO,gBAAgB,UAAU,WAAW,IAAI,SAAS,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE;AAC5F;;;AC7SA,MAAa,sBAAsB;AA4BnC,eAAsB,SACpB,OACA,OACyB;CACzB,MAAM,QAAQ,MAAM,SAAA;CACpB,MAAM,SAAS,MAAM,YAAY,KAAK;CACtC,IAAI,MAAM;CACV,IAAI;CACJ,IAAI;CACJ,MAAM,YAAY,KAAK,IAAI;CAC3B,IAAI;EACF,MAAM,WAAW,MAAM,MAAM,UAAU;GACrC;GACA,aAAa;GACb,WAAW,MAAM,aAAa;GAC9B,UAAU,CACR;IAAE,MAAM;IAAU,SAAS,MAAM;GAAa,GAC9C;IAAE,MAAM;IAAQ,SAAS;GAAO,CAClC;EACF,CAAC;EACD,MAAM,OAAO,kBAAkB,UAAU,OAAO,KAAK,IAAI,IAAI,SAAS;EACtE,UAAU,KAAK;EACf,OAAO,KAAK;EACZ,OAAO,SAAS,QAAQ,WAAW,GAAA,CAAI,KAAK;CAC9C,SAAS,KAAK;EAGZ,OAAO;GACL,OAAO;IACL,YAAY,CAAC;IACb,WAAW;IACX,QAAQ;IACR,OAAO,SAAS,MAAM,KAAK,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IAC1F,SAAS,iBAAiB,OAAO,KAAK,IAAI,IAAI,SAAS;GACzD;GACA,MAAM;IAAE,MAAM;IAAc,KAAK;GAAK;EACxC;CACF;CAEA,IAAI,SAAyC;CAC7C,IAAI;EACF,MAAM,UAAU,IACb,QAAQ,gBAAgB,EAAE,CAAC,CAC3B,QAAQ,WAAW,EAAE,CAAC,CACtB,KAAK;EACR,SAAS,KAAK,MAAM,OAAO;CAC7B,QAAQ;EACN,OAAO;GACL,OAAO;IACL,YAAY,CAAC;IACb,WAAW;IACX,QAAQ;IACR,OAAO,SAAS,MAAM,KAAK,sBAAsB,IAAI,MAAM,GAAG,GAAG;IACjE;GACF;GACA;EACF;CACF;CAEA,MAAM,aAAqC,CAAC;CAC5C,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,MAAM,YAAY;EAClC,MAAM,IAAI,OAAO,OAAO,IAAI,QAAQ,CAAC;EACrC,MAAM,UAAU,OAAO,SAAS,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI;EACpE,WAAW,IAAI,OAAO;EACtB,OAAO;CACT;CACA,OAAO;EACL,OAAO;GACL;GACA,WAAW,MAAM,WAAW,WAAW,IAAI,IAAI,MAAM,MAAM,WAAW;GACtE,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;GACzD;EACF;EACA;CACF;AACF;AAEA,SAAS,kBACP,UACA,gBACA,YAIA;CACA,MAAM,QAAQ,eAAe,SAAS,KAAK;CAI3C,MAAM,QAAQ,SAAS,SAAS;CAChC,OAAO;EACL,SAAS;GACP;GACA,SAAS,SAAS,WAAW;GAC7B;GACA;EACF;EACA,MACE,SAAS,YAAY,KAAA,IACjB;GAAE,MAAM;GAAY,KAAK,SAAS;EAAQ,IAC1C,MAAM,aAAa,SAAS,CAAC,cAAc,KAAK,IAC9C;GAAE,MAAM;GAAc,KAAK;EAAK,IAChC;GACE,MAAM;GACN,KAAK,aAAa,MAAM,cAAc,MAAM,kBAAkB,KAAK;EACrE;CACV;AACF;AAEA,SAAS,eAAe,OAAsD;CAC5E,MAAM,eAAe,WAAW,OAAO,aAAa;CACpD,MAAM,mBAAmB,WAAW,OAAO,iBAAiB;CAC5D,MAAM,WAAW,iBAAiB,KAAA,KAAa,qBAAqB,KAAA;CACpE,OAAO;EACL,cAAc,gBAAgB;EAC9B,kBAAkB,oBAAoB;EACtC,cAAc,gBAAgB,MAAM,oBAAoB;EACxD;CACF;AACF;AAEA,SAAS,iBAAiB,OAAe,YAAqC;CAC5E,OAAO;EACL,OAAO;GAAE,cAAc;GAAG,kBAAkB;GAAG,aAAa;GAAG,UAAU;EAAM;EAC/E,SAAS;EACT;EACA;CACF;AACF;AAEA,SAAS,WAAW,OAAoC;CACtD,OAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS,IAAI,QAAQ,KAAA;AAC1F;;;AAIA,SAAgB,iBAAiB,MAAyC;CACxE,OAAO,KAAK,KAAK,MAAM,KAAK,EAAE,IAAI,IAAI,EAAE,aAAa,CAAC,CAAC,KAAK,IAAI;AAClE;;AAGA,SAAgB,iBAAiB,MAAyC;CAExE,OAAO,6DADQ,KAAK,KAAK,MAAM,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,KAAK,GACqB,EAAE;AAC7E;;;;;;;;;;;;;;;;;;;ACtGA,eAAsB,aACpB,MAC0B;CAC1B,OAAO,yBAAyB,MAAM,OAAO,iBAAiB;EAC5D,KAAK,IAAI,OAAO,GAAG,OAAO,aAAa,UAAU,QAAQ;GACvD,MAAM,aAAa,UAAU,IAAI;GACjC,IAAI,OAAO,aAAa,WAAW,GAAG,MAAM,aAAa,WAAW,IAAI;EAC1E;CACF,CAAC;AACH;;;;;;;;ACsDA,SAAS,6BAA6B,QAAkD;CACtF,IAAI,OAAO,WAAW,GAAG,OAAO;CAChC,MAAM,OAAO,OAAO,QAAQ,MAAM,CAAC,EAAE,MAAM;CAC3C,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,OAAO,KAAK,QAAQ,KAAK,MAAM,MAAM,EAAE,WAAW,CAAC,IAAI,KAAK;AAC9D;;;;;;AAeA,SAAgB,qBAAqB,OAKnC;CACA,MAAM,gBAA0B,CAAC;CACjC,IAAI,CAAC,MAAM,aAAa,QAAQ,cAAc,KAAK,MAAM,aAAa,SAAS;CAE/E,MAAM,WAAW,MAAM,cAAc,6BAA6B,MAAM,WAAW,IAAI,KAAA;CACvF,IAAI,OAAO,aAAa,UAAU,cAAc,KAAK,QAAQ;CAC7D,MAAM,cAAc,MAAM,iBACtB,6BAA6B,MAAM,cAAc,IACjD,KAAA;CACJ,IAAI,OAAO,gBAAgB,UAAU,cAAc,KAAK,WAAW;CAEnE,OAAO;EACL,WACE,cAAc,WAAW,IACrB,IACA,cAAc,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,cAAc;EAC/D,eAAe,YAAY;EAC3B,kBAAkB,eAAe;EACjC,iBAAiB,cAAc,WAAW;CAC5C;AACF;AAMA,eAAsB,mBACpB,MACmC;CACnC,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,qBAAqB,CAAC,MAAM,CAAC;CACnE,MAAM,eAAe,IAAI,IAAI,KAAK,OAAO,wBAAwB,CAAC,UAAU,CAAC;CAC7E,MAAM,UAAmC,KAAK,WAAW;CACzD,UAAU,KAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,SAAS,MAAM,eAAoC;EACvD,MAAM,CACJ;GAAE,MAAM;GAAW,QAAQ,KAAK;EAAS,GACzC;GAAE,MAAM;GAAW,QAAQ,KAAK,SAAS,KAAK,OAAO;IAAE,IAAI,EAAE;IAAI,OAAO;GAAE,EAAE;EAAE,CAChF;EACA,MAAM,KAAK,QAAQ;EACnB,gBAAgB,KAAK,kBAAkB;EACvC,aAAa,KAAK;EAClB,gBAAgB,KAAK;EACrB,MAAM,QAAQ,MAAM;GAClB,MAAM,gBAAgB,KAAK,IAAI;GAC/B,MAAM,UAAU,KAAK,KAAK,SAAS;GACnC,MAAM,UAAU,KAAK,KAAK,SAAS;GACnC,MAAM,YAAY,OAAO,KAAK,KAAK,SAAS,MAAM,SAAS;GAC3D,MAAM,YAAY,OAAO,KAAK,KAAK,SAAS,MAAM,SAAS;GAK3D,MAAM,MAAM,MAAM,QAAQ;IACxB;IACA;IACA,OAAO,KAAK;IACZ,OAAO,KAAK;IACZ,eAAe,KAAK;IACpB,iBAAiB,KAAK;IACtB,UAAU,KAAK;IACf,mBAAmB,KAAK;IACxB,YAAY,KAAK;IACjB,aAAa,KAAK;IAClB,sBAAsB,KAAK;IAC3B,gBAAgB,KAAK;IACrB,uBAAuB,KAAK;IAC5B,iBAAiB,KAAK;IACtB,gBAAgB,KAAK;IACrB,iBAAiB,KAAK;IACtB,eAAe,KAAK;GACtB,CAAC;GAID,MAAM,cAAc,iBAAiB,GAAG;GAGxC,MAAM,mBAAmB,KAAK,gBAAgB,SAAS;GACvD,IAAI,eAAe;GACnB,IAAI,oBAAoB;GAIxB,IAAI,QAA4C;GAChD,IAAI;IACF,0BAA0B,GAAG;IAE7B,MAAM,gBAAgB,IAAI,UAAU,QAAQ,MAAM,UAAU,IAAI,EAAE,IAAI,CAAC;IACvE,MAAM,mBAAmB,IAAI,UAAU,QAAQ,MAAM,aAAa,IAAI,EAAE,IAAI,CAAC;IAE7E,QAAQ;IACR,MAAM,CAAC,iBAAiB,gBAAgB,qBAAqB,MAAM,QAAQ,IAAI;KAC7E,SAAS,mBAAmB,KAAK,OAAO,cAAc,KAAK,cAAc,GAAG;MAC1E,YAAY,IAAI;MAChB;KACF,CAAC;KACD,KAAK,OAAO,aACR,QAAQ,IACN,cAAc,KAAK,aACjB,SAAS,mBAAmB,KAAK,OAAO,YAAa,KAAK,cAAc,GAAG;MACzE;MACA;KACF,CAAC,CAAC,CAAC,MAAM,YAAY;MACnB,OAAO;OACL,GAAG,OAAO;OACV,MAAM,SAAS;OACf,MAAM,SAAS;MACjB;MACA,MAAM,OAAO;KACf,EAAE,CACJ,CACF,IACA,QAAQ,QAAQ,CAAC,CAAuB;KAC5C,KAAK,OAAO,iBACR,QAAQ,IACN,iBAAiB,KAAK,aACpB,SAAS,mBAAmB,KAAK,OAAO,gBAAiB,KAAK,cAAc,GAAG;MAC7E;MACA;KACF,CAAC,CAAC,CAAC,MAAM,YAAY;MACnB,OAAO;OACL,GAAG,OAAO;OACV,MAAM,SAAS;OACf,MAAM,SAAS;MACjB;MACA,MAAM,OAAO;KACf,EAAE,CACJ,CACF,IACA,QAAQ,QAAQ,CAAC,CAAuB;IAC9C,CAAC;IACD,MAAM,YAAY;KAAC;KAAiB,GAAG;KAAgB,GAAG;IAAiB;IAC3E,eAAe,UAAU,QAAQ,KAAK,QAAQ,OAAO,IAAI,KAAK,OAAO,IAAI,CAAC;IAC1E,oBAAoB,UAAU,OAAO,QAAQ,IAAI,KAAK,SAAS,YAAY;IAC3E,QAAQ;IAER,MAAM,eAAe,gBAAgB;IACrC,MAAM,cAAc,eAAe,KAAK,QAAQ,IAAI,KAAK;IACzD,MAAM,iBAAiB,kBAAkB,KAAK,QAAQ,IAAI,KAAK;IAE/D,MAAM,EAAE,WAAW,eAAe,kBAAkB,oBAClD,qBAAqB;KACnB;KACA,aAAa,KAAK,OAAO,aAAa,cAAc,KAAA;KACpD,gBAAgB,KAAK,OAAO,iBAAiB,iBAAiB,KAAA;IAChE,CAAC;IAEH,MAAM,YAAgC;KAAE;KAAW;IAAa;IAChE,IAAI,KAAK,OAAO,YACd,UAAU,aAAa;KAAE,aAAa;KAAa,WAAW;IAAc;IAC9E,IAAI,KAAK,OAAO,gBACd,UAAU,iBAAiB;KAAE,aAAa;KAAgB,WAAW;IAAiB;IAExF,MAAM,UAAU,KAAK,KAAK,QAAQ,WAAW,WAAW,OAAO,KAAK,KAAK;IACzE,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;IACtC,cAAc,KAAK,SAAS,iBAAiB,GAAG,KAAK,UAAU,IAAI,YAAY,MAAM,CAAC,CAAC;IACvF,cAAc,KAAK,SAAS,gBAAgB,GAAG,KAAK,UAAU,IAAI,WAAW,MAAM,CAAC,CAAC;IACrF,cAAc,KAAK,SAAS,aAAa,GAAG,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;IAE9E,MAAM,QAAQ,CAAC,SAAS,aAAa,UAAU,QAAQ,CAAC,GAAG;IAC3D,IAAI,KAAK,OAAO,YAAY,MAAM,KAAK,QAAQ,cAAc,QAAQ,CAAC,GAAG;IACzE,IAAI,KAAK,OAAO,gBAAgB,MAAM,KAAK,WAAW,iBAAiB,QAAQ,CAAC,GAAG;IACnF,IAAI,iBAAiB,MAAM,KAAK,mBAAmB;IACnD,IAAI,CAAC,mBAAmB,MAAM,KAAK,uBAAuB;IAE1D,OAAO;KACL,QAAQ;MACN,OAAO,IAAI,WAAW;MACtB,WAAW,IAAI;MACf,eAAe,IAAI,UAAU;KAC/B;KACA,SAAS;MAAE,OAAO,aAAa;MAAG,OAAO;MAAW,OAAO,MAAM,KAAK,GAAG;KAAE;KAC3E,SAAS,IAAI,UAAU;KAMvB,gBACE,qBAAqB,mBACjB;MAAE,MAAM;MAAa,KAAK,IAAI,UAAU;KAAa,IACrD;MAAE,MAAM;MAAc,KAAK;KAAK;KACtC,YAAY,IAAI;IAClB;GACF,SAAS,KAAK;IAIZ,IAAI,gBAAgB,KAAA,GAAW,MAAM;IACrC,MAAM,cAAc,KAAK;KACvB,SAAS,cAAc;KACvB,YAAY,KAAK,IAAI,IAAI;KAKzB,MACE,qBAAqB,UAAU,cAAe,UAAU,aAAa,qBACjE,cACA;IACR,CAAC;GACH;EACF;CACF,CAAC;CAGD,MAAM,UAAU;EACd,OAAO,OAAO,QAAQ;EACtB,UAAU,OAAO,QAAQ;EACzB,WAAW,OAAO,QAAQ;EAC1B,cAAc,OAAO,QAAQ;EAC7B,qBAAqB,OAAO,QAAQ;EACpC,mBAAmB,OAAO,QAAQ;EAClC,YAAY,OAAO,QAAQ;EAC3B,cAAc,OAAO,QAAQ;EAC7B,cAAc,OAAO,QAAQ;EAC7B,WAAW,OAAO,OAAO;EACzB,WAAW,OAAO,OAAO;CAC3B;CACA,cAAc,KAAK,KAAK,QAAQ,cAAc,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;CAIjF,MAAM,aAAa,OAAO,QAAQ;CAClC,MAAM,YAAY,aAAa,IAAI,oBAAoB;CAEvD,MAAM,KAAe;EACnB;EACA;EACA,cAAc,OAAO,QAAQ,WAAW,qBAAqB,OAAO,QAAQ,kBAAkB,IAAA,CAAK,QAAQ,CAAC,EAAE,gBAAgB,OAAO,QAAQ,iBAAiB,QAAQ,CAAC,EAAE,OAAO,UAAU,OAAO,OAAO,QAAQ,aAAa,QAAQ,CAAC,EAAE,oBAAoB,OAAO,QAAQ,aAAa,IAAA,CAAM,QAAQ,CAAC,EAAE;EACzS;EACA,GAAI,aAAa,IACb,CACE,KAAK,WAAW,MAAM,OAAO,QAAQ,aAAa,mGAClD,EACF,IACA,CAAC;EACL;EACA;EACA;EACA;EACA,GAAG,OAAO,QAAQ,OAAO,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,KAC5C,CAAC,IAAI,OACJ,KAAK,GAAG,MAAM,EAAE,WAAW,IAAA,CAAK,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,QAAQ,CAAC,EAAE,GAC5G;EACA;EACA;EACA;EACA;EACA;EACA,GAAG,OAAO,QAAQ,OAAO,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,KAC5C,CAAC,IAAI,OACJ,KAAK,GAAG,MAAM,EAAE,WAAW,IAAA,CAAK,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,QAAQ,CAAC,EAAE,GAC5G;EACA;CACF;CACA,cAAc,KAAK,KAAK,QAAQ,YAAY,GAAG,GAAG,KAAK,IAAI,CAAC;CAE5D,OAAO,EAAE,OAAO;AAClB;;;;;AAMA,SAAS,iBACP,KACoB;CACpB,MAAM,QAAQ,KAAK;CACnB,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ,KAAA;AACrF;AAEA,SAAS,mBACP,OACA,WAC8B;CAC9B,IAAI,cAAc,KAAA,KAAa,MAAM,cAAc,KAAA,GAAW,OAAO;CACrE,OAAO;EAAE,GAAG;EAAO;CAAU;AAC/B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/multishot/cost.ts","../../src/multishot/default-tools.ts","../../src/multishot/shape-defaults.ts","../../src/multishot/conversation.ts","../../src/multishot/judges.ts","../../src/multishot/multishot.ts","../../src/multishot/matrix.ts"],"sourcesContent":["// Per-model cost estimator for multishot legs whose transport reported token\n// usage but no billed amount.\n\n/**\n * Rough per-model cost estimate from token counts. Underestimates Anthropic,\n * overestimates open-weight models — accurate enough for a cost ceiling, and\n * never presented as a billed amount: a leg metered from this table is\n * recorded with `estimated` provenance.\n */\nexport function estimateMultishotCost(\n model: string,\n usage?: { prompt_tokens?: number; completion_tokens?: number },\n): number {\n if (!usage) return 0\n const inputTok = usage.prompt_tokens ?? 0\n const outputTok = usage.completion_tokens ?? 0\n let inPer1k = 0.003\n let outPer1k = 0.015\n if (model.includes('gpt-4o-mini')) {\n inPer1k = 0.00015\n outPer1k = 0.0006\n } else if (model.includes('gpt-5.4') || model.includes('claude-sonnet')) {\n inPer1k = 0.003\n outPer1k = 0.015\n } else if (model.includes('kimi') || model.includes('glm') || model.includes('deepseek')) {\n inPer1k = 0.0005\n outPer1k = 0.002\n }\n return (inputTok * inPer1k + outputTok * outPer1k) / 1000\n}\n","// Default delegate_research + delegate_code tools and their inline executors.\n//\n// Consumers can override either by passing their own tools + executors to\n// runMultishot. The defaults are sufficient for most domains — point the\n// researcher system prompt at your domain's citation style and the coder\n// at your preferred language.\n\nimport { estimateMultishotCost } from './cost'\nimport type { MultishotToolDefinition, MultishotToolExecutor } from './types'\n\nconst DEFAULT_RESEARCHER_MODEL = 'openai/gpt-4o-mini'\nexport const DEFAULT_CODER_MODEL = 'openai/gpt-4o-mini'\n\nexport interface DefaultResearcherConfig {\n /** Replace the system prompt to bias the researcher toward a domain's\n * citation style. Defaults to a generic \"cite sources by name\" prompt. */\n systemPrompt?: string\n model?: string\n}\n\nexport interface DefaultCoderConfig {\n /** Replace the system prompt to bias the coder toward a language /\n * framework / artifact style. */\n systemPrompt?: string\n model?: string\n}\n\nconst GENERIC_RESEARCHER_SYSTEM =\n 'You are a research specialist. Return a markdown brief with 3-5 findings. Each finding cites a specific source by name. Add a confidence level (high/medium/low) per finding. No fluff, no preamble.'\n\nconst GENERIC_CODER_SYSTEM =\n 'You are an expert engineer. Output ONE fenced code block containing the complete solution. Inline-comment non-obvious decisions. No explanation outside the block.'\n\nconst DEFAULT_DELEGATE_RESEARCH_TOOL: MultishotToolDefinition = {\n type: 'function',\n function: {\n name: 'delegate_research',\n description:\n 'Research a topic deeply via specialist. Returns evidence-bearing items with citations. Use for audience research, competitive intel, regulatory landscape, market data, citation-grounded analysis.',\n parameters: {\n type: 'object',\n properties: {\n question: { type: 'string', description: 'Specific question to research' },\n scope: {\n type: 'string',\n description: 'Optional scope: time window, geography, jurisdiction, segment',\n },\n },\n required: ['question'],\n },\n },\n}\n\nconst DEFAULT_DELEGATE_CODE_TOOL: MultishotToolDefinition = {\n type: 'function',\n function: {\n name: 'delegate_code',\n description:\n 'Generate a runnable script, template, pipeline, or tool via specialist. Returns complete working code or structured markdown. Use for content pipelines, calc snippets, dashboards, compliance checklists, deadline trackers.',\n parameters: {\n type: 'object',\n properties: {\n goal: { type: 'string', description: 'What the code must accomplish' },\n language: {\n type: 'string',\n description: 'Optional language preference (default: TypeScript)',\n },\n },\n required: ['goal'],\n },\n },\n}\n\nfunction createResearchExecutor(config: DefaultResearcherConfig = {}): MultishotToolExecutor {\n const systemPrompt = config.systemPrompt ?? GENERIC_RESEARCHER_SYSTEM\n const model = config.model ?? DEFAULT_RESEARCHER_MODEL\n return async (args, ctx) => {\n const question = String(args.question ?? '')\n const scope = args.scope ? String(args.scope) : undefined\n const { message, usage, costUsd } = await ctx.transport({\n model,\n temperature: 0.3,\n maxTokens: 1800,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: `Research: ${question}${scope ? `\\nScope: ${scope}` : ''}` },\n ],\n signal: ctx.signal,\n })\n return {\n content: message.content ?? '',\n costUsd: costUsd ?? estimateMultishotCost(model, usage),\n }\n }\n}\n\nfunction createCodeExecutor(config: DefaultCoderConfig = {}): MultishotToolExecutor {\n const systemPrompt = config.systemPrompt ?? GENERIC_CODER_SYSTEM\n const model = config.model ?? DEFAULT_CODER_MODEL\n return async (args, ctx) => {\n const goal = String(args.goal ?? '')\n const language = args.language ? String(args.language) : 'TypeScript'\n const { message, usage, costUsd } = await ctx.transport({\n model,\n temperature: 0.2,\n maxTokens: 2000,\n messages: [\n { role: 'system', content: `${systemPrompt}\\n\\nLanguage: ${language}` },\n { role: 'user', content: `Produce: ${goal}` },\n ],\n signal: ctx.signal,\n })\n return {\n content: message.content ?? '',\n costUsd: costUsd ?? estimateMultishotCost(model, usage),\n }\n }\n}\n\nexport interface DefaultToolsConfig {\n research?: DefaultResearcherConfig\n code?: DefaultCoderConfig\n /** When true (default), each tool result is recorded as a typed artifact:\n * research → type='research', code → type='code'. */\n recordArtifacts?: boolean\n}\n\nexport interface DefaultToolsBundle {\n tools: MultishotToolDefinition[]\n executors: Record<string, MultishotToolExecutor>\n artifactTypeFor: (toolName: string) => string | undefined\n}\n\nexport function defaultDelegationTools(config: DefaultToolsConfig = {}): DefaultToolsBundle {\n return {\n tools: [DEFAULT_DELEGATE_RESEARCH_TOOL, DEFAULT_DELEGATE_CODE_TOOL],\n executors: {\n delegate_research: createResearchExecutor(config.research),\n delegate_code: createCodeExecutor(config.code),\n },\n artifactTypeFor: (name) =>\n name === 'delegate_research' ? 'research' : name === 'delegate_code' ? 'code' : undefined,\n }\n}\n","// Profile-derived defaults for MultishotShape — the pure-profile path.\n//\n// `MultishotShape`'s callbacks were REQUIRED beside `profile: AgentProfile`,\n// which mixed the abstractions: the node under test was a profile, but the\n// simulated user's role could only be expressed as code. These defaults make\n// the callbacks optional — a pure-profile call works, and the derived prompts\n// are plain data (a pure function of profile + persona payload), so an\n// optimizer can sweep them (tangle-network/agent-runtime#694).\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { MultishotPersona, MultishotShape } from './types'\n\n/** Persona payload rendered as stable `- key: value` lines. `id` is identity,\n * not voice, and structured values are serialized so nothing is dropped. */\nfunction renderPersonaFacts(persona: MultishotPersona): string {\n const lines: string[] = []\n for (const [key, value] of Object.entries(persona)) {\n if (key === 'id' || value === undefined) continue\n const rendered =\n typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n ? String(value)\n : JSON.stringify(value)\n lines.push(`- ${key}: ${rendered}`)\n }\n return lines.join('\\n')\n}\n\n/** Default opening user message: the persona introduces itself with its whole\n * payload and asks the agent (as described by the profile) to take over. */\nfunction defaultMultishotOpener(profile: AgentProfile, persona: MultishotPersona): string {\n const facts = renderPersonaFacts(persona)\n const agentDescription = profile.description ?? profile.name ?? 'the agent'\n return [\n `Hi — I'm reaching out to ${agentDescription} for help. My situation:`,\n facts.length > 0 ? facts : `- (no details provided beyond id: ${persona.id})`,\n '',\n 'Tell me what you need from me, and get started on my case.',\n ].join('\\n')\n}\n\n/** Default driver system prompt: roleplay the persona from its payload, stay\n * in character, push back on vague answers, and never go silent. */\nfunction defaultMultishotDriverSystemPrompt(\n profile: AgentProfile,\n persona: MultishotPersona,\n): string {\n const facts = renderPersonaFacts(persona)\n const agentDescription = profile.description ?? profile.name ?? 'an AI agent'\n return [\n `You are role-playing a real person (persona \"${persona.id}\") talking to ${agentDescription}.`,\n facts.length > 0 ? `Who you are:\\n${facts}` : '',\n '',\n 'How to behave:',\n '- Stay in character: first person, realistic voice, concrete details from your situation.',\n '- Judge every reply by whether it actually moves YOUR case forward. Push back on vague, hedged, or generic answers and demand specifics.',\n \"- Answer the agent's questions with information consistent with who you are; invent plausible details rather than stalling.\",\n '- Never go silent: always produce a substantive next message.',\n '- Output ONLY your next message to the agent — no meta-commentary, no stage directions.',\n ]\n .filter((block) => block.length > 0)\n .join('\\n')\n}\n\n/** The fully-resolved shape for a profile: caller overrides win, the\n * profile-derived defaults fill the rest. */\nexport function defaultShapeFromProfile<TPersona extends MultishotPersona>(\n profile: AgentProfile,\n shape?: MultishotShape<TPersona>,\n): Required<MultishotShape<TPersona>> {\n return {\n buildOpener: shape?.buildOpener ?? ((persona) => defaultMultishotOpener(profile, persona)),\n buildDriverSystemPrompt:\n shape?.buildDriverSystemPrompt ??\n ((persona) => defaultMultishotDriverSystemPrompt(profile, persona)),\n }\n}\n","// The multishot conversation's two legs, separable from the loop that orders\n// them.\n//\n// `runMultishot` orders the legs as a plain turn loop. A caller that orders\n// them another way — a Runtime flow graph, a scheduler, a replay harness —\n// drives the same legs through `runMultishotConversation`, so the transcript,\n// artifacts, tool-call count, driver point of view and cost accounting stay\n// this package's single implementation.\n//\n// agent-eval owns no model transport: every leg runs on a MultishotTransport\n// the caller supplies, so no provider credential enters this package.\n\nimport { withCellSpend } from '../matrix'\nimport { estimateMultishotCost } from './cost'\nimport { defaultDelegationTools } from './default-tools'\nimport type { RunMultishotOptions } from './multishot'\nimport { defaultShapeFromProfile } from './shape-defaults'\nimport {\n type MultishotArtifact,\n MultishotDriverEmptyError,\n MultishotFatalToolError,\n type MultishotMessage,\n type MultishotPersona,\n type MultishotResult,\n} from './types'\n\n/** Prompt and completion tokens one leg reported. */\nexport interface MultishotLegTokens {\n input: number\n output: number\n}\n\n/** What one leg spent: its tokens and the USD it added to the conversation's\n * cost (provider-reported, else estimated from usage; tool executor spend\n * included). */\nexport interface MultishotLegSpend {\n tokens: MultishotLegTokens\n usd: number\n}\n\n/** One conversation's state and legs. Each leg appends to the shared\n * transcript; the caller decides the order in which legs run. */\nexport interface MultishotConversation {\n /** Agent turns the conversation is configured for (`opts.maxTurns ?? 10`). */\n readonly maxTurns: number\n /** The model the agent leg runs on. */\n readonly agentModel: string\n /** The primary simulated-user model. */\n readonly driverModel: string\n /** The persona's first message, already in the transcript. */\n readonly opener: string\n /** The simulated user's system prompt. */\n readonly driverSystemPrompt: string\n /** One agent turn: inference, inline tool execution and follow-up inference,\n * until the agent answers without tools. Throws on abort, on a fatal tool\n * error and on the per-turn tool dispatch cap. */\n agentTurn(turn: number): Promise<MultishotLegSpend>\n /** The simulated user's reply to the transcript so far, appended for the\n * next agent turn. Retries an empty reply once per model, rotates through\n * the fallback models, then throws `MultishotDriverEmptyError`. */\n driverTurn(turn: number): Promise<MultishotLegSpend & { content: string }>\n}\n\n/** Orders the legs of one conversation. Resolves when the conversation is done. */\nexport type MultishotConversationDriver = (conversation: MultishotConversation) => Promise<void>\n\ninterface ConversationMeter {\n costUsd: number\n startedAt: number\n /** True once a call contributed a fabricated `0` — no provider cost and no\n * usage to price. `costUsd` is a subtotal from that point on. */\n uncaptured: boolean\n}\n\n/**\n * Run one multishot conversation whose leg order `drive` decides.\n *\n * Returns the conversation's `MultishotResult`. When any leg or `drive` throws,\n * the error is rethrown carrying the spend so far (`withCellSpend`), so a\n * matrix bills the failed cell for the turns it already paid for.\n */\nexport async function runMultishotConversation<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n drive: MultishotConversationDriver,\n): Promise<MultishotResult> {\n const meter: ConversationMeter = { costUsd: 0, startedAt: Date.now(), uncaptured: false }\n try {\n const state = openConversation(opts, meter)\n await drive(state.conversation)\n return {\n transcript: state.transcript,\n artifacts: state.artifacts,\n toolCalls: state.toolCalls(),\n durationMs: Date.now() - meter.startedAt,\n costUsd: meter.costUsd,\n // A shot that priced every call reports a complete estimate. One that had\n // a call the router priced at nothing reports a subtotal, so the cell is\n // recorded as under-counted rather than as a complete estimate.\n costProvenance: meter.uncaptured\n ? { kind: 'uncaptured', usd: null }\n : { kind: 'estimated', usd: meter.costUsd },\n }\n } catch (err) {\n throw withCellSpend(err, {\n costUsd: meter.costUsd,\n durationMs: Date.now() - meter.startedAt,\n kind: meter.uncaptured ? 'uncaptured' : 'estimated',\n })\n }\n}\n\nfunction openConversation<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n meter: ConversationMeter,\n): {\n conversation: MultishotConversation\n transcript: MultishotMessage[]\n artifacts: MultishotArtifact[]\n toolCalls: () => number\n} {\n const maxTurns = opts.maxTurns ?? 10\n const maxToolDispatches = opts.maxToolDispatches ?? 4\n const agentModel = opts.agentModel ?? 'openai/gpt-5.4'\n const driverModel = opts.driverModel ?? 'openai/gpt-4o-mini'\n const driverModels = [driverModel, ...(opts.driverFallbackModels ?? [])]\n const agentMaxTokens = opts.agentMaxTokens ?? 2500\n const toolFollowupMaxTokens = opts.toolFollowupMaxTokens ?? 2000\n const driverMaxTokens = opts.driverMaxTokens ?? 600\n\n const bundle =\n opts.tools && opts.toolExecutors\n ? {\n tools: opts.tools,\n executors: opts.toolExecutors,\n artifactTypeFor: opts.artifactTypeFor ?? (() => undefined),\n }\n : defaultDelegationTools()\n const tools = opts.tools ?? bundle.tools\n const executors = opts.toolExecutors ?? bundle.executors\n const artifactTypeFor = opts.artifactTypeFor ?? bundle.artifactTypeFor\n\n const agentTransport = opts.agentTransport\n const driverTransport = opts.driverTransport\n const toolTransport = opts.toolTransport ?? agentTransport\n\n const shape = defaultShapeFromProfile(opts.profile, opts.shape)\n\n const transcript: MultishotMessage[] = []\n const artifacts: MultishotArtifact[] = []\n let toolCalls = 0\n\n const opener = shape.buildOpener(opts.persona)\n transcript.push({ role: 'user', content: opener })\n\n const systemPrompt = [opts.profile.prompt?.systemPrompt, opts.profile.prompt?.appendSystemPrompt]\n .filter((value): value is string => Boolean(value))\n .join('\\n\\n')\n const agentMessages: Array<Record<string, unknown>> = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: opener },\n ]\n const driverSystemPrompt = shape.buildDriverSystemPrompt(opts.persona)\n\n async function agentTurn(turn: number): Promise<MultishotLegSpend> {\n if (opts.signal?.aborted) throw new Error('multishot aborted')\n const usdBefore = meter.costUsd\n const tokens = { input: 0, output: 0 }\n let dispatchesThisTurn = 0\n while (true) {\n const {\n message: agentMsg,\n usage: agentUsage,\n costUsd: agentCostUsd,\n } = await agentTransport({\n model: agentModel,\n messages: agentMessages,\n tools,\n temperature: 0.7,\n maxTokens: dispatchesThisTurn === 0 ? agentMaxTokens : toolFollowupMaxTokens,\n signal: opts.signal,\n })\n meter.costUsd += agentCostUsd ?? estimateMultishotCost(agentModel, agentUsage)\n if (agentCostUsd === undefined && agentUsage === undefined) meter.uncaptured = true\n tokens.input += agentUsage?.prompt_tokens ?? 0\n tokens.output += agentUsage?.completion_tokens ?? 0\n\n const agentText = (agentMsg.content ?? '').trim()\n const agentToolCalls = (agentMsg.tool_calls ?? []).map((tc) => ({\n id: tc.id,\n name: tc.function.name,\n args: (() => {\n try {\n return JSON.parse(tc.function.arguments) as Record<string, unknown>\n } catch {\n return {} as Record<string, unknown>\n }\n })(),\n }))\n\n agentMessages.push({\n role: 'assistant',\n content: agentText || null,\n ...(agentMsg.tool_calls?.length ? { tool_calls: agentMsg.tool_calls } : {}),\n })\n transcript.push({\n role: 'assistant',\n content: agentText,\n toolCalls: agentToolCalls.length > 0 ? agentToolCalls : undefined,\n })\n\n if (agentToolCalls.length === 0) break\n dispatchesThisTurn += agentToolCalls.length\n if (dispatchesThisTurn > maxToolDispatches) {\n throw new Error(\n `multishot: tool dispatch cap exceeded (${dispatchesThisTurn}/${maxToolDispatches}) on turn ${turn}`,\n )\n }\n\n for (const tc of agentToolCalls) {\n toolCalls++\n let toolResult = ''\n try {\n const executor = executors[tc.name]\n if (!executor) {\n toolResult = JSON.stringify({ error: `unknown tool ${tc.name}` })\n } else {\n const r = await executor(tc.args, { transport: toolTransport, signal: opts.signal })\n toolResult = r.content\n meter.costUsd += r.costUsd\n const artifactType = artifactTypeFor(tc.name)\n if (artifactType) {\n artifacts.push({\n type: artifactType,\n turn,\n invocation: { name: tc.name, args: tc.args },\n content: toolResult,\n })\n }\n }\n } catch (err) {\n if (err instanceof MultishotFatalToolError) throw err\n toolResult = JSON.stringify({ error: err instanceof Error ? err.message : String(err) })\n }\n agentMessages.push({ role: 'tool', tool_call_id: tc.id, content: toolResult || 'done' })\n transcript.push({ role: 'tool', content: toolResult || 'done', toolCallId: tc.id })\n }\n }\n return { tokens, usd: meter.costUsd - usdBefore }\n }\n\n // Every driver attempt is charged, including the empty ones that force a\n // retry and the ones that precede `MultishotDriverEmptyError`: those calls\n // billed the provider whether or not their content was usable.\n async function driverTurn(turn: number): Promise<MultishotLegSpend & { content: string }> {\n const usdBefore = meter.costUsd\n // Driver point of view: the agent's `assistant` messages become `user`\n // (the agent talking TO the driver); the driver's prior `user` messages\n // become `assistant` (the driver's prior responses).\n const driverMessages: Array<Record<string, unknown>> = [\n { role: 'system', content: driverSystemPrompt },\n ]\n for (const msg of transcript) {\n if (msg.role === 'tool') continue\n const content = driverVisibleContent(msg)\n if (!content) continue\n if (msg.role === 'assistant') driverMessages.push({ role: 'user', content })\n else if (msg.role === 'user') driverMessages.push({ role: 'assistant', content })\n }\n\n // The driver must never go silent. Retry once on empty content; then fail loud.\n const tokens = { input: 0, output: 0 }\n for (const model of driverModels) {\n for (let attempt = 0; attempt < 2; attempt++) {\n const { message, usage, costUsd } = await driverTransport({\n model,\n messages: driverMessages,\n temperature: 0.9,\n maxTokens: driverMaxTokens,\n signal: opts.signal,\n })\n meter.costUsd += costUsd ?? estimateMultishotCost(model, usage)\n if (costUsd === undefined && usage === undefined) meter.uncaptured = true\n tokens.input += usage?.prompt_tokens ?? 0\n tokens.output += usage?.completion_tokens ?? 0\n const content = (message.content ?? '').trim()\n if (content.length > 0) {\n agentMessages.push({ role: 'user', content })\n transcript.push({ role: 'user', content })\n return { content, tokens, usd: meter.costUsd - usdBefore }\n }\n }\n }\n throw new MultishotDriverEmptyError(turn)\n }\n\n return {\n conversation: {\n maxTurns,\n agentModel,\n driverModel,\n opener,\n driverSystemPrompt,\n agentTurn,\n driverTurn,\n },\n transcript,\n artifacts,\n toolCalls: () => toolCalls,\n }\n}\n\n/** Silent tool-calling agent turns surface to the driver as\n * \"Agent called tools: …\" so the simulated user can react to them. */\nfunction driverVisibleContent(msg: MultishotMessage): string | null {\n const text = msg.content.trim()\n if (text.length > 0) return text\n if (msg.role !== 'assistant' || !msg.toolCalls?.length) return null\n\n const toolNames = msg.toolCalls.map((call) => call.name.trim()).filter(Boolean)\n if (toolNames.length === 0) return 'Agent called tools.'\n return `Agent called ${toolNames.length === 1 ? 'tool' : 'tools'}: ${toolNames.join(', ')}.`\n}\n","// Generic judge runner — domain consumers configure dimensions + prompts.\n//\n// Three judge slots are conventional for multishot eval:\n// - conversation (scores the full transcript)\n// - codeReview (scores each code artifact)\n// - contentQuality (scores each non-code artifact)\n//\n// But the runJudge primitive is fully generic: any input maps to a score plus\n// explicit observed, estimated, or uncaptured cost.\n\nimport type { JudgeDimension, JudgeScore } from '../campaign/types'\nimport type { CostProvenance } from '../cost-ledger'\nimport type { LlmCallMetadata, LlmUsage } from '../llm-client'\nimport { estimateCost, isModelPriced } from '../metrics'\nimport type { MultishotTransport, MultishotTransportResponse } from './types'\n\n// Canonical declaration lives in campaign/types.ts. Multishot emits the same\n// shape on its producer-defined 0-10 scale.\nexport type { JudgeDimension, JudgeScore } from '../campaign/types'\n\nexport const DEFAULT_JUDGE_MODEL = 'openai/gpt-4o-mini'\n\nexport interface MultishotJudgeConfig<TInput> {\n /** Display name (for trace + log). */\n name: string\n /** Caller-owned execution for this judge's call. agent-eval issues no\n * provider request and holds no credential. */\n transport: MultishotTransport\n /** Model used for this judge. */\n model?: string\n /** 0-10 scored dimensions. */\n dimensions: JudgeDimension[]\n /** Judge system prompt — sets persona + JSON-only constraint. */\n systemPrompt: string\n /** Build the user prompt from the typed input. Must include \"Respond with\n * ONLY this JSON: { ... }\" listing each dimension key. */\n buildPrompt: (input: TInput) => string\n /** Maximum output tokens for the judge response. Defaults to 1500. */\n maxTokens?: number\n}\n\nexport interface JudgeRunResult {\n /** Semantic result; failed scores remain non-throwing so matrix aggregation can exclude them. */\n score: JudgeScore\n /** Cost of the completed call, separate from diagnostic provider metadata. */\n cost: CostProvenance\n}\n\nexport async function runJudge<TInput>(\n judge: MultishotJudgeConfig<TInput>,\n input: TInput,\n): Promise<JudgeRunResult> {\n const model = judge.model ?? DEFAULT_JUDGE_MODEL\n const prompt = judge.buildPrompt(input)\n let raw = ''\n let llmCall: LlmCallMetadata\n let cost: CostProvenance\n const startedAt = Date.now()\n try {\n const response = await judge.transport({\n model,\n temperature: 0,\n maxTokens: judge.maxTokens ?? 1500,\n messages: [\n { role: 'system', content: judge.systemPrompt },\n { role: 'user', content: prompt },\n ],\n })\n const call = judgeCallMetadata(response, model, Date.now() - startedAt)\n llmCall = call.llmCall\n cost = call.cost\n raw = (response.message.content ?? '').trim()\n } catch (err) {\n // failed:true lets consumers reading `.composite` keep working while\n // aggregators exclude this score from means instead of averaging a zero.\n return {\n score: {\n dimensions: {},\n composite: 0,\n failed: true,\n notes: `judge ${judge.name} call failed: ${err instanceof Error ? err.message : String(err)}`,\n llmCall: unknownJudgeCall(model, Date.now() - startedAt),\n },\n cost: { kind: 'uncaptured', usd: null },\n }\n }\n\n let parsed: Record<string, unknown> | null = null\n try {\n const cleaned = raw\n .replace(/^```json\\s*/i, '')\n .replace(/```\\s*$/, '')\n .trim()\n parsed = JSON.parse(cleaned) as Record<string, unknown>\n } catch {\n return {\n score: {\n dimensions: {},\n composite: 0,\n failed: true,\n notes: `judge ${judge.name} returned non-JSON: ${raw.slice(0, 200)}`,\n llmCall,\n },\n cost,\n }\n }\n\n const dimensions: Record<string, number> = {}\n let sum = 0\n for (const dim of judge.dimensions) {\n const v = Number(parsed[dim.key] ?? 0)\n const clamped = Number.isFinite(v) ? Math.max(0, Math.min(10, v)) : 0\n dimensions[dim.key] = clamped\n sum += clamped\n }\n return {\n score: {\n dimensions,\n composite: judge.dimensions.length === 0 ? 0 : sum / judge.dimensions.length,\n notes: typeof parsed.notes === 'string' ? parsed.notes : '',\n llmCall,\n },\n cost,\n }\n}\n\nfunction judgeCallMetadata(\n response: MultishotTransportResponse,\n requestedModel: string,\n durationMs: number,\n): {\n llmCall: LlmCallMetadata\n cost: CostProvenance\n} {\n const usage = canonicalUsage(response.usage)\n // The transport reports the served identity when it observed one. Falling\n // back to the requested id keeps attribution honest for a transport that\n // reported none; it is not proof that model answered.\n const model = response.model ?? requestedModel\n return {\n llmCall: {\n usage,\n costUsd: response.costUsd ?? null,\n model,\n durationMs,\n },\n cost:\n response.costUsd !== undefined\n ? { kind: 'observed', usd: response.costUsd }\n : usage.captured === false || !isModelPriced(model)\n ? { kind: 'uncaptured', usd: null }\n : {\n kind: 'estimated',\n usd: estimateCost(usage.promptTokens, usage.completionTokens, model),\n },\n }\n}\n\nfunction canonicalUsage(usage: MultishotTransportResponse['usage']): LlmUsage {\n const promptTokens = tokenCount(usage?.prompt_tokens)\n const completionTokens = tokenCount(usage?.completion_tokens)\n const captured = promptTokens !== undefined && completionTokens !== undefined\n return {\n promptTokens: promptTokens ?? 0,\n completionTokens: completionTokens ?? 0,\n totalTokens: (promptTokens ?? 0) + (completionTokens ?? 0),\n captured,\n }\n}\n\nfunction unknownJudgeCall(model: string, durationMs: number): LlmCallMetadata {\n return {\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0, captured: false },\n costUsd: null,\n model,\n durationMs,\n }\n}\n\nfunction tokenCount(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined\n}\n\n/** Convenience: stringified dimension list for inclusion in a judge prompt.\n * Returns lines like `- audience_fit: Does this match what the audience cares about? (0-10)`. */\nexport function renderDimensions(dims: readonly JudgeDimension[]): string {\n return dims.map((d) => `- ${d.key}: ${d.description}`).join('\\n')\n}\n\n/** Convenience: build the \"Respond with ONLY this JSON\" footer for a judge prompt. */\nexport function renderJsonFooter(dims: readonly JudgeDimension[]): string {\n const fields = dims.map((d) => `\"${d.key}\":N`).join(',')\n return `Respond with ONLY this JSON (no markdown, no preamble):\\n{${fields},\"notes\":\"1-2 sentence critique\"}`\n}\n","// Multi-turn driver-agent simulation with inline tool execution.\n//\n// The driver = LLM acting as the persona (reactive, non-deterministic).\n// The agent = the product agent under test, executed by the caller-supplied\n// transport with the profile's systemPrompt + the configured tools.\n// Tool calls execute inline via the configured executors and feed back\n// into the agent's message log so the agent integrates the result.\n//\n// agent-eval owns no model transport: every leg runs on a MultishotTransport\n// the caller supplies, so no provider credential enters this package.\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport { runMultishotConversation } from './conversation'\nimport type {\n MultishotPersona,\n MultishotResult,\n MultishotShape,\n MultishotToolDefinition,\n MultishotToolExecutor,\n MultishotTransport,\n} from './types'\n\nexport interface RunMultishotOptions<TPersona extends MultishotPersona> {\n profile: AgentProfile\n persona: TPersona\n /** Persona-shaping callbacks. Optional — omitted callbacks are derived from\n * the profile + persona payload, so a pure-profile call works. */\n shape?: MultishotShape<TPersona>\n /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */\n tools?: MultishotToolDefinition[]\n /** Map from tool name → executor invoked inline when the agent emits a tool_call. */\n toolExecutors?: Record<string, MultishotToolExecutor>\n /** Map from tool name → artifact type label written into MultishotArtifact.type.\n * Tools without a mapping still execute, but their results aren't surfaced as\n * typed artifacts (only as tool messages in the transcript). */\n artifactTypeFor?: (toolName: string) => string | undefined\n maxTurns?: number\n agentModel?: string\n driverModel?: string\n /** Fallback driver models tried when the primary simulated-user model returns empty twice. */\n driverFallbackModels?: string[]\n /** Maximum output tokens for the first agent call in each assistant turn. */\n agentMaxTokens?: number\n /** Maximum output tokens for agent follow-up calls after tool results. */\n toolFollowupMaxTokens?: number\n /** Maximum output tokens for each simulated-user driver response. */\n driverMaxTokens?: number\n /** Maximum tool calls the agent may dispatch inside one assistant turn. */\n maxToolDispatches?: number\n /** Caller-owned execution for the agent leg. Every agent inference step\n * runs through this function; `agentModel` names the model it receives. */\n agentTransport: MultishotTransport\n /** Caller-owned execution for the simulated-user driver leg. Driver model\n * fallback rotation still applies — the transport receives each candidate\n * model in turn. */\n driverTransport: MultishotTransport\n /** Caller-owned execution for the specialist leg the tool executors run.\n * Defaults to `agentTransport`. */\n toolTransport?: MultishotTransport\n signal?: AbortSignal\n}\n\n/** One multishot shot — the conversation engine `runMultishotMatrix` invokes\n * once per cell. `runMultishot` is the default implementation.\n *\n * An alternative engine (a graph-backed conversation, a replay of a recorded\n * transcript, a sandbox-hosted agent) implements this exact signature and\n * reaches the matrix through `RunMultishotMatrixOptions.runShot`. The matrix\n * keeps every other cell mechanic — cell fan-out, concurrency, the cost\n * ceiling, the judge slots, the cell composite, and the per-cell writers — so\n * swapping the engine needs no copy of the cell body. */\nexport type MultishotShot<TPersona extends MultishotPersona> = (\n opts: RunMultishotOptions<TPersona>,\n) => Promise<MultishotResult>\n\n/** The package's reference conversation engine, and the referent of three\n * things that stop working without it.\n *\n * 1. `runMultishotMatrix` runs it as the per-cell engine when the caller names\n * no `runShot`, so the matrix always has an engine to run.\n * 2. `golden.test.ts` proves the frozen records against it on every run, and\n * perturbs it to prove the records detect a change. Records checked only\n * against a replay of themselves prove nothing.\n * 3. The repo's recording command names it as `--engine`. The script defaults\n * no engine, so a version records whichever one the caller names — and a\n * record set minted from a consumer's engine would let a product's wiring\n * define this package's frozen contract.\n *\n * An alternative engine reaches the matrix through `runShot` and reaches the\n * records through `assertMultishotGoldenScenario`. Neither seam removes the\n * three roles above. */\nexport async function runMultishot<TPersona extends MultishotPersona>(\n opts: RunMultishotOptions<TPersona>,\n): Promise<MultishotResult> {\n return runMultishotConversation(opts, async (conversation) => {\n for (let turn = 0; turn < conversation.maxTurns; turn++) {\n await conversation.agentTurn(turn)\n if (turn < conversation.maxTurns - 1) await conversation.driverTurn(turn)\n }\n })\n}\n","// Multishot matrix wrapper — sweeps profiles × personas × reps, runs\n// the driver-agent loop per cell, applies up to three configured judges,\n// persists per-cell artifacts, and aggregates by axis.\n//\n// Uses runAgentMatrix from @tangle-network/agent-eval/matrix under the\n// hood so cell scheduling + concurrency + cost ceiling are unified with\n// other matrix consumers.\n\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { CostProvenance } from '../cost-ledger'\nimport type { MatrixResult } from '../matrix'\nimport { runAgentMatrix, withCellSpend } from '../matrix'\nimport { type MultishotJudgeConfig, type JudgeScore, runJudge } from './judges'\nimport { type MultishotShot, runMultishot } from './multishot'\nimport {\n assertMultishotShotResult,\n type MultishotArtifact,\n type MultishotMessage,\n type MultishotPersona,\n type MultishotShape,\n type MultishotToolDefinition,\n type MultishotToolExecutor,\n type MultishotTransport,\n} from './types'\n\nexport interface ConversationJudgeInput<TPersona extends MultishotPersona> {\n transcript: MultishotMessage[]\n persona: TPersona\n}\n\nexport interface ArtifactJudgeInput<TPersona extends MultishotPersona> {\n artifact: MultishotArtifact\n persona: TPersona\n}\n\nexport interface MultishotJudges<TPersona extends MultishotPersona> {\n /** Scores the full transcript end-to-end (always runs). */\n conversation: MultishotJudgeConfig<ConversationJudgeInput<TPersona>>\n /** Scores each code-type artifact. Optional — omit when domain has no code artifacts. */\n codeReview?: MultishotJudgeConfig<ArtifactJudgeInput<TPersona>>\n /** Scores each non-code (research/content/template) artifact. Optional. */\n contentQuality?: MultishotJudgeConfig<ArtifactJudgeInput<TPersona>>\n /** Which artifact types route to codeReview. Defaults to ['code']. */\n codeArtifactTypes?: string[]\n /** Which artifact types route to contentQuality. Defaults to ['research']. */\n contentArtifactTypes?: string[]\n}\n\nexport interface CellCompositeScore {\n composite: number\n conversation: JudgeScore\n codeReview?: {\n perArtifact: Array<JudgeScore & { turn: number; type: string }>\n composite: number\n }\n contentQuality?: {\n perArtifact: Array<JudgeScore & { turn: number; type: string }>\n composite: number\n }\n}\n\nexport interface RunMultishotMatrixOptions<TPersona extends MultishotPersona> {\n /** AgentProfile axis (matrix primary). */\n profiles: Array<{ id: string; value: AgentProfile }>\n /** Persona axis. */\n personas: TPersona[]\n /** Persona-shaping callbacks. Optional — omitted callbacks are derived per\n * cell from that cell's profile + persona payload (pure-profile path). */\n shape?: MultishotShape<TPersona>\n /** Judge configurations. */\n judges: MultishotJudges<TPersona>\n /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */\n tools?: MultishotToolDefinition[]\n /** Map from tool name → inline executor. Must align with `tools`. */\n toolExecutors?: Record<string, MultishotToolExecutor>\n /** Tool name → artifact type label. Defaults to research/code mapping. */\n artifactTypeFor?: (toolName: string) => string | undefined\n /** Where per-cell artifacts land. Cells write to `<runDir>/<profileId>/<personaId>/rep-N/`. */\n runDir: string\n /** Replicates per (profile, persona) cell. */\n reps?: number\n /** Max conversation turns per cell. */\n maxTurns?: number\n /** Maximum tool calls the agent may dispatch inside one assistant turn. */\n maxToolDispatches?: number\n /** Max concurrent cells. */\n maxConcurrency?: number\n /** Total $ ceiling across the matrix; cells aborted past this. */\n costCeiling?: number\n /** Upper bound on what one cell can spend. A cell whose cost is a subtotal\n * is charged this bound against `costCeiling` instead of its known amount,\n * so hidden spend cannot walk the run past its budget. */\n maxCellCostUsd?: number\n /** Agent model. */\n agentModel?: string\n /** Driver model. */\n driverModel?: string\n /** Fallback driver models tried when the primary simulated-user model returns empty twice. */\n driverFallbackModels?: string[]\n /** Maximum output tokens for the first agent call in each assistant turn. */\n agentMaxTokens?: number\n /** Maximum output tokens for agent follow-up calls after tool results. */\n toolFollowupMaxTokens?: number\n /** Maximum output tokens for each simulated-user driver response. */\n driverMaxTokens?: number\n /** Maximum output tokens for each judge response. */\n judgeMaxTokens?: number\n /** Caller-owned execution for the agent leg of every cell (see\n * RunMultishotOptions.agentTransport). Judges are unaffected; each judge\n * carries its own transport in MultishotJudges. */\n agentTransport: MultishotTransport\n /** Caller-owned execution for the simulated-user driver leg of every cell. */\n driverTransport: MultishotTransport\n /** Caller-owned execution for the specialist leg the tool executors run in\n * every cell. Defaults to `agentTransport`. */\n toolTransport?: MultishotTransport\n /** Conversation engine for every cell. Defaults to `runMultishot`.\n *\n * The matrix owns everything around the shot — cell fan-out, concurrency,\n * the cost ceiling, the judge slots, the cell composite, the per-cell\n * artifact writers and the run summary — and forwards the whole cell input\n * to this function, so an alternative engine replaces ONLY the\n * conversation. Every option on this interface that `runMultishot` accepts\n * reaches the shot unchanged. `RunMultishotOptions.signal` has no\n * matrix-level counterpart and is not forwarded; a shot owns its own\n * cancellation.\n *\n * A shot that resolves with a value outside `MultishotResult` throws\n * `MultishotShotResultError` for that cell. The default engine is never\n * used as a fallback. */\n runShot?: MultishotShot<TPersona>\n}\n\n/** Per-cell output the multishot matrix records in `MatrixResult.cells`.\n * A consumer that supplies its own `runShot` reads the matrix through this\n * type instead of declaring a structural copy. */\nexport interface MultishotCellOutput {\n turns: number\n toolCalls: number\n artifactCount: number\n}\n\ninterface ArtifactJudgeRun {\n score: JudgeScore & { turn: number; type: string }\n cost: CostProvenance\n}\n\n/** Mean composite over non-failed scores. `0` when the list is empty (a\n * configured judge with nothing to score contributes 0, matching the cell\n * composite's long-standing semantics); `null` when scores exist but every\n * one failed — no signal, so the slot must be EXCLUDED from the cell mean\n * rather than dragging it to zero. */\nfunction meanCompositeExcludingFailed(scores: ReadonlyArray<JudgeScore>): number | null {\n if (scores.length === 0) return 0\n const live = scores.filter((s) => !s.failed)\n if (live.length === 0) return null\n return live.reduce((sum, s) => sum + s.composite, 0) / live.length\n}\n\nexport interface CellCompositeInput {\n conversation: JudgeScore\n /** Present iff the codeReview judge is configured. */\n codeReviews?: ReadonlyArray<JudgeScore>\n /** Present iff the contentQuality judge is configured. */\n contentReviews?: ReadonlyArray<JudgeScore>\n}\n\n/** Cell composite = mean over configured judge slots, excluding failed\n * scores: a failed conversation judge or an all-failed artifact slot carries\n * no signal and is dropped from the mean. `composite` is 0 only when EVERY\n * configured slot failed (`allJudgesFailed` distinguishes that from a real\n * zero). Pure — exported for deterministic testing. */\nexport function computeCellComposite(input: CellCompositeInput): {\n composite: number\n codeComposite: number\n contentComposite: number\n allJudgesFailed: boolean\n} {\n const contributions: number[] = []\n if (!input.conversation.failed) contributions.push(input.conversation.composite)\n\n const codeMean = input.codeReviews ? meanCompositeExcludingFailed(input.codeReviews) : undefined\n if (typeof codeMean === 'number') contributions.push(codeMean)\n const contentMean = input.contentReviews\n ? meanCompositeExcludingFailed(input.contentReviews)\n : undefined\n if (typeof contentMean === 'number') contributions.push(contentMean)\n\n return {\n composite:\n contributions.length === 0\n ? 0\n : contributions.reduce((s, v) => s + v, 0) / contributions.length,\n codeComposite: codeMean ?? 0,\n contentComposite: contentMean ?? 0,\n allJudgesFailed: contributions.length === 0,\n }\n}\n\nexport interface RunMultishotMatrixResult {\n matrix: MatrixResult<MultishotCellOutput>\n}\n\nexport async function runMultishotMatrix<TPersona extends MultishotPersona>(\n opts: RunMultishotMatrixOptions<TPersona>,\n): Promise<RunMultishotMatrixResult> {\n const codeTypes = new Set(opts.judges.codeArtifactTypes ?? ['code'])\n const contentTypes = new Set(opts.judges.contentArtifactTypes ?? ['research'])\n const runShot: MultishotShot<TPersona> = opts.runShot ?? runMultishot\n mkdirSync(opts.runDir, { recursive: true })\n\n const matrix = await runAgentMatrix<MultishotCellOutput>({\n axes: [\n { name: 'profile', values: opts.profiles },\n { name: 'persona', values: opts.personas.map((p) => ({ id: p.id, value: p })) },\n ],\n reps: opts.reps ?? 1,\n maxConcurrency: opts.maxConcurrency ?? 2,\n costCeiling: opts.costCeiling,\n maxCellCostUsd: opts.maxCellCostUsd,\n async runCell(cell) {\n const cellStartedAt = Date.now()\n const profile = cell.axes.profile?.value as AgentProfile\n const persona = cell.axes.persona?.value as TPersona\n const profileId = String(cell.axes.profile?.id ?? 'unknown')\n const personaId = String(cell.axes.persona?.id ?? 'unknown')\n\n // A shot that throws declares its own spend (see `runMultishot`). Rethrow\n // it untouched: a shot that declared nothing spent an unknown amount, and\n // claiming a number here would report a fabricated total.\n const sim = await runShot({\n profile,\n persona,\n shape: opts.shape,\n tools: opts.tools,\n toolExecutors: opts.toolExecutors,\n artifactTypeFor: opts.artifactTypeFor,\n maxTurns: opts.maxTurns,\n maxToolDispatches: opts.maxToolDispatches,\n agentModel: opts.agentModel,\n driverModel: opts.driverModel,\n driverFallbackModels: opts.driverFallbackModels,\n agentMaxTokens: opts.agentMaxTokens,\n toolFollowupMaxTokens: opts.toolFollowupMaxTokens,\n driverMaxTokens: opts.driverMaxTokens,\n agentTransport: opts.agentTransport,\n driverTransport: opts.driverTransport,\n toolTransport: opts.toolTransport,\n })\n // Everything from here on runs with the shot's spend already committed.\n // A throw past this line must carry it, or the money leaves the matrix's\n // cumulative sum and the cost ceiling under-counts the run.\n const shotCostUsd = shotCostSubtotal(sim)\n // A shot that says nothing about provenance is taken at its word, which\n // is how every engine written before the field behaved.\n const shotCostComplete = sim?.costProvenance?.kind !== 'uncaptured'\n let judgeCostUsd = 0\n let judgeCostComplete = false\n // Where the cell is, so a throw declares the right completeness: before\n // the judges only the shot has spent, while they are in flight their\n // spend is unknown, and after they settle their receipts decide.\n let phase: 'validate' | 'judging' | 'scoring' = 'validate'\n try {\n assertMultishotShotResult(sim)\n\n const codeArtifacts = sim.artifacts.filter((a) => codeTypes.has(a.type))\n const contentArtifacts = sim.artifacts.filter((a) => contentTypes.has(a.type))\n\n phase = 'judging'\n const [conversationRun, codeReviewRuns, contentReviewRuns] = await Promise.all([\n runJudge(withJudgeMaxTokens(opts.judges.conversation, opts.judgeMaxTokens), {\n transcript: sim.transcript,\n persona,\n }),\n opts.judges.codeReview\n ? Promise.all(\n codeArtifacts.map((artifact) =>\n runJudge(withJudgeMaxTokens(opts.judges.codeReview!, opts.judgeMaxTokens), {\n artifact,\n persona,\n }).then((result) => ({\n score: {\n ...result.score,\n turn: artifact.turn,\n type: artifact.type,\n },\n cost: result.cost,\n })),\n ),\n )\n : Promise.resolve([] as ArtifactJudgeRun[]),\n opts.judges.contentQuality\n ? Promise.all(\n contentArtifacts.map((artifact) =>\n runJudge(withJudgeMaxTokens(opts.judges.contentQuality!, opts.judgeMaxTokens), {\n artifact,\n persona,\n }).then((result) => ({\n score: {\n ...result.score,\n turn: artifact.turn,\n type: artifact.type,\n },\n cost: result.cost,\n })),\n ),\n )\n : Promise.resolve([] as ArtifactJudgeRun[]),\n ])\n const judgeRuns = [conversationRun, ...codeReviewRuns, ...contentReviewRuns]\n judgeCostUsd = judgeRuns.reduce((sum, run) => sum + (run.cost.usd ?? 0), 0)\n judgeCostComplete = judgeRuns.every((run) => run.cost.kind !== 'uncaptured')\n phase = 'scoring'\n\n const conversation = conversationRun.score\n const codeReviews = codeReviewRuns.map((run) => run.score)\n const contentReviews = contentReviewRuns.map((run) => run.score)\n\n const { composite, codeComposite, contentComposite, allJudgesFailed } =\n computeCellComposite({\n conversation,\n codeReviews: opts.judges.codeReview ? codeReviews : undefined,\n contentReviews: opts.judges.contentQuality ? contentReviews : undefined,\n })\n\n const cellScore: CellCompositeScore = { composite, conversation }\n if (opts.judges.codeReview)\n cellScore.codeReview = { perArtifact: codeReviews, composite: codeComposite }\n if (opts.judges.contentQuality)\n cellScore.contentQuality = { perArtifact: contentReviews, composite: contentComposite }\n\n const cellDir = join(opts.runDir, profileId, personaId, `rep-${cell.rep}`)\n mkdirSync(cellDir, { recursive: true })\n writeFileSync(join(cellDir, 'transcript.json'), JSON.stringify(sim.transcript, null, 2))\n writeFileSync(join(cellDir, 'artifacts.json'), JSON.stringify(sim.artifacts, null, 2))\n writeFileSync(join(cellDir, 'scores.json'), JSON.stringify(cellScore, null, 2))\n\n const notes = [`convo=${conversation.composite.toFixed(1)}`]\n if (opts.judges.codeReview) notes.push(`code=${codeComposite.toFixed(1)}`)\n if (opts.judges.contentQuality) notes.push(`content=${contentComposite.toFixed(1)}`)\n if (allJudgesFailed) notes.push('all-judges-failed')\n if (!judgeCostComplete) notes.push('judge-cost-incomplete')\n\n return {\n output: {\n turns: sim.transcript.length,\n toolCalls: sim.toolCalls,\n artifactCount: sim.artifacts.length,\n },\n verdict: { valid: composite >= 5, score: composite, notes: notes.join(' ') },\n costUsd: sim.costUsd + judgeCostUsd,\n // Either leg can leave the cell total a subtotal: a judge whose cost\n // the router never reported, or a shot that declared its own spend\n // uncaptured. The matrix counts the known part toward the ceiling and\n // reports the cell as under-counted rather than presenting the sum as\n // complete.\n costProvenance:\n judgeCostComplete && shotCostComplete\n ? { kind: 'estimated', usd: sim.costUsd + judgeCostUsd }\n : { kind: 'uncaptured', usd: null },\n durationMs: sim.durationMs,\n }\n } catch (err) {\n // No usable shot subtotal means the cell's spend is genuinely unknown;\n // rethrow untouched so the matrix records it as uncaptured instead of\n // billing a number this frame cannot support.\n if (shotCostUsd === undefined) throw err\n throw withCellSpend(err, {\n costUsd: shotCostUsd + judgeCostUsd,\n durationMs: Date.now() - cellStartedAt,\n // The judges bill before they settle, so a throw among them leaves a\n // subtotal. Before they start, and after they settle with every\n // receipt captured, the amount is the cell's whole spend — unless the\n // shot already declared its own part incomplete.\n kind:\n shotCostComplete && (phase === 'validate' || (phase === 'scoring' && judgeCostComplete))\n ? 'estimated'\n : 'uncaptured',\n })\n }\n },\n })\n\n // Persist top-level summary.\n const summary = {\n cells: matrix.summary.totalCells,\n passRate: matrix.summary.overallPassRate,\n meanScore: matrix.summary.overallMeanScore,\n totalCostUsd: matrix.summary.totalCostUsd,\n costUncapturedCells: matrix.summary.costUncapturedCells,\n ceilingChargedUsd: matrix.summary.ceilingChargedUsd,\n durationMs: matrix.summary.durationMs,\n runsExecuted: matrix.summary.runsExecuted,\n cellsSkipped: matrix.summary.cellsSkipped,\n byProfile: matrix.byAxis.profile,\n byPersona: matrix.byAxis.persona,\n }\n writeFileSync(join(opts.runDir, 'summary.json'), JSON.stringify(summary, null, 2))\n\n // A reader of the on-disk summary must not take the cost line as the run's\n // whole spend when some cells reported only a subtotal.\n const uncaptured = matrix.summary.costUncapturedCells\n const costLabel = uncaptured > 0 ? 'Cost (at least)' : 'Cost'\n\n const md: string[] = [\n `# Multishot matrix`,\n ``,\n `**Cells**: ${matrix.summary.totalCells} | **Pass rate**: ${(matrix.summary.overallPassRate * 100).toFixed(0)}% | **Mean**: ${matrix.summary.overallMeanScore.toFixed(2)} | **${costLabel}**: $${matrix.summary.totalCostUsd.toFixed(2)} | **Duration**: ${(matrix.summary.durationMs / 1000).toFixed(0)}s`,\n ``,\n ...(uncaptured > 0\n ? [\n `> ${uncaptured} of ${matrix.summary.runsExecuted} cells reported a cost subtotal, not a total. Real spend is higher than every cost figure below.`,\n ``,\n ]\n : []),\n `## By profile`,\n ``,\n '| profile | pass | mean | cost |',\n '|---|---|---|---|',\n ...Object.entries(matrix.byAxis.profile ?? {}).map(\n ([id, s]) =>\n `| ${id} | ${(s.passRate * 100).toFixed(0)}% | ${s.meanScore.toFixed(2)} | $${s.totalCostUsd.toFixed(2)} |`,\n ),\n ``,\n `## By persona`,\n ``,\n '| persona | pass | mean | cost |',\n '|---|---|---|---|',\n ...Object.entries(matrix.byAxis.persona ?? {}).map(\n ([id, s]) =>\n `| ${id} | ${(s.passRate * 100).toFixed(0)}% | ${s.meanScore.toFixed(2)} | $${s.totalCostUsd.toFixed(2)} |`,\n ),\n ``,\n ]\n writeFileSync(join(opts.runDir, 'summary.md'), md.join('\\n'))\n\n return { matrix }\n}\n\n/** The shot's own spend, when the value it resolved with reports a usable\n * amount. `undefined` when it does not — a malformed shot result is exactly\n * the case where the number cannot be trusted, and billing a wrong figure is\n * worse than recording the cell as uncaptured. */\nfunction shotCostSubtotal(\n sim: { costUsd?: unknown; costProvenance?: CostProvenance } | null | undefined,\n): number | undefined {\n const value = sim?.costUsd\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined\n}\n\nfunction withJudgeMaxTokens<TInput>(\n judge: MultishotJudgeConfig<TInput>,\n maxTokens: number | undefined,\n): MultishotJudgeConfig<TInput> {\n if (maxTokens === undefined || judge.maxTokens !== undefined) return judge\n return { ...judge, maxTokens }\n}\n"],"mappings":"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"}
@@ -1,9 +1,8 @@
1
- //#region src/math/nonnegative-number.ts
1
+ // src/math/nonnegative-number.ts
2
2
  /** Finite non-negative values can be added to cost and duration totals. */
3
3
  function isNonnegativeFiniteNumber(value) {
4
4
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
5
5
  }
6
- //#endregion
7
6
  export { isNonnegativeFiniteNumber as t };
8
7
 
9
- //# sourceMappingURL=nonnegative-number-DvdMxg_f.js.map
8
+ //# sourceMappingURL=nonnegative-number-lEYbOsuh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nonnegative-number-DvdMxg_f.js","names":[],"sources":["../src/math/nonnegative-number.ts"],"sourcesContent":["/** Finite non-negative values can be added to cost and duration totals. */\nexport function isNonnegativeFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n}\n"],"mappings":";;AACA,SAAgB,0BAA0B,OAAiC;CACzE,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS;AACzE"}
1
+ {"version":3,"file":"nonnegative-number-lEYbOsuh.js","names":[],"sources":["../src/math/nonnegative-number.ts"],"sourcesContent":["/** Finite non-negative values can be added to cost and duration totals. */\nexport function isNonnegativeFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n}\n"],"mappings":";;AACA,SAAgB,0BAA0B,OAAiC;CACzE,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS;AACzE"}
package/dist/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "@tangle-network/agent-eval — wire protocol",
5
- "version": "0.221.8",
5
+ "version": "0.222.0",
6
6
  "description": "HTTP and stdio RPC interface to agent-eval. The TypeScript runtime is the source of truth; this spec is the contract that cross-language clients (Python, Rust, Go) generate from.\n\nWire-protocol version: 1.1.0. Bumps on breaking changes to request/response schemas.",
7
7
  "contact": {
8
8
  "name": "Tangle Network",
@@ -1,9 +1,9 @@
1
- import { s as ValidationError } from "./errors-BcOs5MKW.js";
1
+ import { s as ValidationError } from "./errors-DeEEV9Vx.js";
2
2
  import { LLM_MODEL_ATTR_KEYS, SPAN_KIND_ATTR_KEYS as SPAN_KIND_ATTR_KEYS$1 } from "./trace-attributes.js";
3
- import "./otlp-attributes-D9ptWaIJ.js";
4
- import { i as summarizeTraceErrors, n as recordAggregateMeasurements, r as summarizeExecutionMeasurements, t as readTaskFailureLabels } from "./task-failure-attributes-oIK3BhCR.js";
3
+ import "./otlp-attributes-Boeb7gtH.js";
4
+ import { i as summarizeTraceErrors, n as recordAggregateMeasurements, r as summarizeExecutionMeasurements, t as readTaskFailureLabels } from "./task-failure-attributes-CC6VuIpk.js";
5
5
  import { resolveSpanKind } from "@tangle-network/agent-trace-contract";
6
- //#region src/contract/intake/otel-spans.ts
6
+ // src/contract/intake/otel-spans.ts
7
7
  /**
8
8
  * # `intake/otel-spans` — OTel `TraceSpanEvent[]` → `RunRecord[]`.
9
9
  *
@@ -263,7 +263,6 @@ function collectNumericAttrs(spans) {
263
263
  for (const span of spans) for (const [k, v] of Object.entries(span.attributes)) if (typeof v === "number" && Number.isFinite(v)) raw[k] = v;
264
264
  return raw;
265
265
  }
266
- //#endregion
267
266
  export { fromOtelSpans as t };
268
267
 
269
- //# sourceMappingURL=otel-spans-64hmQqON.js.map
268
+ //# sourceMappingURL=otel-spans-BsGzTWIK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"otel-spans-64hmQqON.js","names":["SPAN_KIND_ATTR_KEYS"],"sources":["../src/contract/intake/otel-spans.ts"],"sourcesContent":["/**\n * # `intake/otel-spans` — OTel `TraceSpanEvent[]` → `RunRecord[]`.\n *\n * Turns an existing observability stream into the substrate-canonical\n * `RunRecord` shape so consumers with logs but no eval discipline can\n * call `analyzeRuns()` against their production traffic immediately.\n *\n * Pivot rule: spans are grouped by `tangle.runId` (the same attribute the\n * hosted-tier wire format uses) or, when absent, by `traceId`. One group\n * becomes one `RunRecord`. The root span (no `parentSpanId`) supplies:\n *\n * - `runId` (the group key)\n * - `wallMs` from `endTimeUnixNano - startTimeUnixNano`\n * - `model` from `gen_ai.request.model` / `llm.model` / `tangle.model`\n * - task failure class and detail from explicit `tangle.task.*` attributes\n * - cost from `cost.usd` / `gen_ai.usage.cost_usd` / `tangle.cost.usd`\n * - token usage from model-call input, output, cache-read, and cache-write\n * attributes without double-counting aggregate parent spans\n * - task quality from an explicit `scoreForRun` callback or a designated\n * evaluation attribute on a root / `EVALUATOR` span; `outcome.raw`\n * collects every numeric attribute without promoting it to task quality.\n *\n * Errored tool, model, and child-agent spans contribute to execution-error\n * counts. Root process, guardrail, evaluator, propagated parent, and unknown\n * errors retain separate counters. Only one failed root can set\n * `RunRecord.terminalOutcome` and `RunRecord.terminalFailureReason`; a child\n * error cannot become a task failure.\n */\n\nimport { resolveSpanKind } from '@tangle-network/agent-trace-contract'\nimport { ValidationError } from '../../errors'\nimport type { TraceSpanEvent } from '../../hosted/types'\nimport type {\n JudgeScoresRecord,\n RunOutcome,\n RunRecord,\n RunSplitTag,\n RunTerminalOutcome,\n} from '../../run-record'\nimport { summarizeTraceErrors, type TraceErrorRole } from '../../trace/error-classification'\nimport {\n recordAggregateMeasurements,\n summarizeExecutionMeasurements,\n} from '../../trace/execution-measurements'\nimport { LLM_MODEL_ATTR_KEYS, SPAN_KIND_ATTR_KEYS } from '../../trace/otlp-attributes'\nimport { readTaskFailureLabels } from '../../trace/task-failure-attributes'\n\nconst TASK_SCORE_ATTR_KEYS = [\n 'gen_ai.evaluation.score.value',\n 'tangle.task.score',\n 'eval.score',\n 'tangle.score',\n] as const\nconst MODEL_KEYS = ['tangle.model', ...LLM_MODEL_ATTR_KEYS, 'model']\nconst PROMPT_HASH_KEYS = ['tangle.prompt_hash', 'prompt.hash']\nconst CONFIG_HASH_KEYS = ['tangle.config_hash', 'config.hash']\n\nexport interface FromOtelSpansOptions {\n spans: TraceSpanEvent[]\n /** Default split tag for synthesized records. Defaults to `'holdout'`. */\n defaultSplit?: RunSplitTag\n /** Default `experimentId` when not present on any span. */\n experimentId?: string\n /**\n * Explicit task-quality score for a logical run. The callback receives\n * spans in deterministic time/id order. Its value must agree with any\n * designated score attributes present on root or `EVALUATOR` spans.\n */\n scoreForRun?: (runId: string, spans: readonly TraceSpanEvent[]) => number | undefined\n}\n\nexport function fromOtelSpans(opts: FromOtelSpansOptions): RunRecord[] {\n const { spans, defaultSplit = 'holdout', experimentId = 'otel-corpus' } = opts\n const grouped = groupSpans(spans)\n\n const runs: RunRecord[] = []\n for (const [groupKey, groupSpans] of grouped) {\n const root = findRoot(groupSpans)\n if (!root) continue\n const measurements = summarizeExecutionMeasurements(\n groupSpans.map((span) => ({\n id: span.spanId,\n ...(span.parentSpanId ? { parentId: span.parentSpanId } : {}),\n attributes: span.attributes,\n kind: errorRoleForSpan(span),\n })),\n )\n const callSpanIds = new Set(measurements.callSpanIds)\n const callSpans = groupSpans.filter((span) => callSpanIds.has(span.spanId))\n const wallMs = unixNanoDurationMs(root.startTimeUnixNano, root.endTimeUnixNano)\n const model =\n readAttrString(callSpans, MODEL_KEYS) ??\n readAttrString(groupSpans, MODEL_KEYS) ??\n 'unknown@unknown'\n const capturedCost =\n (measurements.cost.complete ? measurements.cost.value : undefined) ??\n measurements.aggregate?.costUsd\n const costUsd = capturedCost ?? null\n const scenarioId = readConsistentScenarioId(groupKey, groupSpans) ?? groupKey\n const promptHash = readAttrString(groupSpans, PROMPT_HASH_KEYS) ?? 'sha256:unknown'\n const configHash = readAttrString(groupSpans, CONFIG_HASH_KEYS) ?? 'sha256:unknown'\n const score = resolveTaskScore(groupKey, groupSpans, opts.scoreForRun)\n const taskFailure = readTaskFailureLabels(\n groupSpans.filter((span) => !span.parentSpanId && isTerminalRootCandidate(span)),\n `fromOtelSpans: run '${groupKey}'`,\n )\n\n const rawNumeric = collectNumericAttrs(groupSpans)\n const errorSummary = summarizeTraceErrors(\n groupSpans.map((span) => ({\n id: spanIdentity(span),\n ...(span.parentSpanId ? { parentId: parentIdentity(span) } : {}),\n role: errorRoleForSpan(span),\n error: span.status?.code === 'ERROR',\n processRoot: !span.parentSpanId && isTerminalRootCandidate(span),\n })),\n )\n rawNumeric.error_span_count = errorSummary.total\n rawNumeric.execution_error_count = errorSummary.execution\n rawNumeric.process_error_count = errorSummary.process\n rawNumeric.guardrail_error_count = errorSummary.guardrail\n rawNumeric.judge_error_count = errorSummary.evaluation\n rawNumeric.propagated_error_count = errorSummary.propagated\n rawNumeric.unclassified_error_count = errorSummary.unclassified\n rawNumeric.llm_span_count = measurements.modelCallCount\n if (measurements.cost.value !== undefined && !measurements.cost.complete) {\n rawNumeric.partial_observed_cost_usd = measurements.cost.value\n }\n recordAggregateMeasurements(rawNumeric, measurements.aggregate)\n\n const judgeScores: JudgeScoresRecord | undefined =\n score !== undefined\n ? {\n perJudge: { 'otel-derived': { score } },\n perDimMean: { score },\n composite: score,\n }\n : undefined\n\n const terminalOutcome = terminalOutcomeFromRoots(groupSpans)\n const failedRoot =\n terminalOutcome === 'failed'\n ? groupSpans.find(\n (span) =>\n !span.parentSpanId && isTerminalRootCandidate(span) && span.status?.code === 'ERROR',\n )\n : undefined\n const outcome: RunOutcome = {\n raw: rawNumeric,\n ...(judgeScores ? { judgeScores } : {}),\n }\n if (score !== undefined) {\n if (defaultSplit === 'holdout') outcome.holdoutScore = score\n else outcome.searchScore = score\n }\n\n runs.push({\n runId: groupKey,\n experimentId,\n candidateId: (root.attributes['tangle.candidateId'] as string | undefined) ?? 'otel-default',\n seed: 0,\n model,\n promptHash,\n configHash,\n commitSha: (root.attributes['tangle.commit_sha'] as string | undefined) ?? 'unknown',\n wallMs,\n costUsd,\n costProvenance:\n capturedCost === undefined\n ? { kind: 'uncaptured', usd: null }\n : { kind: 'observed', usd: capturedCost },\n tokenUsage: measurements.tokenUsage,\n terminalOutcome,\n ...(failedRoot\n ? { terminalFailureReason: failedRoot.status?.message ?? failedRoot.name }\n : {}),\n outcome,\n ...taskFailure,\n splitTag: defaultSplit,\n scenarioId,\n })\n }\n return runs\n}\n\nfunction terminalOutcomeFromRoots(spans: TraceSpanEvent[]): RunTerminalOutcome {\n const roots = spans.filter((span) => !span.parentSpanId && isTerminalRootCandidate(span))\n if (roots.length !== 1) return 'unknown'\n if (roots[0]!.status?.code === 'OK') return 'succeeded'\n if (roots[0]!.status?.code === 'ERROR') return 'failed'\n return 'unknown'\n}\n\nfunction isTerminalRootCandidate(span: TraceSpanEvent): boolean {\n const role = errorRoleForSpan(span)\n if (role === 'LLM' || role === 'TOOL' || role === 'GUARDRAIL' || role === 'EVALUATOR') {\n return false\n }\n return true\n}\n\nfunction readSpanKind(span: TraceSpanEvent): string | undefined {\n return readAttrString([span], [...SPAN_KIND_ATTR_KEYS, 'span.kind'])?.toUpperCase()\n}\n\nfunction errorRoleForSpan(span: TraceSpanEvent): TraceErrorRole {\n return resolveSpanKind({\n kind: readSpanKind(span),\n name: span.name,\n attributes: span.attributes,\n })\n}\n\nfunction spanIdentity(span: TraceSpanEvent): string {\n return `${span.traceId}:${span.spanId}`\n}\n\nfunction parentIdentity(span: TraceSpanEvent): string {\n return `${span.traceId}:${span.parentSpanId}`\n}\n\n// ── Internal helpers ────────────────────────────────────────────────\n\nfunction groupSpans(spans: TraceSpanEvent[]): Map<string, TraceSpanEvent[]> {\n const m = new Map<string, TraceSpanEvent[]>()\n for (const span of spans) {\n const key = (span['tangle.runId'] as string | undefined) ?? span.traceId\n const list = m.get(key) ?? []\n list.push(span)\n m.set(key, list)\n }\n return m\n}\n\nfunction findRoot(group: TraceSpanEvent[]): TraceSpanEvent | undefined {\n const structuralRoots = group.filter((span) => !span.parentSpanId)\n const terminalRoots = structuralRoots.filter(isTerminalRootCandidate)\n const pool =\n terminalRoots.length > 0 ? terminalRoots : structuralRoots.length > 0 ? structuralRoots : group\n return orderSpans(pool)[0]\n}\n\nfunction readAttrString(spans: TraceSpanEvent[], keys: string[]): string | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'string' && v.length > 0) return v\n }\n }\n return undefined\n}\n\nfunction readConsistentScenarioId(\n runId: string,\n spans: readonly TraceSpanEvent[],\n): string | undefined {\n const values = new Set<string>()\n for (const span of spans) {\n const topLevel = span['tangle.scenarioId']\n if (typeof topLevel === 'string' && topLevel.length > 0) values.add(topLevel)\n const attribute = span.attributes['tangle.scenarioId']\n if (typeof attribute === 'string' && attribute.length > 0) values.add(attribute)\n }\n if (values.size > 1) {\n throw new ValidationError(\n `fromOtelSpans: conflicting scenario ids for run '${runId}': ${[...values].sort().join(', ')}`,\n )\n }\n return values.values().next().value\n}\n\ninterface TaskScoreSource {\n label: string\n value: number\n}\n\nfunction resolveTaskScore(\n runId: string,\n spans: TraceSpanEvent[],\n scoreForRun: FromOtelSpansOptions['scoreForRun'],\n): number | undefined {\n const orderedSpans = orderSpans(spans)\n const sources: TaskScoreSource[] = []\n\n if (scoreForRun) {\n const supplied: unknown = scoreForRun(runId, orderedSpans)\n if (supplied !== undefined) {\n if (typeof supplied !== 'number' || !Number.isFinite(supplied)) {\n throw new ValidationError(\n `fromOtelSpans: scoreForRun returned a non-finite number for run '${runId}'`,\n )\n }\n sources.push({ label: 'scoreForRun', value: supplied })\n }\n }\n\n for (const span of orderedSpans) {\n const role = errorRoleForSpan(span)\n if (span.parentSpanId && role !== 'EVALUATOR') continue\n if (role === 'EVALUATOR' && span.status?.code === 'ERROR') continue\n for (const key of TASK_SCORE_ATTR_KEYS) {\n if (!Object.hasOwn(span.attributes, key)) continue\n sources.push({\n label: `span '${span.spanId}' attribute '${key}'`,\n value: parseTaskScoreAttribute(runId, span.spanId, key, span.attributes[key]),\n })\n }\n }\n\n if (sources.length === 0) return undefined\n sources.sort((left, right) => left.label.localeCompare(right.label))\n const score = sources[0]!.value\n if (sources.some((source) => source.value !== score)) {\n const details = sources.map((source) => `${source.label}=${source.value}`).join(', ')\n throw new ValidationError(\n `fromOtelSpans: conflicting task-quality scores for run '${runId}': ${details}`,\n )\n }\n return score\n}\n\nfunction parseTaskScoreAttribute(\n runId: string,\n spanId: string,\n key: string,\n value: unknown,\n): number {\n const source = `span '${spanId}' attribute '${key}'`\n if (typeof value === 'string') {\n if (value.trim().length === 0) {\n throw new ValidationError(\n `fromOtelSpans: ${source} is blank for run '${runId}'; task quality must be finite`,\n )\n }\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n return value\n }\n throw new ValidationError(\n `fromOtelSpans: ${source} is not a finite task-quality score for run '${runId}'`,\n )\n}\n\nfunction orderSpans(spans: readonly TraceSpanEvent[]): TraceSpanEvent[] {\n return [...spans].sort(\n (left, right) =>\n compareUnixNano(left.startTimeUnixNano, right.startTimeUnixNano) ||\n left.spanId.localeCompare(right.spanId),\n )\n}\n\nfunction parseUnixNano(value: string): bigint {\n try {\n return BigInt(value)\n } catch {\n throw new ValidationError(`fromOtelSpans: invalid Unix nanosecond timestamp '${value}'`)\n }\n}\n\nfunction compareUnixNano(left: string, right: string): number {\n const leftValue = parseUnixNano(left)\n const rightValue = parseUnixNano(right)\n return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0\n}\n\nfunction unixNanoDurationMs(start: string, end: string): number {\n const delta = parseUnixNano(end) - parseUnixNano(start)\n if (delta <= 0n) return 0\n const wholeMs = delta / 1_000_000n\n const fractionalMs = delta % 1_000_000n\n const value = Number(wholeMs) + Number(fractionalMs) / 1_000_000\n if (!Number.isSafeInteger(Number(wholeMs))) {\n throw new ValidationError('fromOtelSpans: span duration exceeds the safe millisecond range')\n }\n return value\n}\n\nfunction collectNumericAttrs(spans: TraceSpanEvent[]): Record<string, number> {\n const raw: Record<string, number> = {}\n for (const span of spans) {\n for (const [k, v] of Object.entries(span.attributes)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[k] = v\n }\n }\n return raw\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"otel-spans-BsGzTWIK.js","names":["SPAN_KIND_ATTR_KEYS"],"sources":["../src/contract/intake/otel-spans.ts"],"sourcesContent":["/**\n * # `intake/otel-spans` — OTel `TraceSpanEvent[]` → `RunRecord[]`.\n *\n * Turns an existing observability stream into the substrate-canonical\n * `RunRecord` shape so consumers with logs but no eval discipline can\n * call `analyzeRuns()` against their production traffic immediately.\n *\n * Pivot rule: spans are grouped by `tangle.runId` (the same attribute the\n * hosted-tier wire format uses) or, when absent, by `traceId`. One group\n * becomes one `RunRecord`. The root span (no `parentSpanId`) supplies:\n *\n * - `runId` (the group key)\n * - `wallMs` from `endTimeUnixNano - startTimeUnixNano`\n * - `model` from `gen_ai.request.model` / `llm.model` / `tangle.model`\n * - task failure class and detail from explicit `tangle.task.*` attributes\n * - cost from `cost.usd` / `gen_ai.usage.cost_usd` / `tangle.cost.usd`\n * - token usage from model-call input, output, cache-read, and cache-write\n * attributes without double-counting aggregate parent spans\n * - task quality from an explicit `scoreForRun` callback or a designated\n * evaluation attribute on a root / `EVALUATOR` span; `outcome.raw`\n * collects every numeric attribute without promoting it to task quality.\n *\n * Errored tool, model, and child-agent spans contribute to execution-error\n * counts. Root process, guardrail, evaluator, propagated parent, and unknown\n * errors retain separate counters. Only one failed root can set\n * `RunRecord.terminalOutcome` and `RunRecord.terminalFailureReason`; a child\n * error cannot become a task failure.\n */\n\nimport { resolveSpanKind } from '@tangle-network/agent-trace-contract'\nimport { ValidationError } from '../../errors'\nimport type { TraceSpanEvent } from '../../hosted/types'\nimport type {\n JudgeScoresRecord,\n RunOutcome,\n RunRecord,\n RunSplitTag,\n RunTerminalOutcome,\n} from '../../run-record'\nimport { summarizeTraceErrors, type TraceErrorRole } from '../../trace/error-classification'\nimport {\n recordAggregateMeasurements,\n summarizeExecutionMeasurements,\n} from '../../trace/execution-measurements'\nimport { LLM_MODEL_ATTR_KEYS, SPAN_KIND_ATTR_KEYS } from '../../trace/otlp-attributes'\nimport { readTaskFailureLabels } from '../../trace/task-failure-attributes'\n\nconst TASK_SCORE_ATTR_KEYS = [\n 'gen_ai.evaluation.score.value',\n 'tangle.task.score',\n 'eval.score',\n 'tangle.score',\n] as const\nconst MODEL_KEYS = ['tangle.model', ...LLM_MODEL_ATTR_KEYS, 'model']\nconst PROMPT_HASH_KEYS = ['tangle.prompt_hash', 'prompt.hash']\nconst CONFIG_HASH_KEYS = ['tangle.config_hash', 'config.hash']\n\nexport interface FromOtelSpansOptions {\n spans: TraceSpanEvent[]\n /** Default split tag for synthesized records. Defaults to `'holdout'`. */\n defaultSplit?: RunSplitTag\n /** Default `experimentId` when not present on any span. */\n experimentId?: string\n /**\n * Explicit task-quality score for a logical run. The callback receives\n * spans in deterministic time/id order. Its value must agree with any\n * designated score attributes present on root or `EVALUATOR` spans.\n */\n scoreForRun?: (runId: string, spans: readonly TraceSpanEvent[]) => number | undefined\n}\n\nexport function fromOtelSpans(opts: FromOtelSpansOptions): RunRecord[] {\n const { spans, defaultSplit = 'holdout', experimentId = 'otel-corpus' } = opts\n const grouped = groupSpans(spans)\n\n const runs: RunRecord[] = []\n for (const [groupKey, groupSpans] of grouped) {\n const root = findRoot(groupSpans)\n if (!root) continue\n const measurements = summarizeExecutionMeasurements(\n groupSpans.map((span) => ({\n id: span.spanId,\n ...(span.parentSpanId ? { parentId: span.parentSpanId } : {}),\n attributes: span.attributes,\n kind: errorRoleForSpan(span),\n })),\n )\n const callSpanIds = new Set(measurements.callSpanIds)\n const callSpans = groupSpans.filter((span) => callSpanIds.has(span.spanId))\n const wallMs = unixNanoDurationMs(root.startTimeUnixNano, root.endTimeUnixNano)\n const model =\n readAttrString(callSpans, MODEL_KEYS) ??\n readAttrString(groupSpans, MODEL_KEYS) ??\n 'unknown@unknown'\n const capturedCost =\n (measurements.cost.complete ? measurements.cost.value : undefined) ??\n measurements.aggregate?.costUsd\n const costUsd = capturedCost ?? null\n const scenarioId = readConsistentScenarioId(groupKey, groupSpans) ?? groupKey\n const promptHash = readAttrString(groupSpans, PROMPT_HASH_KEYS) ?? 'sha256:unknown'\n const configHash = readAttrString(groupSpans, CONFIG_HASH_KEYS) ?? 'sha256:unknown'\n const score = resolveTaskScore(groupKey, groupSpans, opts.scoreForRun)\n const taskFailure = readTaskFailureLabels(\n groupSpans.filter((span) => !span.parentSpanId && isTerminalRootCandidate(span)),\n `fromOtelSpans: run '${groupKey}'`,\n )\n\n const rawNumeric = collectNumericAttrs(groupSpans)\n const errorSummary = summarizeTraceErrors(\n groupSpans.map((span) => ({\n id: spanIdentity(span),\n ...(span.parentSpanId ? { parentId: parentIdentity(span) } : {}),\n role: errorRoleForSpan(span),\n error: span.status?.code === 'ERROR',\n processRoot: !span.parentSpanId && isTerminalRootCandidate(span),\n })),\n )\n rawNumeric.error_span_count = errorSummary.total\n rawNumeric.execution_error_count = errorSummary.execution\n rawNumeric.process_error_count = errorSummary.process\n rawNumeric.guardrail_error_count = errorSummary.guardrail\n rawNumeric.judge_error_count = errorSummary.evaluation\n rawNumeric.propagated_error_count = errorSummary.propagated\n rawNumeric.unclassified_error_count = errorSummary.unclassified\n rawNumeric.llm_span_count = measurements.modelCallCount\n if (measurements.cost.value !== undefined && !measurements.cost.complete) {\n rawNumeric.partial_observed_cost_usd = measurements.cost.value\n }\n recordAggregateMeasurements(rawNumeric, measurements.aggregate)\n\n const judgeScores: JudgeScoresRecord | undefined =\n score !== undefined\n ? {\n perJudge: { 'otel-derived': { score } },\n perDimMean: { score },\n composite: score,\n }\n : undefined\n\n const terminalOutcome = terminalOutcomeFromRoots(groupSpans)\n const failedRoot =\n terminalOutcome === 'failed'\n ? groupSpans.find(\n (span) =>\n !span.parentSpanId && isTerminalRootCandidate(span) && span.status?.code === 'ERROR',\n )\n : undefined\n const outcome: RunOutcome = {\n raw: rawNumeric,\n ...(judgeScores ? { judgeScores } : {}),\n }\n if (score !== undefined) {\n if (defaultSplit === 'holdout') outcome.holdoutScore = score\n else outcome.searchScore = score\n }\n\n runs.push({\n runId: groupKey,\n experimentId,\n candidateId: (root.attributes['tangle.candidateId'] as string | undefined) ?? 'otel-default',\n seed: 0,\n model,\n promptHash,\n configHash,\n commitSha: (root.attributes['tangle.commit_sha'] as string | undefined) ?? 'unknown',\n wallMs,\n costUsd,\n costProvenance:\n capturedCost === undefined\n ? { kind: 'uncaptured', usd: null }\n : { kind: 'observed', usd: capturedCost },\n tokenUsage: measurements.tokenUsage,\n terminalOutcome,\n ...(failedRoot\n ? { terminalFailureReason: failedRoot.status?.message ?? failedRoot.name }\n : {}),\n outcome,\n ...taskFailure,\n splitTag: defaultSplit,\n scenarioId,\n })\n }\n return runs\n}\n\nfunction terminalOutcomeFromRoots(spans: TraceSpanEvent[]): RunTerminalOutcome {\n const roots = spans.filter((span) => !span.parentSpanId && isTerminalRootCandidate(span))\n if (roots.length !== 1) return 'unknown'\n if (roots[0]!.status?.code === 'OK') return 'succeeded'\n if (roots[0]!.status?.code === 'ERROR') return 'failed'\n return 'unknown'\n}\n\nfunction isTerminalRootCandidate(span: TraceSpanEvent): boolean {\n const role = errorRoleForSpan(span)\n if (role === 'LLM' || role === 'TOOL' || role === 'GUARDRAIL' || role === 'EVALUATOR') {\n return false\n }\n return true\n}\n\nfunction readSpanKind(span: TraceSpanEvent): string | undefined {\n return readAttrString([span], [...SPAN_KIND_ATTR_KEYS, 'span.kind'])?.toUpperCase()\n}\n\nfunction errorRoleForSpan(span: TraceSpanEvent): TraceErrorRole {\n return resolveSpanKind({\n kind: readSpanKind(span),\n name: span.name,\n attributes: span.attributes,\n })\n}\n\nfunction spanIdentity(span: TraceSpanEvent): string {\n return `${span.traceId}:${span.spanId}`\n}\n\nfunction parentIdentity(span: TraceSpanEvent): string {\n return `${span.traceId}:${span.parentSpanId}`\n}\n\n// ── Internal helpers ────────────────────────────────────────────────\n\nfunction groupSpans(spans: TraceSpanEvent[]): Map<string, TraceSpanEvent[]> {\n const m = new Map<string, TraceSpanEvent[]>()\n for (const span of spans) {\n const key = (span['tangle.runId'] as string | undefined) ?? span.traceId\n const list = m.get(key) ?? []\n list.push(span)\n m.set(key, list)\n }\n return m\n}\n\nfunction findRoot(group: TraceSpanEvent[]): TraceSpanEvent | undefined {\n const structuralRoots = group.filter((span) => !span.parentSpanId)\n const terminalRoots = structuralRoots.filter(isTerminalRootCandidate)\n const pool =\n terminalRoots.length > 0 ? terminalRoots : structuralRoots.length > 0 ? structuralRoots : group\n return orderSpans(pool)[0]\n}\n\nfunction readAttrString(spans: TraceSpanEvent[], keys: string[]): string | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'string' && v.length > 0) return v\n }\n }\n return undefined\n}\n\nfunction readConsistentScenarioId(\n runId: string,\n spans: readonly TraceSpanEvent[],\n): string | undefined {\n const values = new Set<string>()\n for (const span of spans) {\n const topLevel = span['tangle.scenarioId']\n if (typeof topLevel === 'string' && topLevel.length > 0) values.add(topLevel)\n const attribute = span.attributes['tangle.scenarioId']\n if (typeof attribute === 'string' && attribute.length > 0) values.add(attribute)\n }\n if (values.size > 1) {\n throw new ValidationError(\n `fromOtelSpans: conflicting scenario ids for run '${runId}': ${[...values].sort().join(', ')}`,\n )\n }\n return values.values().next().value\n}\n\ninterface TaskScoreSource {\n label: string\n value: number\n}\n\nfunction resolveTaskScore(\n runId: string,\n spans: TraceSpanEvent[],\n scoreForRun: FromOtelSpansOptions['scoreForRun'],\n): number | undefined {\n const orderedSpans = orderSpans(spans)\n const sources: TaskScoreSource[] = []\n\n if (scoreForRun) {\n const supplied: unknown = scoreForRun(runId, orderedSpans)\n if (supplied !== undefined) {\n if (typeof supplied !== 'number' || !Number.isFinite(supplied)) {\n throw new ValidationError(\n `fromOtelSpans: scoreForRun returned a non-finite number for run '${runId}'`,\n )\n }\n sources.push({ label: 'scoreForRun', value: supplied })\n }\n }\n\n for (const span of orderedSpans) {\n const role = errorRoleForSpan(span)\n if (span.parentSpanId && role !== 'EVALUATOR') continue\n if (role === 'EVALUATOR' && span.status?.code === 'ERROR') continue\n for (const key of TASK_SCORE_ATTR_KEYS) {\n if (!Object.hasOwn(span.attributes, key)) continue\n sources.push({\n label: `span '${span.spanId}' attribute '${key}'`,\n value: parseTaskScoreAttribute(runId, span.spanId, key, span.attributes[key]),\n })\n }\n }\n\n if (sources.length === 0) return undefined\n sources.sort((left, right) => left.label.localeCompare(right.label))\n const score = sources[0]!.value\n if (sources.some((source) => source.value !== score)) {\n const details = sources.map((source) => `${source.label}=${source.value}`).join(', ')\n throw new ValidationError(\n `fromOtelSpans: conflicting task-quality scores for run '${runId}': ${details}`,\n )\n }\n return score\n}\n\nfunction parseTaskScoreAttribute(\n runId: string,\n spanId: string,\n key: string,\n value: unknown,\n): number {\n const source = `span '${spanId}' attribute '${key}'`\n if (typeof value === 'string') {\n if (value.trim().length === 0) {\n throw new ValidationError(\n `fromOtelSpans: ${source} is blank for run '${runId}'; task quality must be finite`,\n )\n }\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n return value\n }\n throw new ValidationError(\n `fromOtelSpans: ${source} is not a finite task-quality score for run '${runId}'`,\n )\n}\n\nfunction orderSpans(spans: readonly TraceSpanEvent[]): TraceSpanEvent[] {\n return [...spans].sort(\n (left, right) =>\n compareUnixNano(left.startTimeUnixNano, right.startTimeUnixNano) ||\n left.spanId.localeCompare(right.spanId),\n )\n}\n\nfunction parseUnixNano(value: string): bigint {\n try {\n return BigInt(value)\n } catch {\n throw new ValidationError(`fromOtelSpans: invalid Unix nanosecond timestamp '${value}'`)\n }\n}\n\nfunction compareUnixNano(left: string, right: string): number {\n const leftValue = parseUnixNano(left)\n const rightValue = parseUnixNano(right)\n return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0\n}\n\nfunction unixNanoDurationMs(start: string, end: string): number {\n const delta = parseUnixNano(end) - parseUnixNano(start)\n if (delta <= 0n) return 0\n const wholeMs = delta / 1_000_000n\n const fractionalMs = delta % 1_000_000n\n const value = Number(wholeMs) + Number(fractionalMs) / 1_000_000\n if (!Number.isSafeInteger(Number(wholeMs))) {\n throw new ValidationError('fromOtelSpans: span duration exceeds the safe millisecond range')\n }\n return value\n}\n\nfunction collectNumericAttrs(spans: TraceSpanEvent[]): Record<string, number> {\n const raw: Record<string, number> = {}\n for (const span of spans) {\n for (const [k, v] of Object.entries(span.attributes)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[k] = v\n }\n }\n return raw\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { INPUT_VALUE, OUTPUT_VALUE, TOOL_ARGS_CAPTURED, TOOL_LATENCY_MS, TOOL_NAME } from "./trace-attributes.js";
2
- //#region src/trace/otlp-attributes.ts
2
+ // src/trace/otlp-attributes.ts
3
3
  const TOOL_SPAN_ATTRIBUTE_KEYS = [
4
4
  TOOL_NAME,
5
5
  TOOL_ARGS_CAPTURED,
@@ -47,7 +47,6 @@ function stringifyTraceValue(value) {
47
47
  return String(value);
48
48
  }
49
49
  }
50
- //#endregion
51
50
  export { traceSpanKindToOpenInferenceKind as n, applyToolSpanOtlpAttributes as t };
52
51
 
53
- //# sourceMappingURL=otlp-attributes-D9ptWaIJ.js.map
52
+ //# sourceMappingURL=otlp-attributes-Boeb7gtH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"otlp-attributes-D9ptWaIJ.js","names":[],"sources":["../src/trace/otlp-attributes.ts"],"sourcesContent":["/** Canonical OpenInference-over-OTLP attribute vocabulary used at the trace boundary. */\n\nimport type { SpanKind } from '@tangle-network/agent-trace-contract'\nimport {\n INPUT_VALUE,\n OUTPUT_VALUE,\n TOOL_ARGS_CAPTURED,\n TOOL_LATENCY_MS,\n TOOL_NAME,\n} from './attribute-vocabulary'\nimport type { ToolSpan } from './schema'\n\nexport * from './attribute-vocabulary'\n\nconst TOOL_SPAN_ATTRIBUTE_KEYS = [\n TOOL_NAME,\n TOOL_ARGS_CAPTURED,\n TOOL_LATENCY_MS,\n INPUT_VALUE,\n OUTPUT_VALUE,\n] as const\n\nexport type ToolSpanOtlpInput = Pick<\n ToolSpan,\n 'toolName' | 'args' | 'argsCaptured' | 'result' | 'latencyMs'\n>\n\nfunction toolSpanOtlpAttributes(\n span: ToolSpanOtlpInput,\n): Record<string, string | number | boolean> {\n const argsCaptured = span.argsCaptured !== false\n const attributes: Record<string, string | number | boolean> = {\n [TOOL_NAME]: span.toolName,\n [TOOL_ARGS_CAPTURED]: argsCaptured,\n }\n if (span.latencyMs !== undefined) attributes[TOOL_LATENCY_MS] = span.latencyMs\n if (argsCaptured) attributes[INPUT_VALUE] = stringifyTraceValue(span.args)\n if (span.result !== undefined) attributes[OUTPUT_VALUE] = stringifyTraceValue(span.result)\n return attributes\n}\n\nexport function applyToolSpanOtlpAttributes(\n attributes: Record<string, unknown>,\n span: ToolSpanOtlpInput,\n): void {\n for (const key of TOOL_SPAN_ATTRIBUTE_KEYS) delete attributes[key]\n Object.assign(attributes, toolSpanOtlpAttributes(span))\n}\n\n/**\n * The contract kind this package writes for one of its own span kinds. A kind\n * with no contract equivalent is written as `UNKNOWN`, which the contract\n * accepts, rather than a word no reader knows.\n */\nexport function traceSpanKindToOpenInferenceKind(kind: string): SpanKind {\n switch (kind) {\n case 'llm':\n return 'LLM'\n case 'tool':\n return 'TOOL'\n case 'retrieval':\n return 'RETRIEVER'\n case 'judge':\n return 'EVALUATOR'\n case 'sandbox':\n return 'CHAIN'\n case 'agent':\n return 'AGENT'\n default:\n return 'UNKNOWN'\n }\n}\n\nfunction stringifyTraceValue(value: unknown): string {\n if (value === undefined) return 'null'\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n"],"mappings":";;AAcA,MAAM,2BAA2B;CAC/B;CACA;CACA;CACA;CACA;AACF;AAOA,SAAS,uBACP,MAC2C;CAC3C,MAAM,eAAe,KAAK,iBAAiB;CAC3C,MAAM,aAAwD;GAC3D,YAAY,KAAK;GACjB,qBAAqB;CACxB;CACA,IAAI,KAAK,cAAc,KAAA,GAAW,WAAW,mBAAmB,KAAK;CACrE,IAAI,cAAc,WAAW,eAAe,oBAAoB,KAAK,IAAI;CACzE,IAAI,KAAK,WAAW,KAAA,GAAW,WAAW,gBAAgB,oBAAoB,KAAK,MAAM;CACzF,OAAO;AACT;AAEA,SAAgB,4BACd,YACA,MACM;CACN,KAAK,MAAM,OAAO,0BAA0B,OAAO,WAAW;CAC9D,OAAO,OAAO,YAAY,uBAAuB,IAAI,CAAC;AACxD;;;;;;AAOA,SAAgB,iCAAiC,MAAwB;CACvE,QAAQ,MAAR;EACE,KAAK,OACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,oBAAoB,OAAwB;CACnD,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI;EACF,OAAO,KAAK,UAAU,KAAK,KAAK,OAAO,KAAK;CAC9C,QAAQ;EACN,OAAO,OAAO,KAAK;CACrB;AACF"}
1
+ {"version":3,"file":"otlp-attributes-Boeb7gtH.js","names":[],"sources":["../src/trace/otlp-attributes.ts"],"sourcesContent":["/** Canonical OpenInference-over-OTLP attribute vocabulary used at the trace boundary. */\n\nimport type { SpanKind } from '@tangle-network/agent-trace-contract'\nimport {\n INPUT_VALUE,\n OUTPUT_VALUE,\n TOOL_ARGS_CAPTURED,\n TOOL_LATENCY_MS,\n TOOL_NAME,\n} from './attribute-vocabulary'\nimport type { ToolSpan } from './schema'\n\nexport * from './attribute-vocabulary'\n\nconst TOOL_SPAN_ATTRIBUTE_KEYS = [\n TOOL_NAME,\n TOOL_ARGS_CAPTURED,\n TOOL_LATENCY_MS,\n INPUT_VALUE,\n OUTPUT_VALUE,\n] as const\n\nexport type ToolSpanOtlpInput = Pick<\n ToolSpan,\n 'toolName' | 'args' | 'argsCaptured' | 'result' | 'latencyMs'\n>\n\nfunction toolSpanOtlpAttributes(\n span: ToolSpanOtlpInput,\n): Record<string, string | number | boolean> {\n const argsCaptured = span.argsCaptured !== false\n const attributes: Record<string, string | number | boolean> = {\n [TOOL_NAME]: span.toolName,\n [TOOL_ARGS_CAPTURED]: argsCaptured,\n }\n if (span.latencyMs !== undefined) attributes[TOOL_LATENCY_MS] = span.latencyMs\n if (argsCaptured) attributes[INPUT_VALUE] = stringifyTraceValue(span.args)\n if (span.result !== undefined) attributes[OUTPUT_VALUE] = stringifyTraceValue(span.result)\n return attributes\n}\n\nexport function applyToolSpanOtlpAttributes(\n attributes: Record<string, unknown>,\n span: ToolSpanOtlpInput,\n): void {\n for (const key of TOOL_SPAN_ATTRIBUTE_KEYS) delete attributes[key]\n Object.assign(attributes, toolSpanOtlpAttributes(span))\n}\n\n/**\n * The contract kind this package writes for one of its own span kinds. A kind\n * with no contract equivalent is written as `UNKNOWN`, which the contract\n * accepts, rather than a word no reader knows.\n */\nexport function traceSpanKindToOpenInferenceKind(kind: string): SpanKind {\n switch (kind) {\n case 'llm':\n return 'LLM'\n case 'tool':\n return 'TOOL'\n case 'retrieval':\n return 'RETRIEVER'\n case 'judge':\n return 'EVALUATOR'\n case 'sandbox':\n return 'CHAIN'\n case 'agent':\n return 'AGENT'\n default:\n return 'UNKNOWN'\n }\n}\n\nfunction stringifyTraceValue(value: unknown): string {\n if (value === undefined) return 'null'\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n"],"mappings":";;AAcA,MAAM,2BAA2B;CAC/B;CACA;CACA;CACA;CACA;AACF;AAOA,SAAS,uBACP,MAC2C;CAC3C,MAAM,eAAe,KAAK,iBAAiB;CAC3C,MAAM,aAAwD;GAC3D,YAAY,KAAK;GACjB,qBAAqB;CACxB;CACA,IAAI,KAAK,cAAc,KAAA,GAAW,WAAW,mBAAmB,KAAK;CACrE,IAAI,cAAc,WAAW,eAAe,oBAAoB,KAAK,IAAI;CACzE,IAAI,KAAK,WAAW,KAAA,GAAW,WAAW,gBAAgB,oBAAoB,KAAK,MAAM;CACzF,OAAO;AACT;AAEA,SAAgB,4BACd,YACA,MACM;CACN,KAAK,MAAM,OAAO,0BAA0B,OAAO,WAAW;CAC9D,OAAO,OAAO,YAAY,uBAAuB,IAAI,CAAC;AACxD;;;;;;AAOA,SAAgB,iCAAiC,MAAwB;CACvE,QAAQ,MAAR;EACE,KAAK,OACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,oBAAoB,OAAwB;CACnD,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI;EACF,OAAO,KAAK,UAAU,KAAK,KAAK,OAAO,KAAK;CAC9C,QAAQ;EACN,OAAO,OAAO,KAAK;CACrB;AACF"}
@@ -1,6 +1,6 @@
1
- import { i as makeRng } from "./internal-BTK91Bqt.js";
2
- import { a as spearmanR, r as pearsonR } from "./descriptive-CVNy48rR.js";
3
- //#region src/meta-eval/outcome-observations.ts
1
+ import { i as makeRng } from "./internal-v6XfOeJW.js";
2
+ import { a as spearmanR, r as pearsonR } from "./descriptive-cPwITVfy.js";
3
+ // src/meta-eval/outcome-observations.ts
4
4
  /** Reduce observations of one named metric; unrelated keys cannot supply a value. */
5
5
  function reduceOutcomeMetric(outcomes, metric, reduction) {
6
6
  const observations = outcomes.flatMap((outcome) => {
@@ -72,7 +72,6 @@ function interval(values) {
72
72
  upper: Math.min(1, values[Math.min(values.length - 1, Math.floor(.975 * values.length))])
73
73
  };
74
74
  }
75
- //#endregion
76
75
  export { validateObservationOptions as a, reduceOutcomeMetric as i, correlationSummary as n, validateOutcomeMetricSpecifications as o, hasVariation as r, assertUniqueObservationIds as t };
77
76
 
78
- //# sourceMappingURL=outcome-observations-FLmRpgYa.js.map
77
+ //# sourceMappingURL=outcome-observations-D4snOtUb.js.map