@tangle-network/agent-eval 1.0.22 → 1.0.24
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.
- package/CHANGELOG.md +78 -0
- package/dist/adapters/http.d.ts +2 -2
- package/dist/{agent-profile-DU5InUT9.d.ts → agent-profile-DC_v4p1f.d.ts} +3 -3
- package/dist/{agent-profile-DU5InUT9.d.ts.map → agent-profile-DC_v4p1f.d.ts.map} +1 -1
- package/dist/analyst/index.d.ts +14 -14
- package/dist/analyst/index.js +9 -9
- package/dist/{analyze-runs-jLTRKuoK.js → analyze-runs-BCSHzqna.js} +2 -2
- package/dist/{analyze-runs-jLTRKuoK.js.map → analyze-runs-BCSHzqna.js.map} +1 -1
- package/dist/{analyze-runs-DYYe18Gw.d.ts → analyze-runs-DGr7mpC3.d.ts} +5 -5
- package/dist/{analyze-runs-DYYe18Gw.d.ts.map → analyze-runs-DGr7mpC3.d.ts.map} +1 -1
- package/dist/app-grade/index.d.ts +4 -4
- package/dist/app-grade/index.js +3 -3
- package/dist/{benchmark-command-DkUpd9Q6.js → benchmark-command-DRAHkn4D.js} +8 -9
- package/dist/{benchmark-command-DkUpd9Q6.js.map → benchmark-command-DRAHkn4D.js.map} +1 -1
- package/dist/benchmarks/index.d.ts +5 -5
- package/dist/benchmarks/index.js +3 -3
- package/dist/campaign/index.d.ts +7 -7
- package/dist/campaign/index.js +8 -8
- package/dist/{campaign-C2mmydmx.js → campaign-C9QC27C2.js} +12 -12
- package/dist/{campaign-C2mmydmx.js.map → campaign-C9QC27C2.js.map} +1 -1
- package/dist/{campaign-evidence-NtH29ctt.js → campaign-evidence-CVNKiK0q.js} +2 -2
- package/dist/{campaign-evidence-NtH29ctt.js.map → campaign-evidence-CVNKiK0q.js.map} +1 -1
- package/dist/{chat-client-Zz97O3NB.js → chat-client-9XLgWrQ7.js} +5 -3
- package/dist/chat-client-9XLgWrQ7.js.map +1 -0
- package/dist/{chat-json-call-Dgi7-RH-.js → chat-json-call-CaNO3k0A.js} +2 -2
- package/dist/{chat-json-call-Dgi7-RH-.js.map → chat-json-call-CaNO3k0A.js.map} +1 -1
- package/dist/cli.js +8 -8
- package/dist/{cluster-Cd0MRbr9.d.ts → cluster-CkzP4h3T.d.ts} +4 -2
- package/dist/{cluster-Cd0MRbr9.d.ts.map → cluster-CkzP4h3T.d.ts.map} +1 -1
- package/dist/{completion-verifier-DFyYFezn.js → completion-verifier-BYLOcQt7.js} +5 -4
- package/dist/completion-verifier-BYLOcQt7.js.map +1 -0
- package/dist/{completion-verifier-BEpsr3N4.d.ts → completion-verifier-CJVDPv2T.d.ts} +3 -2
- package/dist/{completion-verifier-BEpsr3N4.d.ts.map → completion-verifier-CJVDPv2T.d.ts.map} +1 -1
- package/dist/contract/index.d.ts +11 -11
- package/dist/contract/index.js +11 -13
- package/dist/contract/index.js.map +1 -1
- package/dist/{cost-ledger-DfhStGcZ.js → cost-ledger-1CwUnVOd.js} +145 -3
- package/dist/cost-ledger-1CwUnVOd.js.map +1 -0
- package/dist/{decision-point-Di2LATNH.js → decision-point-CQOczIIH.js} +2 -2
- package/dist/{decision-point-Di2LATNH.js.map → decision-point-CQOczIIH.js.map} +1 -1
- package/dist/{default-registry-aPvwtzEM.d.ts → default-registry-C_Akmpui.d.ts} +7 -7
- package/dist/{default-registry-aPvwtzEM.d.ts.map → default-registry-C_Akmpui.d.ts.map} +1 -1
- package/dist/{default-registry-CdFbxPnr.js → default-registry-D-xd7KxV.js} +5 -5
- package/dist/{default-registry-CdFbxPnr.js.map → default-registry-D-xd7KxV.js.map} +1 -1
- package/dist/{define-agent-eval-BROmIwn1.js → define-agent-eval-BLVewqJm.js} +8 -8
- package/dist/{define-agent-eval-BROmIwn1.js.map → define-agent-eval-BLVewqJm.js.map} +1 -1
- package/dist/{define-agent-eval-DGWBgCid.d.ts → define-agent-eval-nNPC7cD5.d.ts} +7 -7
- package/dist/{define-agent-eval-DGWBgCid.d.ts.map → define-agent-eval-nNPC7cD5.d.ts.map} +1 -1
- package/dist/diagnosis/index.d.ts +2 -2
- package/dist/diagnosis/index.js +1 -1
- package/dist/{dspy-rlm-engine-cWyn8G1a.js → dspy-rlm-engine-BS_jxE0P.js} +4 -4
- package/dist/{dspy-rlm-engine-cWyn8G1a.js.map → dspy-rlm-engine-BS_jxE0P.js.map} +1 -1
- package/dist/{engine-BF8naBn7.d.ts → engine-B0gr15-l.d.ts} +2 -2
- package/dist/{engine-BF8naBn7.d.ts.map → engine-B0gr15-l.d.ts.map} +1 -1
- package/dist/{eval-campaign-Dq8DEKmy.js → eval-campaign-DpkToY_w.js} +2 -2
- package/dist/eval-campaign-DpkToY_w.js.map +1 -0
- package/dist/{evaluation-bU_bhlv-.js → evaluation-C_GJvEEG.js} +2 -2
- package/dist/{evaluation-bU_bhlv-.js.map → evaluation-C_GJvEEG.js.map} +1 -1
- package/dist/{evaluation-CFKj_IlJ.d.ts → evaluation-mk3u_ZJC.d.ts} +4 -4
- package/dist/{evaluation-CFKj_IlJ.d.ts.map → evaluation-mk3u_ZJC.d.ts.map} +1 -1
- package/dist/evaluation.d.ts +1 -1
- package/dist/evaluation.js +1 -1
- package/dist/{exact-types-VAFjtOQN.d.ts → exact-types-Blq7YvsK.d.ts} +2 -2
- package/dist/{exact-types-VAFjtOQN.d.ts.map → exact-types-Blq7YvsK.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +3 -3
- package/dist/experiment/index.js +2 -2
- package/dist/{external-optimizer-process-2ImGH_LR.js → external-optimizer-process-m9xln7zN.js} +2 -2
- package/dist/{external-optimizer-process-2ImGH_LR.js.map → external-optimizer-process-m9xln7zN.js.map} +1 -1
- package/dist/{external-optimizer-subprocess-_C_2yriN.js → external-optimizer-subprocess-GO6s84Ov.js} +3 -3
- package/dist/{external-optimizer-subprocess-_C_2yriN.js.map → external-optimizer-subprocess-GO6s84Ov.js.map} +1 -1
- package/dist/{feedback-trajectory-DTj8eVTR.d.ts → feedback-trajectory-D3oISeGl.d.ts} +3 -3
- package/dist/{feedback-trajectory-DTj8eVTR.d.ts.map → feedback-trajectory-D3oISeGl.d.ts.map} +1 -1
- package/dist/{findings-store-BSuaV3dN.js → findings-store-CTy71Lnr.js} +5 -5
- package/dist/{findings-store-BSuaV3dN.js.map → findings-store-CTy71Lnr.js.map} +1 -1
- package/dist/fuzz.js +1 -1
- package/dist/hosted/index.js +1 -1
- package/dist/{index-DNXFzSpc.d.ts → index-BN6htPVi.d.ts} +2 -2
- package/dist/{index-DNXFzSpc.d.ts.map → index-BN6htPVi.d.ts.map} +1 -1
- package/dist/{index-BlTbxHlY.d.ts → index-BdFlQP54.d.ts} +4 -4
- package/dist/{index-BlTbxHlY.d.ts.map → index-BdFlQP54.d.ts.map} +1 -1
- package/dist/{index-QLDWZTxI.d.ts → index-CxuK3sxA.d.ts} +9 -9
- package/dist/{index-QLDWZTxI.d.ts.map → index-CxuK3sxA.d.ts.map} +1 -1
- package/dist/{index-YS58LHlx.d.ts → index-Dodw93oW.d.ts} +25 -181
- package/dist/index-Dodw93oW.d.ts.map +1 -0
- package/dist/{index-DX87wzX3.d.ts → index-IE8O0HNr.d.ts} +9 -9
- package/dist/{index-DX87wzX3.d.ts.map → index-IE8O0HNr.d.ts.map} +1 -1
- package/dist/{index-B62BaRzH.d.ts → index-KAYaJtMA.d.ts} +4 -4
- package/dist/{index-B62BaRzH.d.ts.map → index-KAYaJtMA.d.ts.map} +1 -1
- package/dist/{index-Bp3w4fWc.d.ts → index-cp5gkylN.d.ts} +12 -12
- package/dist/{index-Bp3w4fWc.d.ts.map → index-cp5gkylN.d.ts.map} +1 -1
- package/dist/index.d.ts +30 -30
- package/dist/index.js +72 -30
- package/dist/index.js.map +1 -1
- package/dist/{integrity-CrmnGB2T.d.ts → integrity-zeWMeTQt.d.ts} +2 -2
- package/dist/{integrity-CrmnGB2T.d.ts.map → integrity-zeWMeTQt.d.ts.map} +1 -1
- package/dist/{judge-gate-CrN0PaAL.js → judge-gate-DsoI5tx7.js} +2 -2
- package/dist/{judge-gate-CrN0PaAL.js.map → judge-gate-DsoI5tx7.js.map} +1 -1
- package/dist/{kind-factory-CV0FNCMM.js → kind-factory-CJXaE1oF.js} +2 -2
- package/dist/{kind-factory-CV0FNCMM.js.map → kind-factory-CJXaE1oF.js.map} +1 -1
- package/dist/{llm-client-DMMSg-Ro.js → llm-client-Bj-TooRS.js} +11 -11
- package/dist/{llm-client-DMMSg-Ro.js.map → llm-client-Bj-TooRS.js.map} +1 -1
- package/dist/{llm-judge-C813vmpc.js → llm-judge-DzAT7Wka.js} +11 -11
- package/dist/{llm-judge-C813vmpc.js.map → llm-judge-DzAT7Wka.js.map} +1 -1
- package/dist/{matrix-C-GxIgeJ.d.ts → matrix-Diw3yJCG.d.ts} +3 -4
- package/dist/matrix-Diw3yJCG.d.ts.map +1 -0
- package/dist/meta-eval/index.d.ts +3 -3
- package/dist/meta-eval/index.js +2 -2
- package/dist/{mint-yF51iBgY.js → mint-Ck92efNo.js} +2 -2
- package/dist/{mint-yF51iBgY.js.map → mint-Ck92efNo.js.map} +1 -1
- package/dist/multishot/golden/index.d.ts +1 -1
- package/dist/multishot/index.d.ts +3 -2
- package/dist/multishot/index.d.ts.map +1 -1
- package/dist/multishot/index.js +3 -3
- package/dist/multishot/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/{paired-promotion-decision-DJU3fZxH.d.ts → paired-promotion-decision-COeOgNHG.d.ts} +2 -2
- package/dist/{paired-promotion-decision-DJU3fZxH.d.ts.map → paired-promotion-decision-COeOgNHG.d.ts.map} +1 -1
- package/dist/paired-promotion-power-D03cUj9E.js +289 -0
- package/dist/paired-promotion-power-D03cUj9E.js.map +1 -0
- package/dist/{pareto-fJZg8pXm.js → pareto-UzjB3ZBk.js} +5 -288
- package/dist/pareto-UzjB3ZBk.js.map +1 -0
- package/dist/{prime-protocol-D1NkJRuD.d.ts → prime-protocol-bRbh6dqd.d.ts} +2 -2
- package/dist/{prime-protocol-D1NkJRuD.d.ts.map → prime-protocol-bRbh6dqd.d.ts.map} +1 -1
- package/dist/{promotion-gate-Da0xV4sa.d.ts → promotion-gate-XglbDCNo.d.ts} +3 -3
- package/dist/{promotion-gate-Da0xV4sa.d.ts.map → promotion-gate-XglbDCNo.d.ts.map} +1 -1
- package/dist/{proposal-findings-DWs94yT8.js → proposal-findings-CS6LoGGp.js} +2 -2
- package/dist/{proposal-findings-DWs94yT8.js.map → proposal-findings-CS6LoGGp.js.map} +1 -1
- package/dist/{registry-BAcEbzKm.d.ts → registry-Pfeqsr5k.d.ts} +4 -4
- package/dist/{registry-BAcEbzKm.d.ts.map → registry-Pfeqsr5k.d.ts.map} +1 -1
- package/dist/{release-confidence-DGtuPDxJ.js → release-confidence-B4Xxdpmn.js} +2 -2
- package/dist/{release-confidence-DGtuPDxJ.js.map → release-confidence-B4Xxdpmn.js.map} +1 -1
- package/dist/reporting.d.ts +5 -5
- package/dist/reporting.js +2 -2
- package/dist/{researcher-CSlc84Bp.d.ts → researcher-DlyjP5uq.d.ts} +6 -6
- package/dist/{researcher-CSlc84Bp.d.ts.map → researcher-DlyjP5uq.d.ts.map} +1 -1
- package/dist/{reward-ST4PXNXF.d.ts → reward-ap_R9mCH.d.ts} +2 -2
- package/dist/{reward-ST4PXNXF.d.ts.map → reward-ap_R9mCH.d.ts.map} +1 -1
- package/dist/{reward-hacking-C9hPVT0Q.d.ts → reward-hacking-CIdVwVe4.d.ts} +2 -2
- package/dist/{reward-hacking-C9hPVT0Q.d.ts.map → reward-hacking-CIdVwVe4.d.ts.map} +1 -1
- package/dist/rl.d.ts +11 -11
- package/dist/rl.js +5 -5
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +3 -3
- package/dist/rollout/index.js +2 -2
- package/dist/{rollout-DKa54qer.js → rollout-Dh5q6CPA.js} +3 -3
- package/dist/{rollout-DKa54qer.js.map → rollout-Dh5q6CPA.js.map} +1 -1
- package/dist/{rubric-predictive-validity-B3RzbwOx.d.ts → rubric-predictive-validity-Bbi88Aut.d.ts} +2 -2
- package/dist/{rubric-predictive-validity-B3RzbwOx.d.ts.map → rubric-predictive-validity-Bbi88Aut.d.ts.map} +1 -1
- package/dist/{run-record-CFbnkE1K.js → run-record-DTTx9Ktr.js} +2 -2
- package/dist/{run-record-CFbnkE1K.js.map → run-record-DTTx9Ktr.js.map} +1 -1
- package/dist/{run-record-CpLS4Uid.js → run-record-DmX_ESC5.js} +7 -5
- package/dist/run-record-DmX_ESC5.js.map +1 -0
- package/dist/{run-record-D2BFMPGl.d.ts → run-record-pBlhZizT.d.ts} +8 -8
- package/dist/{run-record-D2BFMPGl.d.ts.map → run-record-pBlhZizT.d.ts.map} +1 -1
- package/dist/search/index.d.ts +2 -2
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +2 -2
- package/dist/{search-kernel-CQGLbmgn.d.ts → search-kernel-6P1dRpJ4.d.ts} +4 -4
- package/dist/{search-kernel-CQGLbmgn.d.ts.map → search-kernel-6P1dRpJ4.d.ts.map} +1 -1
- package/dist/{search-ledger-Dk-yk5Li.js → search-ledger-9liYyZf5.js} +2 -2
- package/dist/{search-ledger-Dk-yk5Li.js.map → search-ledger-9liYyZf5.js.map} +1 -1
- package/dist/{search-shipper-Dm-_Dtvy.js → search-shipper-B6tMNx1I.js} +2 -2
- package/dist/{search-shipper-Dm-_Dtvy.js.map → search-shipper-B6tMNx1I.js.map} +1 -1
- package/dist/{search-summary-sPWiYtSl.js → search-summary-CISbbxyr.js} +2 -2
- package/dist/{search-summary-sPWiYtSl.js.map → search-summary-CISbbxyr.js.map} +1 -1
- package/dist/{sequential-CAksw6EU.js → sequential-Ko7T-zvu.js} +65 -28
- package/dist/sequential-Ko7T-zvu.js.map +1 -0
- package/dist/sequential-OeSwJ2uG.d.ts +246 -0
- package/dist/sequential-OeSwJ2uG.d.ts.map +1 -0
- package/dist/{server-DFVwfoZq.js → server-BorE0Y3O.js} +16 -5
- package/dist/server-BorE0Y3O.js.map +1 -0
- package/dist/{skillopt-optimization-method-QO1nU8Kz.js → skillopt-optimization-method-BtX7xXDd.js} +7 -7
- package/dist/{skillopt-optimization-method-QO1nU8Kz.js.map → skillopt-optimization-method-BtX7xXDd.js.map} +1 -1
- package/dist/{statistical-heldout-CvOwNqt9.d.ts → statistical-heldout-vjrs8iyO.d.ts} +6 -6
- package/dist/{statistical-heldout-CvOwNqt9.d.ts.map → statistical-heldout-vjrs8iyO.d.ts.map} +1 -1
- package/dist/statistics.d.ts +2 -2
- package/dist/{store-otlp-C-jyj3WX.js → store-otlp-CmgKDr0O.js} +2 -2
- package/dist/{store-otlp-C-jyj3WX.js.map → store-otlp-CmgKDr0O.js.map} +1 -1
- package/dist/{store-tool-spans-B3z_Qb5u.d.ts → store-tool-spans-BemsQEhd.d.ts} +6 -6
- package/dist/{store-tool-spans-B3z_Qb5u.d.ts.map → store-tool-spans-BemsQEhd.d.ts.map} +1 -1
- package/dist/{store-tool-spans-DalWlKY8.js → store-tool-spans-CW24axM0.js} +3 -3
- package/dist/{store-tool-spans-DalWlKY8.js.map → store-tool-spans-CW24axM0.js.map} +1 -1
- package/dist/{summary-report-DyZquTaH.d.ts → summary-report-vdhE20Zf.d.ts} +4 -4
- package/dist/{summary-report-DyZquTaH.d.ts.map → summary-report-vdhE20Zf.d.ts.map} +1 -1
- package/dist/supervisor-run/index.d.ts +1 -1
- package/dist/{systemone-DVk-Crtu.d.ts → systemone-DFUN9DL1.d.ts} +7 -7
- package/dist/{systemone-DVk-Crtu.d.ts.map → systemone-DFUN9DL1.d.ts.map} +1 -1
- package/dist/{systemone-review-CToBl1oa.d.ts → systemone-review-4CKmHvr5.d.ts} +2 -2
- package/dist/{systemone-review-CToBl1oa.d.ts.map → systemone-review-4CKmHvr5.d.ts.map} +1 -1
- package/dist/systemone.d.ts +3 -3
- package/dist/systemone.js +2 -2
- package/dist/{tool-groups-R5RO9OHn.d.ts → tool-groups-Dpl3picW.d.ts} +3 -3
- package/dist/tool-groups-Dpl3picW.d.ts.map +1 -0
- package/dist/{trace-questions-BY6taxnl.d.ts → trace-questions-oT2fZWJ8.d.ts} +3 -3
- package/dist/{trace-questions-BY6taxnl.d.ts.map → trace-questions-oT2fZWJ8.d.ts.map} +1 -1
- package/dist/trace-repair/index.d.ts +2 -2
- package/dist/traces.d.ts +6 -6
- package/dist/traces.js +5 -11
- package/dist/traces.js.map +1 -1
- package/dist/{tree-C-N2kP-8.js → tree-D2cNtu9m.js} +10 -10
- package/dist/tree-D2cNtu9m.js.map +1 -0
- package/dist/{types-kBMNdo1X.d.ts → types-6GuPL-Vt.d.ts} +3 -3
- package/dist/{types-kBMNdo1X.d.ts.map → types-6GuPL-Vt.d.ts.map} +1 -1
- package/dist/{types-ip2D3-Ib.d.ts → types-C9yEqDjQ.d.ts} +6 -6
- package/dist/{types-ip2D3-Ib.d.ts.map → types-C9yEqDjQ.d.ts.map} +1 -1
- package/dist/{types-BsdcSWnf.d.ts → types-CP3rkpir.d.ts} +3 -3
- package/dist/{types-BsdcSWnf.d.ts.map → types-CP3rkpir.d.ts.map} +1 -1
- package/dist/{types-DUVhW5V1.d.ts → types-CwHU7U9J.d.ts} +2 -2
- package/dist/{types-DUVhW5V1.d.ts.map → types-CwHU7U9J.d.ts.map} +1 -1
- package/dist/wire/index.d.ts +4 -4
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +1 -1
- package/docs/adopt-stack.md +9 -0
- package/docs/eval-fixtures.md +2 -2
- package/docs/search-ledger.md +1 -0
- package/docs/wire-protocol.md +1 -1
- package/package.json +1 -1
- package/dist/chat-client-Zz97O3NB.js.map +0 -1
- package/dist/completion-verifier-DFyYFezn.js.map +0 -1
- package/dist/cost-ledger-DfhStGcZ.js.map +0 -1
- package/dist/eval-campaign-Dq8DEKmy.js.map +0 -1
- package/dist/index-YS58LHlx.d.ts.map +0 -1
- package/dist/matrix-C-GxIgeJ.d.ts.map +0 -1
- package/dist/metrics-zALlR17s.js +0 -146
- package/dist/metrics-zALlR17s.js.map +0 -1
- package/dist/pareto-fJZg8pXm.js.map +0 -1
- package/dist/run-record-CpLS4Uid.js.map +0 -1
- package/dist/sequential-B9p6uoV8.d.ts +0 -168
- package/dist/sequential-B9p6uoV8.d.ts.map +0 -1
- package/dist/sequential-CAksw6EU.js.map +0 -1
- package/dist/server-DFVwfoZq.js.map +0 -1
- package/dist/tool-groups-R5RO9OHn.d.ts.map +0 -1
- package/dist/tree-C-N2kP-8.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run-record-CpLS4Uid.js","names":[],"sources":["../src/run-record.ts"],"sourcesContent":["/**\n * Paper-grade RunRecord schema + runtime validator.\n *\n * Every run that participates in a promotion gate, paper table, or\n * researcher loop SHOULD be recorded as a `RunRecord`. The mandatory\n * fields are exactly those the paper \"Two Loops, Three Roles\" requires\n * for reproducibility: who/what/when/cost/seed/hash, plus the search vs\n * holdout split tag. A task score is optional because execution-only records\n * must preserve missing labels instead of converting errors into zero quality.\n *\n * This is intentionally NOT a replacement for the rich `Run` /\n * `ProposeReviewReport` / `ScenarioResult` types already in the\n * package. Those are runtime structures with full provenance. A\n * `RunRecord` is the analysis-time projection — the JSON-friendly\n * row you'd put in a parquet file or paste into a notebook.\n *\n * Validate at the boundary:\n *\n * const rec = validateRunRecord(rawJson) // throws on missing\n * const ok = isRunRecord(rawJson) // boolean check\n * const rec = parseRunRecordSafe(rawJson) // { ok, value | error }\n *\n * The validator runs in pure TS — zod is intentionally NOT a\n * dependency.\n */\n\nimport type { AgentProfileCell } from './agent-profile-cell'\nimport { validateAgentProfileCell } from './agent-profile-cell'\nimport type { CostProvenance } from './cost-ledger'\nimport { ValidationError } from './errors'\n// Value import of a leaf module that itself imports only this file's TYPES —\n// no runtime cycle. It keeps the raw split-score derivation spelled in exactly\n// one place (see `rollout/score-derivation-guard`).\nimport { observedScore } from './rollout/reward'\nimport { FAILURE_CLASSES, type FailureClass } from './trace/schema'\n\n/** Search/dev/holdout split tag. 'search' is the paper-grade alias for the\n * combined train+test pool that the optimizer is allowed to read. */\nexport type RunSplitTag = 'search' | 'dev' | 'holdout'\n\n/**\n * Explicit execution-lifecycle result for a run.\n *\n * This is separate from task quality (`outcome`) and failure classification.\n * Producers set it only from root-run or process evidence.\n */\nexport type RunTerminalOutcome = 'succeeded' | 'failed' | 'cancelled' | 'incomplete' | 'unknown'\n\n/** Explicit model value for a row that never produced a served model snapshot. */\nexport const UNKNOWN_MODEL = 'unknown'\n\nexport interface RunTokenUsage {\n input: number\n /** All generated tokens charged as output, including reasoning tokens. */\n output: number\n /** Present only when one or more paid calls did not report token usage.\n * In that case, every numeric field is a known subtotal, not a measured total. */\n tokensKnown?: false\n /** Reasoning-token subset of `output`, when the provider reports it. */\n reasoning?: number\n /** Prompt tokens served from a provider cache. */\n cached?: number\n /** Prompt tokens written into a provider cache. */\n cacheWrite?: number\n}\n\n/**\n * How a run's USD amount was obtained.\n *\n * `costUsd` is the run's total, or null when the total is unknown. A run whose\n * receipts prove only part of its spend is a `lower-bound`: its total is\n * unknown, so `costUsd` and `usd` stay null, and the proven part is\n * `knownLowerBoundUsd`. A reader of the total therefore never takes a floor\n * for a total. A floor of $0 proves nothing, so it is written `uncaptured`.\n *\n * Only a RunRecord needs this kind. Every other cost shape keeps a known\n * subtotal beside `CostProvenance`, where `uncaptured` already means \"at\n * least the subtotal\"; a RunRecord's nullable `costUsd` cannot hold one.\n */\nexport type RunCostProvenance =\n | CostProvenance\n | { kind: 'lower-bound'; usd: null; knownLowerBoundUsd: number }\n\n/**\n * The run's place in a search: one attempt at one cell. The search ledger\n * holds the lineage (the node's parents, depth and order); a RunRecord only\n * points at it.\n */\nexport interface RunSearchCoordinates {\n searchId: string\n nodeId: string\n /** The cell id hashes the search, node, task, split and repeat, so it is\n * unique across candidates. */\n cellId: string\n /** Attempt number within the cell, counted from 1. */\n attempt: number\n}\n\n/** Where the run's execution record lives. */\nexport interface RunTraceRef {\n /** Trace id shared by every span of the run. */\n traceId: string\n /** Root run of the execution tree the run spawned, when one exists. */\n execRunId?: string\n}\n\n/**\n * The run id of one attempt at a search cell. It is unique across candidates\n * and attempts, unlike a `${scenario}:${rep}` id, which every candidate that\n * ran the same scenario shares.\n */\nexport function searchCellRunId(search: Pick<RunSearchCoordinates, 'cellId' | 'attempt'>): string {\n return `${search.cellId}:${search.attempt}`\n}\n\nexport interface RunJudgeMetadata {\n model: string\n promptVersion: string\n /** [0,1] confidence the judge declared. Constant judge confidence\n * across many runs is a fallback signal (see `canary.ts`). */\n confidence: number\n /** True if the judge degraded to a fallback path (rules-only,\n * prior-call cache, etc.). The canary uses this to alert. */\n fallback: boolean\n}\n\n/**\n * Per-judge / per-dimension breakdown for runs scored by an ensemble of\n * judges over a multi-dimensional rubric.\n *\n * The collapsed `outcome.searchScore` / `holdoutScore` carries the\n * composite the gate uses. The full breakdown belongs here so consumers\n * can answer \"which judge disagreed?\", \"which dimension dragged the\n * composite down?\", and \"did half the panel fail?\" without re-running.\n *\n * `perJudge[judgeId][dim]` is the canonical source; `perDimMean` and\n * `composite` are convenience projections — derivable but precomputed so\n * downstream IRR primitives (`interRaterReliability`,\n * `corpusInterRaterAgreement`) and reporters don't pay the same\n * aggregation twice.\n *\n * Fail-loud discipline: judges that errored out land in `failedJudges`\n * by id. A missing key in `perJudge` is ambiguous (silent zero vs not\n * run); the explicit list makes a partial-failure recorded as such.\n */\nexport interface JudgeScoresRecord {\n /** Per-judge per-dimension scores. `{ \"kimi-k2.6\": { helpfulness: 0.8, clarity: 0.7 }, ... }`. */\n perJudge: Record<string, Record<string, number>>\n /** Per-dim mean across judges. Convenience — derivable from `perJudge`. */\n perDimMean: Record<string, number>\n /** Composite mean across successful judges. Mirrors the task score only\n * when `failedJudges` is empty. */\n composite: number\n /** Judges that errored or returned an unparseable verdict. Recorded\n * by id (e.g. `['glm-5.1']`) so a partial-failure case is explicit,\n * not inferred from missing keys in `perJudge`. */\n failedJudges?: string[]\n /** Free-form notes the judges emitted (joined across judges or\n * first-judge only — consumer's choice). */\n notes?: string\n}\n\nexport interface RunOutcome {\n /** Score on the search/optimization split. Optional for holdout-only and\n * execution-only records. */\n searchScore?: number\n /** Score on the held-out split. Optional for search-only and execution-only\n * records. When both scores are absent, the run is explicitly unlabeled. */\n holdoutScore?: number\n /** Bag of any other metric the run produced — judge dimensions,\n * pass/fail counters, latency stats, etc. Numeric only — keeps\n * reporters honest. */\n raw: Record<string, number>\n /** Per-judge / per-dim breakdown. Consumers writing ensemble\n * judgements populate this; substrate primitives like\n * `interRaterReliability` and `corpusInterRaterAgreement` accept\n * these records as input. Optional — single-judge or scalar-only\n * runs leave it unset. */\n judgeScores?: JudgeScoresRecord\n /** Authenticity / realness verdict — did the run build the REAL thing on the\n * intended infra, or fake it (see `./authenticity`)? Optional: only domains\n * with an authenticity config populate it. Carried in the corpus so the\n * flywheel / off-policy learning can optimize for real completion, not gamed\n * pass-rate. `score` is 0-1; `gated` is the anti-Goodhart flag — a gated run\n * must not count as a real success regardless of `score`. */\n realness?: { score: number; gated: boolean; reason?: string }\n}\n\n/**\n * Mandatory paper-grade fields for a single evaluation run. Optional\n * fields are extension points; mandatory fields throw if missing.\n *\n * Hash discipline:\n * - `promptHash` is the sha256 of the EFFECTIVE prompt sent to the\n * model (after any steering bundle merge).\n * - `configHash` is the sha256 of the effective run config (model,\n * temperature, tools, judges, splits). The pair (promptHash,\n * configHash) uniquely identifies an experiment cell.\n *\n * Model snapshot discipline:\n * - successful rows MUST encode a snapshot version. Bare aliases like\n * `claude-sonnet-4` or `gpt-4o` are banned — they remap silently.\n * Use `claude-sonnet-4-6@2025-04-15` or `gpt-4o-2024-11-20`.\n * - a failed, cancelled, incomplete, or otherwise unknown row may use\n * `UNKNOWN_MODEL` when no served model was observed. This is an explicit\n * absence marker, not a fabricated snapshot.\n */\nexport interface RunRecord {\n /** UUID for the run. */\n runId: string\n /** Logical experiment grouping (a treatment vs a baseline within\n * the same sweep should share `experimentId`). */\n experimentId: string\n /** Stable identifier for the candidate (variant) being run. The\n * promotion gate compares two `candidateId`s on matched items. */\n candidateId: string\n /** RNG seed for the run. Always recorded — silent re-seeding is\n * the most common cause of non-reproducible numbers. */\n seed: number\n /** Model identifier WITH snapshot version. */\n model: string\n /** sha256 of the effective prompt (post-steering). */\n promptHash: string\n /** sha256 of the effective config. */\n configHash: string\n /** Git SHA the harness was run from. */\n commitSha: string\n /** End-to-end wall-clock duration in milliseconds. */\n wallMs: number\n /** Time spent queued before execution started, if known. */\n queueMs?: number\n /** Total USD cost, or null when the total is unknown. */\n costUsd: number | null\n /** Whether `costUsd` came from billing data or a price calculation, is only\n * proven down to a floor, or is unavailable. */\n costProvenance: RunCostProvenance\n /** Token usage breakdown. */\n tokenUsage: RunTokenUsage\n /** Root-run or process terminal result. Never inferred from a child span. */\n terminalOutcome: RunTerminalOutcome\n /** Root-run or process failure reason. Valid only for a failed, cancelled,\n * or incomplete terminal result; never populated from a child span. */\n terminalFailureReason?: string\n /** Judge-side metadata, if a judge was used. */\n judgeMetadata?: RunJudgeMetadata\n /** Per-split scores + raw bag. */\n outcome: RunOutcome\n /** Canonical task-failure class drawn from the shared\n * `FAILURE_CLASSES` taxonomy. Producers set it only from task-result\n * evidence. Execution errors belong in\n * `outcome.raw.execution_error_count`. */\n failureClass?: FailureClass\n /** Free-form task-failure detail scoped under a non-success\n * `failureClass`. It is invalid without that class. */\n failureMode?: string\n /** Which split this run was drawn from. */\n splitTag: RunSplitTag\n /**\n * Stable scenario identifier the run observed or was scored against.\n * Comparison primitives match this identity rather than input order.\n */\n scenarioId: string\n /**\n * Canonical identity for the agent profile cell that produced this row:\n * profile artifact hash plus optional harness/model/prompt/reporting\n * dimensions. Use `agentProfile.cellId` to group persona sweeps and\n * longitudinal reports by the complete source profile, not by a loose\n * candidate label or opaque config hash.\n */\n agentProfile?: AgentProfileCell\n /** The search cell this run settled. When present, `runId` is\n * `searchCellRunId(search)`. */\n search?: RunSearchCoordinates\n /** The run's trace and execution tree. Absent means the producer did not\n * record where they are. */\n traceRef?: RunTraceRef\n}\n\n/**\n * Canonical task-result classification.\n *\n * A producer may omit classification, record explicit success, or attach\n * domain-specific detail to a non-success class. Detail can never stand alone.\n * Execution errors belong in `outcome.raw.execution_error_count`.\n */\nexport type RunTaskFailure =\n | { failureClass?: undefined; failureMode?: undefined }\n | { failureClass: 'success'; failureMode?: undefined }\n | {\n failureClass: Exclude<FailureClass, 'success'>\n failureMode?: string\n }\n\n/**\n * Return task quality, preferring held-out evidence when both scores exist.\n *\n * RAW: no realness protection is applied. Built on `observedScore` rather\n * than repeating the split derivation, so only `rollout/reward.ts` reads the\n * raw fields. Anything that becomes training data must use `trainingScore` or\n * `trainingReward` instead.\n */\nexport function runTaskScore(record: RunRecord): number | undefined {\n const score = observedScore(record)\n return typeof score === 'number' && Number.isFinite(score) ? score : undefined\n}\n\n// ── Validation ───────────────────────────────────────────────────────\n\nconst MANDATORY_TOP_LEVEL = [\n 'runId',\n 'experimentId',\n 'candidateId',\n 'seed',\n 'model',\n 'promptHash',\n 'configHash',\n 'commitSha',\n 'wallMs',\n 'costUsd',\n 'costProvenance',\n 'tokenUsage',\n 'terminalOutcome',\n 'outcome',\n 'splitTag',\n 'scenarioId',\n] as const\n\nconst SPLIT_TAGS: ReadonlyArray<RunSplitTag> = ['search', 'dev', 'holdout']\nconst TERMINAL_OUTCOMES: ReadonlyArray<RunTerminalOutcome> = [\n 'succeeded',\n 'failed',\n 'cancelled',\n 'incomplete',\n 'unknown',\n]\n\nexport class RunRecordValidationError extends ValidationError {\n readonly path: string\n constructor(message: string, path = '') {\n super(path ? `${message} (at ${path})` : message)\n this.path = path\n }\n}\n\n/**\n * Strict validator. Throws `RunRecordValidationError` on the first\n * missing or wrongly-typed field. Returns the input cast to\n * `RunRecord` on success — the validator does not coerce.\n */\nexport function validateRunRecord(input: unknown): RunRecord {\n if (input === null || typeof input !== 'object') {\n throw new RunRecordValidationError('expected object')\n }\n const obj = input as Record<string, unknown>\n\n for (const key of MANDATORY_TOP_LEVEL) {\n if (!(key in obj)) {\n throw new RunRecordValidationError(`missing mandatory field \"${key}\"`)\n }\n }\n\n expectString(obj.runId, 'runId')\n expectString(obj.experimentId, 'experimentId')\n expectString(obj.candidateId, 'candidateId')\n expectFiniteNumber(obj.seed, 'seed')\n expectString(obj.model, 'model')\n expectString(obj.promptHash, 'promptHash')\n expectString(obj.configHash, 'configHash')\n expectString(obj.commitSha, 'commitSha')\n expectNonNegativeNumber(obj.wallMs, 'wallMs')\n if (obj.queueMs !== undefined) expectNonNegativeNumber(obj.queueMs, 'queueMs')\n validateCost(obj.costUsd, obj.costProvenance)\n\n // Snapshot discipline: successful rows require a served model snapshot.\n // Non-success rows may carry the explicit absence marker when execution\n // stopped before a model identity was observed.\n if (\n !modelHasSnapshot(obj.model as string) &&\n !(obj.model === UNKNOWN_MODEL && obj.terminalOutcome !== 'succeeded')\n ) {\n throw new RunRecordValidationError(\n `model \"${obj.model}\" lacks a snapshot version (use 'name@YYYY-MM-DD' or 'name-YYYYMMDD', or '${UNKNOWN_MODEL}' for a non-success row without a served model)`,\n 'model',\n )\n }\n\n // Token usage.\n const tu = obj.tokenUsage\n if (tu === null || typeof tu !== 'object') {\n throw new RunRecordValidationError('tokenUsage must be an object', 'tokenUsage')\n }\n const tuRec = tu as Record<string, unknown>\n expectNonNegativeNumber(tuRec.input, 'tokenUsage.input')\n expectNonNegativeNumber(tuRec.output, 'tokenUsage.output')\n if (tuRec.tokensKnown !== undefined && tuRec.tokensKnown !== false) {\n throw new RunRecordValidationError(\n 'tokensKnown must be false when present; omit it when token usage is complete',\n 'tokenUsage.tokensKnown',\n )\n }\n if (tuRec.reasoning !== undefined) {\n expectNonNegativeNumber(tuRec.reasoning, 'tokenUsage.reasoning')\n if ((tuRec.reasoning as number) > (tuRec.output as number)) {\n throw new RunRecordValidationError(\n 'reasoning tokens must be a subset of output tokens',\n 'tokenUsage.reasoning',\n )\n }\n }\n if (tuRec.cached !== undefined) expectNonNegativeNumber(tuRec.cached, 'tokenUsage.cached')\n if (tuRec.cacheWrite !== undefined) {\n expectNonNegativeNumber(tuRec.cacheWrite, 'tokenUsage.cacheWrite')\n }\n\n // Judge metadata, optional.\n if (obj.judgeMetadata !== undefined) {\n const jm = obj.judgeMetadata\n if (jm === null || typeof jm !== 'object') {\n throw new RunRecordValidationError('judgeMetadata must be an object', 'judgeMetadata')\n }\n const jmRec = jm as Record<string, unknown>\n expectString(jmRec.model, 'judgeMetadata.model')\n expectString(jmRec.promptVersion, 'judgeMetadata.promptVersion')\n expectFiniteNumber(jmRec.confidence, 'judgeMetadata.confidence')\n if (typeof jmRec.fallback !== 'boolean') {\n throw new RunRecordValidationError(\n 'judgeMetadata.fallback must be boolean',\n 'judgeMetadata.fallback',\n )\n }\n }\n\n // Outcome.\n const out = obj.outcome\n if (out === null || typeof out !== 'object') {\n throw new RunRecordValidationError('outcome must be an object', 'outcome')\n }\n const outRec = out as Record<string, unknown>\n if (outRec.searchScore !== undefined)\n expectFiniteNumber(outRec.searchScore, 'outcome.searchScore')\n if (outRec.holdoutScore !== undefined)\n expectFiniteNumber(outRec.holdoutScore, 'outcome.holdoutScore')\n const raw = outRec.raw\n if (raw === null || typeof raw !== 'object') {\n throw new RunRecordValidationError('outcome.raw must be an object', 'outcome.raw')\n }\n for (const [k, v] of Object.entries(raw as Record<string, unknown>)) {\n expectFiniteNumber(v, `outcome.raw.${k}`)\n }\n // Realness verdict, optional.\n if (outRec.realness !== undefined) {\n const r = outRec.realness\n if (r === null || typeof r !== 'object') {\n throw new RunRecordValidationError('outcome.realness must be an object', 'outcome.realness')\n }\n const rr = r as Record<string, unknown>\n expectFiniteNumber(rr.score, 'outcome.realness.score')\n if (typeof rr.gated !== 'boolean') {\n throw new RunRecordValidationError(\n 'outcome.realness.gated must be a boolean',\n 'outcome.realness.gated',\n )\n }\n }\n\n // Per-judge / per-dim breakdown, optional.\n if (outRec.judgeScores !== undefined) {\n validateJudgeScores(outRec.judgeScores, 'outcome.judgeScores')\n }\n\n // Failure mode optional.\n if (\n obj.failureClass !== undefined &&\n (typeof obj.failureClass !== 'string' ||\n !FAILURE_CLASSES.includes(obj.failureClass as FailureClass))\n ) {\n throw new RunRecordValidationError(\n `failureClass must be one of ${FAILURE_CLASSES.join(', ')}`,\n 'failureClass',\n )\n }\n if (obj.failureMode !== undefined) {\n expectString(obj.failureMode, 'failureMode')\n if (obj.failureClass === undefined || obj.failureClass === 'success') {\n throw new RunRecordValidationError(\n 'failureMode requires a non-success failureClass',\n 'failureMode',\n )\n }\n }\n\n if (\n typeof obj.terminalOutcome !== 'string' ||\n !TERMINAL_OUTCOMES.includes(obj.terminalOutcome as RunTerminalOutcome)\n ) {\n throw new RunRecordValidationError(\n `terminalOutcome must be one of ${TERMINAL_OUTCOMES.join(', ')}`,\n 'terminalOutcome',\n )\n }\n if (obj.terminalFailureReason !== undefined) {\n expectString(obj.terminalFailureReason, 'terminalFailureReason')\n if (\n obj.terminalOutcome !== 'failed' &&\n obj.terminalOutcome !== 'cancelled' &&\n obj.terminalOutcome !== 'incomplete'\n ) {\n throw new RunRecordValidationError(\n 'terminalFailureReason requires terminalOutcome failed, cancelled, or incomplete',\n 'terminalFailureReason',\n )\n }\n }\n\n if (obj.agentProfile !== undefined) {\n try {\n const profile = validateAgentProfileCell(obj.agentProfile)\n if (profile.model !== undefined && profile.model !== obj.model) {\n throw new RunRecordValidationError(\n `agentProfile.model \"${profile.model}\" does not match model \"${obj.model}\"`,\n 'agentProfile.model',\n )\n }\n if (profile.promptHash !== undefined && profile.promptHash !== obj.promptHash) {\n throw new RunRecordValidationError(\n `agentProfile.promptHash \"${profile.promptHash}\" does not match promptHash \"${obj.promptHash}\"`,\n 'agentProfile.promptHash',\n )\n }\n } catch (error) {\n if (error instanceof RunRecordValidationError) throw error\n if (error instanceof Error) {\n throw new RunRecordValidationError(error.message, 'agentProfile')\n }\n throw error\n }\n }\n\n expectString(obj.scenarioId, 'scenarioId')\n\n if (obj.search !== undefined) validateSearchCoordinates(obj.search, obj.runId as string)\n if (obj.traceRef !== undefined) validateTraceRef(obj.traceRef)\n\n // Split tag.\n if (typeof obj.splitTag !== 'string' || !SPLIT_TAGS.includes(obj.splitTag as RunSplitTag)) {\n throw new RunRecordValidationError(\n `splitTag must be one of ${SPLIT_TAGS.join(', ')}, got ${String(obj.splitTag)}`,\n 'splitTag',\n )\n }\n\n return input as RunRecord\n}\n\nfunction validateCost(costUsd: unknown, provenance: unknown): void {\n if (provenance === null || typeof provenance !== 'object') {\n throw new RunRecordValidationError('costProvenance must be an object', 'costProvenance')\n }\n const value = provenance as Record<string, unknown>\n if (\n value.kind !== 'observed' &&\n value.kind !== 'estimated' &&\n value.kind !== 'lower-bound' &&\n value.kind !== 'uncaptured'\n ) {\n throw new RunRecordValidationError(\n 'costProvenance.kind must be observed, estimated, lower-bound, or uncaptured',\n 'costProvenance.kind',\n )\n }\n if (value.kind === 'lower-bound') {\n if (value.usd !== null) {\n throw new RunRecordValidationError(\n 'lower-bound costProvenance.usd must be null; the floor is knownLowerBoundUsd',\n 'costProvenance.usd',\n )\n }\n if (costUsd !== null) {\n throw new RunRecordValidationError(\n 'lower-bound cost requires costUsd to be null; a floor is not a total',\n 'costUsd',\n )\n }\n expectFiniteNumber(value.knownLowerBoundUsd, 'costProvenance.knownLowerBoundUsd')\n if ((value.knownLowerBoundUsd as number) <= 0) {\n throw new RunRecordValidationError(\n \"a lower bound must be positive; write a $0 floor as { kind: 'uncaptured', usd: null }\",\n 'costProvenance.knownLowerBoundUsd',\n )\n }\n return\n }\n // A record must never read as a total it cannot support, so an uncaptured\n // cost carries no number at all. A matrix `CellResult` keeps its known\n // subtotal instead, because a cost ceiling must charge the part it can see;\n // converting one to the other drops that subtotal.\n if (value.kind === 'uncaptured') {\n if (value.usd !== null) {\n throw new RunRecordValidationError(\n 'uncaptured costProvenance.usd must be null',\n 'costProvenance.usd',\n )\n }\n if (costUsd !== null) {\n throw new RunRecordValidationError('uncaptured cost requires costUsd to be null', 'costUsd')\n }\n return\n }\n expectNonNegativeNumber(costUsd, 'costUsd')\n expectNonNegativeNumber(value.usd, 'costProvenance.usd')\n if (value.usd !== costUsd) {\n throw new RunRecordValidationError(\n 'costProvenance.usd must equal costUsd',\n 'costProvenance.usd',\n )\n }\n}\n\nfunction validateSearchCoordinates(value: unknown, runId: string): void {\n if (value === null || typeof value !== 'object') {\n throw new RunRecordValidationError('search must be an object', 'search')\n }\n const search = value as Record<string, unknown>\n expectString(search.searchId, 'search.searchId')\n expectString(search.nodeId, 'search.nodeId')\n expectString(search.cellId, 'search.cellId')\n if (!Number.isSafeInteger(search.attempt) || (search.attempt as number) < 1) {\n throw new RunRecordValidationError('expected an integer from 1', 'search.attempt')\n }\n const expected = searchCellRunId(search as unknown as RunSearchCoordinates)\n if (runId !== expected) {\n throw new RunRecordValidationError(\n `runId \"${runId}\" must be \"${expected}\", the search cell and attempt it settled`,\n 'runId',\n )\n }\n}\n\nfunction validateTraceRef(value: unknown): void {\n if (value === null || typeof value !== 'object') {\n throw new RunRecordValidationError('traceRef must be an object', 'traceRef')\n }\n const ref = value as Record<string, unknown>\n expectString(ref.traceId, 'traceRef.traceId')\n if (ref.execRunId !== undefined) expectString(ref.execRunId, 'traceRef.execRunId')\n}\n\n/** Boolean validator — convenience for filtering arrays. */\nexport function isRunRecord(input: unknown): input is RunRecord {\n try {\n validateRunRecord(input)\n return true\n } catch {\n return false\n }\n}\n\n/** Non-throwing validator — returns a discriminated union. */\nexport function parseRunRecordSafe(\n input: unknown,\n): { ok: true; value: RunRecord } | { ok: false; error: RunRecordValidationError } {\n try {\n return { ok: true, value: validateRunRecord(input) }\n } catch (e) {\n if (e instanceof RunRecordValidationError) return { ok: false, error: e }\n throw e\n }\n}\n\n// ── Internals ────────────────────────────────────────────────────────\n\nfunction expectString(value: unknown, path: string): void {\n if (typeof value !== 'string' || value.length === 0) {\n throw new RunRecordValidationError(`expected non-empty string`, path)\n }\n}\n\nfunction expectFiniteNumber(value: unknown, path: string): void {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new RunRecordValidationError(`expected finite number`, path)\n }\n}\n\nfunction expectNonNegativeNumber(value: unknown, path: string): void {\n expectFiniteNumber(value, path)\n if ((value as number) < 0) {\n throw new RunRecordValidationError('expected non-negative number', path)\n }\n}\n\nfunction validateJudgeScores(value: unknown, path: string): void {\n if (value === null || typeof value !== 'object') {\n throw new RunRecordValidationError('judgeScores must be an object', path)\n }\n const rec = value as Record<string, unknown>\n\n const perJudge = rec.perJudge\n if (perJudge === null || typeof perJudge !== 'object') {\n throw new RunRecordValidationError('perJudge must be an object', `${path}.perJudge`)\n }\n for (const [judgeId, dims] of Object.entries(perJudge as Record<string, unknown>)) {\n if (dims === null || typeof dims !== 'object') {\n throw new RunRecordValidationError(\n 'per-judge entry must be an object of dimension scores',\n `${path}.perJudge.${judgeId}`,\n )\n }\n for (const [dim, score] of Object.entries(dims as Record<string, unknown>)) {\n expectFiniteNumber(score, `${path}.perJudge.${judgeId}.${dim}`)\n }\n }\n\n const perDimMean = rec.perDimMean\n if (perDimMean === null || typeof perDimMean !== 'object') {\n throw new RunRecordValidationError('perDimMean must be an object', `${path}.perDimMean`)\n }\n for (const [dim, mean] of Object.entries(perDimMean as Record<string, unknown>)) {\n expectFiniteNumber(mean, `${path}.perDimMean.${dim}`)\n }\n\n expectFiniteNumber(rec.composite, `${path}.composite`)\n\n if (rec.failedJudges !== undefined) {\n if (!Array.isArray(rec.failedJudges)) {\n throw new RunRecordValidationError(\n 'failedJudges must be an array of strings',\n `${path}.failedJudges`,\n )\n }\n for (let i = 0; i < rec.failedJudges.length; i++) {\n const id = rec.failedJudges[i]\n if (typeof id !== 'string' || id.length === 0) {\n throw new RunRecordValidationError(\n 'failedJudges entry must be a non-empty string',\n `${path}.failedJudges[${i}]`,\n )\n }\n }\n }\n\n if (rec.notes !== undefined && typeof rec.notes !== 'string') {\n throw new RunRecordValidationError('notes must be a string', `${path}.notes`)\n }\n}\n\n/**\n * Snapshot check for provider model identifiers. Accepts ISO and compact\n * dates, Router's `-MMDD` snapshots, one opaque `@token`, and Vertex-style\n * `:date-token` suffixes. Routing selectors such as `@preset/name` are not\n * immutable model identities.\n */\nexport function modelHasSnapshot(model: string): boolean {\n if (model.length === 0 || model.trim() !== model) return false\n\n const opaqueAt = model.lastIndexOf('@')\n if (opaqueAt > 0) {\n const base = model.slice(0, opaqueAt)\n const token = model.slice(opaqueAt + 1)\n if (!base.includes('@') && /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/u.test(token)) {\n return true\n }\n }\n\n const isoDate = model.match(/-(\\d{4})-(\\d{2})-(\\d{2})$/u)\n if (isoDate && validSnapshotDate(isoDate[1]!, isoDate[2]!, isoDate[3]!)) return true\n\n const compactDate = model.match(/-(\\d{4})(\\d{2})(\\d{2})$/u)\n if (compactDate && validSnapshotDate(compactDate[1]!, compactDate[2]!, compactDate[3]!)) {\n return true\n }\n\n const routerDate = model.match(/-(\\d{2})(\\d{2})$/u)\n if (routerDate && validSnapshotDate(undefined, routerDate[1]!, routerDate[2]!)) return true\n\n return /:date-[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/u.test(model)\n}\n\nfunction validSnapshotDate(year: string | undefined, month: string, day: string): boolean {\n const monthNumber = Number(month)\n const dayNumber = Number(day)\n if (!Number.isInteger(monthNumber) || monthNumber < 1 || monthNumber > 12) return false\n\n const yearNumber = year === undefined ? undefined : Number(year)\n const leapYear =\n yearNumber === undefined ||\n (yearNumber % 4 === 0 && (yearNumber % 100 !== 0 || yearNumber % 400 === 0))\n const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n return Number.isInteger(dayNumber) && dayNumber >= 1 && dayNumber <= daysInMonth[monthNumber - 1]!\n}\n"],"mappings":"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"}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Always-valid sequential evaluation.
|
|
3
|
-
*
|
|
4
|
-
* `researchReport` assumes a single pre-specified analysis. Real
|
|
5
|
-
* consumers run campaigns weekly / nightly / per-PR; each new run silently
|
|
6
|
-
* inflates the false-discovery rate, because the BH-FDR guarantee is for
|
|
7
|
-
* the *first* look, not the 47th. Without time-uniform inference,
|
|
8
|
-
* launch-decision teams either (a) don't peek, which forfeits the cost
|
|
9
|
-
* advantage of stop-when-decisive, or (b) peek and pretend they didn't,
|
|
10
|
-
* which forfeits scientific validity.
|
|
11
|
-
*
|
|
12
|
-
* This module ships **e-value-based confidence sequences** for paired
|
|
13
|
-
* bounded outcomes. The methodology is the predictable plug-in betting
|
|
14
|
-
* martingale of Waudby-Smith & Ramdas (2024) — provably valid at *any*
|
|
15
|
-
* stopping time. Concretely:
|
|
16
|
-
*
|
|
17
|
-
* For paired deltas D_1, D_2, … ∈ [-c, c] with the null H_0: E[D] ≤ 0,
|
|
18
|
-
* a betting fraction λ_i is chosen using only D_{1..i-1} (predictable
|
|
19
|
-
* plug-in), and the running e-value is
|
|
20
|
-
*
|
|
21
|
-
* E_t = ∏_{i=1}^{t} (1 + λ_i · D_i)
|
|
22
|
-
*
|
|
23
|
-
* E_t is a non-negative martingale under H_0 with E[E_t] ≤ 1, so by
|
|
24
|
-
* Ville's inequality, P(∃ t : E_t ≥ 1/α) ≤ α — we can reject the null
|
|
25
|
-
* at any time without inflating the type-I error.
|
|
26
|
-
*
|
|
27
|
-
* Combined with `runEvalCampaign`, every consumer running rolling
|
|
28
|
-
* campaigns gains the ability to ship the moment evidence is decisive,
|
|
29
|
-
* stop-early on dead-on-arrival variants, and accumulate evidence across
|
|
30
|
-
* partial runs without spending the FDR budget. No new sweep is wasted.
|
|
31
|
-
*
|
|
32
|
-
* References:
|
|
33
|
-
* - Howard, S. R., Ramdas, A., McAuliffe, J., Sekhon, J. (2021).
|
|
34
|
-
* Time-uniform, nonparametric, nonasymptotic confidence sequences.
|
|
35
|
-
* Annals of Statistics, 49(2), 1055–1080.
|
|
36
|
-
* - Waudby-Smith, I., Ramdas, A. (2024). Estimating means of bounded
|
|
37
|
-
* random variables by betting. JRSS B, 86(1), 1–27.
|
|
38
|
-
*/
|
|
39
|
-
type SequentialDecision = 'promote_now' | 'continue' | 'reject_now' | 'equivalent';
|
|
40
|
-
interface PairedEvalueOptions {
|
|
41
|
-
/**
|
|
42
|
-
* Bound on |delta|. Default 1 (matching most score scales). Must satisfy
|
|
43
|
-
* c > 0; deltas outside [-c, c] are clipped with a warning attached to
|
|
44
|
-
* the return value.
|
|
45
|
-
*/
|
|
46
|
-
bound?: number;
|
|
47
|
-
/** Target Type-I error. Default 0.05. */
|
|
48
|
-
alpha?: number;
|
|
49
|
-
/**
|
|
50
|
-
* Region of Practical Equivalence on the *mean* paired delta. When
|
|
51
|
-
* supplied, the verdict can return `'equivalent'` once the running
|
|
52
|
-
* confidence sequence on the mean is fully contained in [low, high].
|
|
53
|
-
*/
|
|
54
|
-
rope?: {
|
|
55
|
-
low: number;
|
|
56
|
-
high: number;
|
|
57
|
-
};
|
|
58
|
-
/** Initial bet shrinkage (0 < scale ≤ 1). Default 0.5 — empirically robust. */
|
|
59
|
-
initialBetShrinkage?: number;
|
|
60
|
-
}
|
|
61
|
-
interface PairedEvalueStep {
|
|
62
|
-
/** 1-indexed observation count. */
|
|
63
|
-
t: number;
|
|
64
|
-
delta: number;
|
|
65
|
-
/** Running e-value E_t = ∏ (1 + λ_i · D_i). */
|
|
66
|
-
evalue: number;
|
|
67
|
-
/** Time-uniform p-value at stopping time t. */
|
|
68
|
-
pValue: number;
|
|
69
|
-
/** Lower bound of the empirical Bernstein confidence sequence at level 1-α. */
|
|
70
|
-
csLow: number;
|
|
71
|
-
csHigh: number;
|
|
72
|
-
/** Verdict at this stopping time. */
|
|
73
|
-
decision: SequentialDecision;
|
|
74
|
-
}
|
|
75
|
-
interface PairedEvalueSequence {
|
|
76
|
-
steps: PairedEvalueStep[];
|
|
77
|
-
/** The decision at the final step. */
|
|
78
|
-
finalDecision: SequentialDecision;
|
|
79
|
-
/** Index (1-based) at which a non-`continue` decision first fired, or null. */
|
|
80
|
-
decisionFiredAt: number | null;
|
|
81
|
-
/** True if any deltas were clipped to [-bound, bound]. */
|
|
82
|
-
clipped: boolean;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Run the paired e-value sequence over an in-order delta stream.
|
|
86
|
-
*
|
|
87
|
-
* Use for *streaming* / interim analyses: pass the deltas you have so
|
|
88
|
-
* far, get the verdict at every prefix length. The decision is
|
|
89
|
-
* monotone-stable in the sense that once `'reject_now'` or `'promote_now'`
|
|
90
|
-
* fires, the verdict at later steps remains decisive (the e-value is a
|
|
91
|
-
* non-negative martingale; once it crosses the threshold, it's crossed).
|
|
92
|
-
*/
|
|
93
|
-
declare function pairedEvalueSequence(deltas: number[], opts?: PairedEvalueOptions): PairedEvalueSequence;
|
|
94
|
-
/** Configuration for the best-case reachability preflight. */
|
|
95
|
-
interface SequentialCrossingHorizonOptions extends Pick<PairedEvalueOptions, 'alpha' | 'bound' | 'initialBetShrinkage'> {
|
|
96
|
-
/** Maximum pairs to simulate before returning `null`. Default 10,000. */
|
|
97
|
-
maxPairs?: number;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Best-case horizons under the exact betting policy used by
|
|
101
|
-
* {@link pairedEvalueSequence}.
|
|
102
|
-
*
|
|
103
|
-
* `evidencePairs` is the first all-at-bound pair count whose e-value reaches
|
|
104
|
-
* `1/alpha`. `decisionPairs` is the first count whose actual two-sided
|
|
105
|
-
* sequence verdict fires (`2/alpha` in the current policy). A design whose
|
|
106
|
-
* pair cap is below either relevant horizon is undecidable by construction and
|
|
107
|
-
* should be refused before model spend.
|
|
108
|
-
*/
|
|
109
|
-
interface SequentialCrossingHorizon {
|
|
110
|
-
readonly evidencePairs: number | null;
|
|
111
|
-
readonly decisionPairs: number | null;
|
|
112
|
-
readonly evidenceThreshold: number;
|
|
113
|
-
readonly decisionThreshold: number;
|
|
114
|
-
readonly maxPairs: number;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Compute the minimum pair count at which even perfect, all-at-bound data can
|
|
118
|
-
* reach the evidence and decision thresholds. The calculation intentionally
|
|
119
|
-
* calls the canonical sequence implementation rather than maintaining a
|
|
120
|
-
* second approximation that can drift from its bet schedule.
|
|
121
|
-
*/
|
|
122
|
-
declare function sequentialCrossingHorizon(opts?: SequentialCrossingHorizonOptions): SequentialCrossingHorizon;
|
|
123
|
-
interface InterimReleaseConfidenceInput {
|
|
124
|
-
/**
|
|
125
|
-
* One delta series per candidate (paired deltas vs comparator). Order
|
|
126
|
-
* within a series is the order the campaigns were run.
|
|
127
|
-
*/
|
|
128
|
-
deltaSeries: Array<{
|
|
129
|
-
candidateId: string;
|
|
130
|
-
deltas: number[];
|
|
131
|
-
}>;
|
|
132
|
-
alpha?: number;
|
|
133
|
-
bound?: number;
|
|
134
|
-
rope?: {
|
|
135
|
-
low: number;
|
|
136
|
-
high: number;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
interface InterimReleaseConfidence {
|
|
140
|
-
candidates: Array<{
|
|
141
|
-
candidateId: string;
|
|
142
|
-
decision: SequentialDecision;
|
|
143
|
-
decisionFiredAt: number | null;
|
|
144
|
-
finalEvalue: number;
|
|
145
|
-
finalPValue: number;
|
|
146
|
-
pairs: number;
|
|
147
|
-
csLow: number;
|
|
148
|
-
csHigh: number;
|
|
149
|
-
}>;
|
|
150
|
-
/**
|
|
151
|
-
* Campaign-level recommendation: pick the strongest 'promote_now', else
|
|
152
|
-
* 'continue' if any candidate is still live, else 'reject_now' if every
|
|
153
|
-
* candidate is dead, else 'equivalent'.
|
|
154
|
-
*/
|
|
155
|
-
recommendation: {
|
|
156
|
-
decision: SequentialDecision;
|
|
157
|
-
candidateId: string | null;
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Run interim sequential analyses across many candidates at once,
|
|
162
|
-
* preserving the time-uniform α guarantee for each candidate's series and
|
|
163
|
-
* synthesising a campaign-level recommendation. Designed to be called on
|
|
164
|
-
* every campaign tick — the recommendation is anytime-valid.
|
|
165
|
-
*/
|
|
166
|
-
declare function evaluateInterimReleaseConfidence(input: InterimReleaseConfidenceInput): InterimReleaseConfidence;
|
|
167
|
-
export { PairedEvalueStep as a, SequentialDecision as c, sequentialCrossingHorizon as d, PairedEvalueSequence as i, evaluateInterimReleaseConfidence as l, InterimReleaseConfidenceInput as n, SequentialCrossingHorizon as o, PairedEvalueOptions as r, SequentialCrossingHorizonOptions as s, InterimReleaseConfidence as t, pairedEvalueSequence as u };
|
|
168
|
-
//# sourceMappingURL=sequential-B9p6uoV8.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sequential-B9p6uoV8.d.ts","names":[],"sources":["../src/sequential.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuCY;UAEK;;;;;;EAMf;;EAEA;;;;;;EAMA;IAAS;IAAa;;;EAEtB;;UAGe;;EAEf;EACA;;EAEA;;EAEA;;EAEA;EACA;;EAEA,UAAU;;UAGK;EACf,OAAO;;EAEP,eAAe;;EAEf;;EAEA;;;;;;;;;;;iBAYc,qBACd,kBACA,OAAM,sBACL;;UA0Ec,yCACP,KAAK;;EAEb;;;;;;;;;;;;UAae;WACN;WACA;WACA;WACA;WACA;;;;;;;;iBAWK,0BACd,OAAM,mCACL;UAmCc;;;;;EAKf,aAAa;IAAQ;IAAqB;;EAC1C;EACA;EACA;IAAS;IAAa;;;UAGP;EACf,YAAY;IACV;IACA,UAAU;IACV;IACA;IACA;IACA;IACA;IACA;;;;;;;EAOF;IAAkB,UAAU;IAAoB;;;;;;;;;iBASlC,iCACd,OAAO,gCACN"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sequential-CAksw6EU.js","names":[],"sources":["../src/sequential.ts"],"sourcesContent":["/**\n * Always-valid sequential evaluation.\n *\n * `researchReport` assumes a single pre-specified analysis. Real\n * consumers run campaigns weekly / nightly / per-PR; each new run silently\n * inflates the false-discovery rate, because the BH-FDR guarantee is for\n * the *first* look, not the 47th. Without time-uniform inference,\n * launch-decision teams either (a) don't peek, which forfeits the cost\n * advantage of stop-when-decisive, or (b) peek and pretend they didn't,\n * which forfeits scientific validity.\n *\n * This module ships **e-value-based confidence sequences** for paired\n * bounded outcomes. The methodology is the predictable plug-in betting\n * martingale of Waudby-Smith & Ramdas (2024) — provably valid at *any*\n * stopping time. Concretely:\n *\n * For paired deltas D_1, D_2, … ∈ [-c, c] with the null H_0: E[D] ≤ 0,\n * a betting fraction λ_i is chosen using only D_{1..i-1} (predictable\n * plug-in), and the running e-value is\n *\n * E_t = ∏_{i=1}^{t} (1 + λ_i · D_i)\n *\n * E_t is a non-negative martingale under H_0 with E[E_t] ≤ 1, so by\n * Ville's inequality, P(∃ t : E_t ≥ 1/α) ≤ α — we can reject the null\n * at any time without inflating the type-I error.\n *\n * Combined with `runEvalCampaign`, every consumer running rolling\n * campaigns gains the ability to ship the moment evidence is decisive,\n * stop-early on dead-on-arrival variants, and accumulate evidence across\n * partial runs without spending the FDR budget. No new sweep is wasted.\n *\n * References:\n * - Howard, S. R., Ramdas, A., McAuliffe, J., Sekhon, J. (2021).\n * Time-uniform, nonparametric, nonasymptotic confidence sequences.\n * Annals of Statistics, 49(2), 1055–1080.\n * - Waudby-Smith, I., Ramdas, A. (2024). Estimating means of bounded\n * random variables by betting. JRSS B, 86(1), 1–27.\n */\n\nexport type SequentialDecision = 'promote_now' | 'continue' | 'reject_now' | 'equivalent'\n\nexport interface PairedEvalueOptions {\n /**\n * Bound on |delta|. Default 1 (matching most score scales). Must satisfy\n * c > 0; deltas outside [-c, c] are clipped with a warning attached to\n * the return value.\n */\n bound?: number\n /** Target Type-I error. Default 0.05. */\n alpha?: number\n /**\n * Region of Practical Equivalence on the *mean* paired delta. When\n * supplied, the verdict can return `'equivalent'` once the running\n * confidence sequence on the mean is fully contained in [low, high].\n */\n rope?: { low: number; high: number }\n /** Initial bet shrinkage (0 < scale ≤ 1). Default 0.5 — empirically robust. */\n initialBetShrinkage?: number\n}\n\nexport interface PairedEvalueStep {\n /** 1-indexed observation count. */\n t: number\n delta: number\n /** Running e-value E_t = ∏ (1 + λ_i · D_i). */\n evalue: number\n /** Time-uniform p-value at stopping time t. */\n pValue: number\n /** Lower bound of the empirical Bernstein confidence sequence at level 1-α. */\n csLow: number\n csHigh: number\n /** Verdict at this stopping time. */\n decision: SequentialDecision\n}\n\nexport interface PairedEvalueSequence {\n steps: PairedEvalueStep[]\n /** The decision at the final step. */\n finalDecision: SequentialDecision\n /** Index (1-based) at which a non-`continue` decision first fired, or null. */\n decisionFiredAt: number | null\n /** True if any deltas were clipped to [-bound, bound]. */\n clipped: boolean\n}\n\n/**\n * Run the paired e-value sequence over an in-order delta stream.\n *\n * Use for *streaming* / interim analyses: pass the deltas you have so\n * far, get the verdict at every prefix length. The decision is\n * monotone-stable in the sense that once `'reject_now'` or `'promote_now'`\n * fires, the verdict at later steps remains decisive (the e-value is a\n * non-negative martingale; once it crosses the threshold, it's crossed).\n */\nexport function pairedEvalueSequence(\n deltas: number[],\n opts: PairedEvalueOptions = {},\n): PairedEvalueSequence {\n const c = opts.bound ?? 1\n const alpha = opts.alpha ?? 0.05\n const initialShrink = opts.initialBetShrinkage ?? 0.5\n const rope = opts.rope ?? null\n assertSequentialScalarConfiguration(c, alpha, initialShrink, 'pairedEvalueSequence')\n if (rope && !(Number.isFinite(rope.low) && Number.isFinite(rope.high) && rope.low <= rope.high)) {\n throw new Error('pairedEvalueSequence: rope must satisfy low ≤ high')\n }\n const { decisionThreshold } = sequentialThresholds(alpha)\n\n const steps: PairedEvalueStep[] = []\n let clipped = false\n let evalue = 1\n let decisionFiredAt: number | null = null\n\n // Running statistics (using only D_{1..i-1} for the bet → predictable plug-in).\n let sum = 0\n let sumSq = 0\n let count = 0\n\n for (let i = 0; i < deltas.length; i++) {\n let d = deltas[i]!\n if (!Number.isFinite(d)) {\n throw new Error(`pairedEvalueSequence: delta[${i}] must be finite`)\n }\n if (d < -c || d > c) {\n d = Math.max(-c, Math.min(c, d))\n clipped = true\n }\n\n // Predictable plug-in bet (positive λ tests for E[D] > 0; we run a two-sided\n // test by tracking the symmetric e-value via |bet|).\n // λ_i ∝ mean / (variance + bound^2). Shrink early to avoid overbetting.\n const muHat = count === 0 ? 0 : sum / count\n const varHat = count === 0 ? c * c : Math.max(1e-12, sumSq / count - muHat * muHat)\n const t = i + 1\n const shrink = initialShrink * Math.min(1, count / 32) // anneal toward 1\n let lambda = (muHat / (varHat + c * c)) * shrink\n // Clip to ensure 1 + λ·D > 0 for all |D| ≤ c (so the e-value stays non-negative).\n const lambdaMax = 0.99 / c\n if (lambda > lambdaMax) lambda = lambdaMax\n if (lambda < -lambdaMax) lambda = -lambdaMax\n\n evalue = evalue * (1 + lambda * d)\n if (!Number.isFinite(evalue) || evalue < 0) evalue = 0\n\n sum += d\n sumSq += d * d\n count += 1\n\n const pValue = Math.min(1, 1 / Math.max(evalue, 1e-300))\n\n // Empirical Bernstein confidence sequence on the mean. Howard et al.\n // (2021), Theorem 4.4 with σ̂² the running sample variance and a\n // calibration constant tuned for two-sided coverage at level 1 - α.\n const cs = empiricalBernsteinCs(sum, sumSq, count, c, alpha)\n\n let decision: SequentialDecision = 'continue'\n if (rope && cs.low >= rope.low && cs.high <= rope.high) decision = 'equivalent'\n else if (evalue >= decisionThreshold && muHat > 0) decision = 'promote_now'\n else if (evalue >= decisionThreshold && muHat < 0) decision = 'reject_now'\n else if (rope && cs.high < rope.low) decision = 'reject_now'\n\n if (decision !== 'continue' && decisionFiredAt === null) decisionFiredAt = t\n\n steps.push({ t, delta: d, evalue, pValue, csLow: cs.low, csHigh: cs.high, decision })\n }\n\n const finalDecision = steps.length === 0 ? 'continue' : steps[steps.length - 1]!.decision\n return { steps, finalDecision, decisionFiredAt, clipped }\n}\n\n/** Configuration for the best-case reachability preflight. */\nexport interface SequentialCrossingHorizonOptions\n extends Pick<PairedEvalueOptions, 'alpha' | 'bound' | 'initialBetShrinkage'> {\n /** Maximum pairs to simulate before returning `null`. Default 10,000. */\n maxPairs?: number\n}\n\n/**\n * Best-case horizons under the exact betting policy used by\n * {@link pairedEvalueSequence}.\n *\n * `evidencePairs` is the first all-at-bound pair count whose e-value reaches\n * `1/alpha`. `decisionPairs` is the first count whose actual two-sided\n * sequence verdict fires (`2/alpha` in the current policy). A design whose\n * pair cap is below either relevant horizon is undecidable by construction and\n * should be refused before model spend.\n */\nexport interface SequentialCrossingHorizon {\n readonly evidencePairs: number | null\n readonly decisionPairs: number | null\n readonly evidenceThreshold: number\n readonly decisionThreshold: number\n readonly maxPairs: number\n}\n\nconst MAX_SEQUENTIAL_CROSSING_PAIRS = 1_000_000\n\n/**\n * Compute the minimum pair count at which even perfect, all-at-bound data can\n * reach the evidence and decision thresholds. The calculation intentionally\n * calls the canonical sequence implementation rather than maintaining a\n * second approximation that can drift from its bet schedule.\n */\nexport function sequentialCrossingHorizon(\n opts: SequentialCrossingHorizonOptions = {},\n): SequentialCrossingHorizon {\n const bound = opts.bound ?? 1\n const alpha = opts.alpha ?? 0.05\n const initialBetShrinkage = opts.initialBetShrinkage ?? 0.5\n const maxPairs = opts.maxPairs ?? 10_000\n assertSequentialScalarConfiguration(\n bound,\n alpha,\n initialBetShrinkage,\n 'sequentialCrossingHorizon',\n )\n if (!Number.isSafeInteger(maxPairs) || maxPairs < 1) {\n throw new Error('sequentialCrossingHorizon: maxPairs must be a positive safe integer')\n }\n if (maxPairs > MAX_SEQUENTIAL_CROSSING_PAIRS) {\n throw new Error(\n `sequentialCrossingHorizon: maxPairs must be <= ${MAX_SEQUENTIAL_CROSSING_PAIRS}`,\n )\n }\n const sequence = pairedEvalueSequence(Array<number>(maxPairs).fill(bound), {\n bound,\n alpha,\n initialBetShrinkage,\n })\n const { evidenceThreshold, decisionThreshold } = sequentialThresholds(alpha)\n const evidencePairs = sequence.steps.find((step) => step.evalue >= evidenceThreshold)?.t ?? null\n return Object.freeze({\n evidencePairs,\n decisionPairs: sequence.decisionFiredAt,\n evidenceThreshold,\n decisionThreshold,\n maxPairs,\n })\n}\n\nexport interface InterimReleaseConfidenceInput {\n /**\n * One delta series per candidate (paired deltas vs comparator). Order\n * within a series is the order the campaigns were run.\n */\n deltaSeries: Array<{ candidateId: string; deltas: number[] }>\n alpha?: number\n bound?: number\n rope?: { low: number; high: number }\n}\n\nexport interface InterimReleaseConfidence {\n candidates: Array<{\n candidateId: string\n decision: SequentialDecision\n decisionFiredAt: number | null\n finalEvalue: number\n finalPValue: number\n pairs: number\n csLow: number\n csHigh: number\n }>\n /**\n * Campaign-level recommendation: pick the strongest 'promote_now', else\n * 'continue' if any candidate is still live, else 'reject_now' if every\n * candidate is dead, else 'equivalent'.\n */\n recommendation: { decision: SequentialDecision; candidateId: string | null }\n}\n\n/**\n * Run interim sequential analyses across many candidates at once,\n * preserving the time-uniform α guarantee for each candidate's series and\n * synthesising a campaign-level recommendation. Designed to be called on\n * every campaign tick — the recommendation is anytime-valid.\n */\nexport function evaluateInterimReleaseConfidence(\n input: InterimReleaseConfidenceInput,\n): InterimReleaseConfidence {\n const candidates = input.deltaSeries.map((s) => {\n const seq = pairedEvalueSequence(s.deltas, {\n alpha: input.alpha,\n bound: input.bound,\n rope: input.rope,\n })\n const last = seq.steps[seq.steps.length - 1]\n return {\n candidateId: s.candidateId,\n decision: seq.finalDecision,\n decisionFiredAt: seq.decisionFiredAt,\n finalEvalue: last?.evalue ?? 1,\n finalPValue: last?.pValue ?? 1,\n pairs: seq.steps.length,\n csLow: last?.csLow ?? Number.NEGATIVE_INFINITY,\n csHigh: last?.csHigh ?? Number.POSITIVE_INFINITY,\n }\n })\n\n const promote = candidates.find((c) => c.decision === 'promote_now')\n if (promote)\n return {\n candidates,\n recommendation: { decision: 'promote_now', candidateId: promote.candidateId },\n }\n const live = candidates.find((c) => c.decision === 'continue')\n if (live) return { candidates, recommendation: { decision: 'continue', candidateId: null } }\n const equiv = candidates.find((c) => c.decision === 'equivalent')\n if (equiv)\n return {\n candidates,\n recommendation: { decision: 'equivalent', candidateId: equiv.candidateId },\n }\n return { candidates, recommendation: { decision: 'reject_now', candidateId: null } }\n}\n\n// ── Internals ────────────────────────────────────────────────────────────\n\nfunction assertSequentialScalarConfiguration(\n bound: number,\n alpha: number,\n initialBetShrinkage: number,\n context: string,\n): void {\n if (!Number.isFinite(bound) || bound <= 0) {\n throw new Error(`${context}: bound must be a finite number > 0`)\n }\n if (!Number.isFinite(alpha) || alpha <= 0 || alpha >= 1) {\n throw new Error(`${context}: alpha must be a finite number in (0,1)`)\n }\n if (\n !Number.isFinite(initialBetShrinkage) ||\n initialBetShrinkage <= 0 ||\n initialBetShrinkage > 1\n ) {\n throw new Error(`${context}: initialBetShrinkage must be a finite number in (0,1]`)\n }\n}\n\nfunction sequentialThresholds(alpha: number): {\n evidenceThreshold: number\n decisionThreshold: number\n} {\n return { evidenceThreshold: 1 / alpha, decisionThreshold: 2 / alpha }\n}\n\n/**\n * Empirical Bernstein confidence sequence on the mean of bounded variables.\n * Adapted from Howard et al. (2021) §4.4. Provides a time-uniform CI on\n * the running mean; valid at every stopping time.\n */\nfunction empiricalBernsteinCs(\n sum: number,\n sumSq: number,\n n: number,\n bound: number,\n alpha: number,\n): { low: number; high: number } {\n if (n === 0) return { low: -bound, high: bound }\n const mean = sum / n\n const variance = Math.max(0, sumSq / n - mean * mean)\n // Iterated-log calibration constant. The 1.7 exponent matches the\n // recommended choice in Howard et al. for two-sided coverage at level\n // 1 - α with mild log-corrections; tightening further requires a\n // tuned mixture and is out of scope.\n const psi = Math.log(2 / alpha) + 1.7 * Math.log(Math.log(Math.max(Math.E, n)) + 1)\n const radius = Math.sqrt((2 * variance * psi) / n) + (3 * bound * psi) / n\n return { low: mean - radius, high: mean + radius }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-DFVwfoZq.js","names":[],"sources":["../src/wire/schemas.ts","../src/wire/rubrics.ts","../src/wire/handlers.ts","../src/wire/rpc.ts","../src/wire/openapi.ts","../src/wire/server.ts"],"sourcesContent":["/**\n * Wire-protocol schemas.\n *\n * These Zod schemas are the contract between the agent-eval runtime and\n * any non-TypeScript client (Python, Rust, Go, …). They get rendered to\n * OpenAPI by `wire/openapi.ts` and code-generators consume that spec to\n * produce typed clients in other languages.\n *\n * Rule: if it's not in this file, it isn't on the wire. Keep names and\n * shapes self-explanatory — every field has a `.describe()` so the\n * generated docs are useful without reading the source.\n */\nimport { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi'\nimport { z } from 'zod'\nimport { hashCanonical } from '../ledger-core/canonical'\n\nextendZodWithOpenApi(z)\n\n// ── Building blocks ─────────────────────────────────────────────────\n\nexport const RubricDimensionSchema = z\n .object({\n id: z\n .string()\n .min(1)\n .describe('Short stable id like \"buyer_quality\" — used as the key in scoring output.'),\n description: z\n .string()\n .min(1)\n .describe('One-line plain-English meaning. Read by humans reviewing low scores.'),\n weight: z\n .number()\n .min(0)\n .default(1)\n .describe('Relative weight in the composite score. Default 1; 0 disables.'),\n min: z.number().default(0).describe('Lower bound of valid score for this dimension.'),\n max: z.number().default(1).describe('Upper bound of valid score for this dimension.'),\n })\n .openapi('WireRubricDimension')\n\nconst FailureModeSchema = z\n .object({\n id: z.string().min(1).describe('Short stable id like \"ai-cadence\" — used in detection lists.'),\n description: z.string().min(1).describe('Plain-English description of the failure pattern.'),\n })\n .openapi('WireFailureMode')\n\n// ── Rubric ──────────────────────────────────────────────────────────\n\nexport const RubricSchema = z\n .object({\n name: z\n .string()\n .min(1)\n .describe('Stable name like \"anti-slop\" — used by clients to invoke this rubric.'),\n description: z\n .string()\n .min(1)\n .describe('What this rubric measures. Shown in /v1/rubrics listing.'),\n systemPrompt: z\n .string()\n .min(1)\n .describe(\n 'Instructs the judging LLM. Should explain the persona (e.g. \"senior engineer reviewing voice\"), what to score on, and what to return.',\n ),\n dimensions: z\n .array(RubricDimensionSchema)\n .min(1)\n .describe('Scoring axes. The composite score is a weighted sum of these.'),\n failureModes: z\n .array(FailureModeSchema)\n .default([])\n .describe('Patterns to detect; each detected mode appears in the result.failureModes list.'),\n wins: z\n .array(FailureModeSchema)\n .default([])\n .describe('Positive patterns; each detected one appears in the result.wins list.'),\n })\n .openapi('Rubric')\n\n// ── Judge call ──────────────────────────────────────────────────────\n\nexport const JudgeRequestSchema = z\n .object({\n rubricName: z\n .string()\n .optional()\n .describe('Use a built-in rubric by name. Mutually exclusive with `rubric`.'),\n rubric: RubricSchema.optional().describe(\n 'Inline rubric definition. Mutually exclusive with `rubricName`.',\n ),\n content: z\n .string()\n .min(1)\n .describe('The text being judged — a tweet, a blog post, a code snippet, anything stringly.'),\n context: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Free-form metadata for the rubric to use — analytics, source URL, author, etc. Surfaced to the LLM.',\n ),\n model: z.string().optional().describe('Override the judge model configured by the server.'),\n })\n .refine((v) => Boolean(v.rubricName) !== Boolean(v.rubric), {\n message: 'Provide exactly one of `rubricName` or `rubric`.',\n })\n .openapi('JudgeRequest')\n\nexport const JudgeResultSchema = z\n .object({\n composite: z\n .number()\n .min(0)\n .max(1)\n .describe('Weighted combination of dimension scores in 0..1. The single number to gate on.'),\n dimensions: z\n .record(z.string(), z.number())\n .describe('Per-dimension score, keyed by WireRubricDimension.id.'),\n failureModes: z\n .array(z.string())\n .default([])\n .describe('Failure-mode ids detected in the content (subset of rubric.failureModes ids).'),\n wins: z\n .array(z.string())\n .default([])\n .describe('Win ids detected in the content (subset of rubric.wins ids).'),\n rationale: z\n .string()\n .describe('Plain-English explanation of the score. Surfaced to the human reviewer.'),\n rubricVersion: z\n .string()\n .describe(\n 'Stable identity of the rubric used, as `<name>@sha256-rfc8785:<hex>`. Scores are only comparable across runs when this matches exactly.',\n ),\n model: z.string().describe('Model that produced the judgement, for reproducibility.'),\n durationMs: z.number().int().nonnegative().describe('End-to-end wall time for this call.'),\n })\n .openapi('JudgeResult')\n\n// ── Rubric listing ──────────────────────────────────────────────────\n\nconst RubricInfoSchema = z\n .object({\n name: z.string().describe('Pass this to /v1/judge as `rubricName`.'),\n description: z.string().describe('What this rubric measures.'),\n dimensions: z\n .array(z.object({ id: z.string(), description: z.string(), weight: z.number() }))\n .describe('The scoring axes this rubric uses, with weights.'),\n failureModes: z.array(z.string()).default([]).describe('Failure-mode ids this rubric detects.'),\n rubricVersion: z\n .string()\n .describe(\n 'Stable identity, as `<name>@sha256-rfc8785:<hex>` — match this to compare scores across runs.',\n ),\n })\n .openapi('RubricInfo')\n\nexport const ListRubricsResponseSchema = z\n .object({\n rubrics: z.array(RubricInfoSchema),\n })\n .openapi('ListRubricsResponse')\n\n// ── Version / health ────────────────────────────────────────────────\n\nexport const VersionResponseSchema = z\n .object({\n package: z.string().describe('Package name (always \"@tangle-network/agent-eval\").'),\n version: z.string().describe('Semver of the running server. Match your client to this.'),\n wireVersion: z\n .string()\n .describe(\n 'Wire-protocol semver. Bumps separately from package version when the schema changes.',\n ),\n apiSurface: z.array(z.string()).describe('List of supported method names.'),\n })\n .openapi('VersionResponse')\n\nexport const HealthResponseSchema = z\n .object({\n status: z.literal('ok'),\n uptimeSec: z.number(),\n })\n .openapi('HealthResponse')\n\n// ── Ingestion: production traces + user feedback ────────────────────\n\n/**\n * Minimal `WireTraceEvent` shape that the production runtime emits.\n * Matches `trace/schema.ts` `WireTraceEvent` but is duplicated here as a\n * wire schema so non-TypeScript clients can validate without depending\n * on internal types.\n */\nexport const TraceEventSchema = z\n .object({\n eventId: z.string().min(1).describe('Stable id for the event. Use ULID or UUID.'),\n runId: z.string().min(1).describe('Run this event belongs to.'),\n spanId: z.string().optional().describe('Span that emitted the event, if any.'),\n kind: z\n .enum([\n 'log',\n 'error',\n 'budget_decrement',\n 'budget_breach',\n 'state_mutation',\n 'policy_violation',\n 'redaction_applied',\n 'custom',\n ])\n .describe('Coarse event category — matches the TraceSchema v1 EventKind enum.'),\n timestamp: z\n .number()\n .int()\n .nonnegative()\n .describe('Unix millis. Must be monotonically non-decreasing within a span.'),\n payload: z\n .record(z.string(), z.unknown())\n .describe('Free-form payload — the runtime owns the shape.'),\n })\n .openapi('WireTraceEvent')\n\nexport const TracesIngestRequestSchema = z\n .object({\n events: z\n .array(TraceEventSchema)\n .min(1)\n .max(10_000)\n .describe('Batch of events. Max 10k per call — bigger streams should be chunked.'),\n })\n .openapi('TracesIngestRequest')\n\nexport const TracesIngestResponseSchema = z\n .object({\n accepted: z.number().int().nonnegative().describe('Number of events persisted.'),\n rejected: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of events the store refused — see `errors[]` for reasons.'),\n errors: z\n .array(\n z.object({\n eventId: z.string().describe('Event id this error applies to.'),\n message: z.string().describe('Why the event was rejected.'),\n }),\n )\n .default([]),\n })\n .openapi('TracesIngestResponse')\n\nconst FeedbackLabelSchema = z\n .object({\n id: z.string().optional(),\n source: z.enum(['user', 'judge', 'environment', 'metric', 'policy', 'system']),\n kind: z.enum([\n 'approve',\n 'reject',\n 'select',\n 'edit',\n 'rank',\n 'rate',\n 'comment',\n 'metric_outcome',\n 'policy_block',\n 'revision_request',\n ]),\n value: z.unknown(),\n reason: z.string().optional(),\n severity: z.enum(['info', 'warning', 'error', 'critical']).optional(),\n createdAt: z.string().describe('ISO-8601 UTC.'),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('FeedbackLabel')\n\nconst FeedbackAttemptSchema = z\n .object({\n id: z.string().min(1),\n stepIndex: z.number().int().nonnegative(),\n artifactType: z.enum([\n 'text',\n 'code',\n 'plan',\n 'research',\n 'action',\n 'ui',\n 'decision',\n 'data',\n 'other',\n ]),\n artifact: z.unknown(),\n options: z.array(z.unknown()).optional(),\n proposedAction: z\n .object({\n type: z.string(),\n risk: z.enum(['low', 'medium', 'high']).optional(),\n costUsd: z.number().optional(),\n externalSideEffect: z.boolean().optional(),\n requiresApproval: z.boolean().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n feedback: z.array(FeedbackLabelSchema).optional(),\n createdAt: z.string(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('FeedbackAttempt')\n\nexport const FeedbackTrajectorySchema = z\n .object({\n id: z.string().min(1).describe('Stable id; idempotency key for the trajectory.'),\n projectId: z.string().optional(),\n scenarioId: z.string().optional(),\n task: z.object({\n intent: z.string().min(1),\n context: z.unknown().optional(),\n }),\n attempts: z.array(FeedbackAttemptSchema).default([]),\n labels: z.array(FeedbackLabelSchema).default([]),\n outcome: z\n .object({\n success: z.boolean().optional(),\n score: z.number().optional(),\n metrics: z.record(z.string(), z.number()).optional(),\n costUsd: z.number().optional(),\n detail: z.string().optional(),\n observedAt: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n split: z.enum(['train', 'dev', 'test', 'holdout']).optional(),\n tags: z.record(z.string(), z.string()).optional(),\n createdAt: z.string().describe('ISO-8601 UTC.'),\n updatedAt: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n })\n .openapi('WireFeedbackTrajectory')\n\nexport const FeedbackIngestResponseSchema = z\n .object({\n id: z.string().describe('Trajectory id that was persisted.'),\n persisted: z.boolean().describe('True when the trajectory was saved (idempotent on id).'),\n })\n .openapi('FeedbackIngestResponse')\n\nexport type WireTraceEvent = z.infer<typeof TraceEventSchema>\nexport type TracesIngestRequest = z.infer<typeof TracesIngestRequestSchema>\nexport type TracesIngestResponse = z.infer<typeof TracesIngestResponseSchema>\nexport type WireFeedbackTrajectory = z.infer<typeof FeedbackTrajectorySchema>\nexport type FeedbackIngestResponse = z.infer<typeof FeedbackIngestResponseSchema>\n\n// ── Errors ──────────────────────────────────────────────────────────\n\nexport const ErrorResponseSchema = z\n .object({\n error: z\n .object({\n code: z\n .string()\n .describe(\n 'Machine-readable code: \"validation_error\", \"rubric_not_found\", \"judge_error\".',\n ),\n message: z.string().describe('Human-readable message.'),\n details: z.unknown().optional().describe('Optional structured detail.'),\n })\n .describe('Errors are always wrapped in this shape across all endpoints.'),\n })\n .openapi('ErrorResponse')\n\n// ── Type exports for callers in the same package ────────────────────\n\nexport type WireRubricDimension = z.infer<typeof RubricDimensionSchema>\nexport type WireFailureMode = z.infer<typeof FailureModeSchema>\nexport type Rubric = z.infer<typeof RubricSchema>\nexport type JudgeRequest = z.infer<typeof JudgeRequestSchema>\nexport type JudgeResult = z.infer<typeof JudgeResultSchema>\nexport type RubricInfo = z.infer<typeof RubricInfoSchema>\nexport type ListRubricsResponse = z.infer<typeof ListRubricsResponseSchema>\nexport type VersionResponse = z.infer<typeof VersionResponseSchema>\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>\n\n// ── Wire-protocol version ───────────────────────────────────────────\n\n/**\n * Bump the major on any breaking change to a request/response schema — the\n * Python client compares majors and refuses a mismatch. Bump the minor when a\n * response value changes meaning without changing its shape, which a client\n * can detect but does not have to act on.\n */\nexport const WIRE_VERSION = '1.1.0'\n\n/**\n * The digest scheme `hashRubric` mints, named inside the value it produces.\n * A consumer holding a tag from an earlier release reads a different scheme\n * here and can tell \"this package changed how it hashes\" from \"the rubric\n * changed\" — the two are indistinguishable when the value is an untagged hex\n * string.\n */\nconst RUBRIC_VERSION_SCHEME = 'sha256-rfc8785'\n\n/**\n * Stable identity of a rubric, as `<name>@sha256-rfc8785:<hex>`. Two scores\n * are comparable when this matches exactly.\n *\n * The digest comes from `hashCanonical`, this package's only canonical-JSON\n * encoder (RFC 8785). RFC 8785 orders keys by UTF-16 code unit, which is a\n * property of the value alone — so the same rubric produces the same tag on\n * every machine, which a locale-collated key order does not guarantee.\n */\nexport function hashRubric(rubric: Rubric): string {\n return `${rubric.name}@${RUBRIC_VERSION_SCHEME}:${hashCanonical(rubric).slice('sha256:'.length)}`\n}\n","/**\n * Built-in rubrics shipped with agent-eval.\n *\n * A rubric is a set of scoring axes plus a system prompt that tells the\n * judging LLM how to grade against those axes. Built-in rubrics are\n * curated for use cases that recur across Tangle projects — call them\n * by name from any client.\n *\n * Adding a rubric:\n * 1. Define the Rubric object below with a clear `description` and\n * named `dimensions`.\n * 2. Register it in `BUILTIN_RUBRICS` at the bottom.\n * 3. Add a test in `tests/wire/rubrics.test.ts`.\n *\n * Custom rubrics: callers pass `rubric` inline to /v1/judge instead of\n * `rubricName` — see schemas.ts.\n */\nimport type { Rubric } from './schemas'\nimport { hashRubric } from './schemas'\n\n// ── anti-slop ───────────────────────────────────────────────────────\n// Voice/style judge tuned for technical-buyer audiences. Used by the\n// Postiz autoresearch loop and any content-quality gate.\n\nconst ANTI_SLOP: Rubric = {\n name: 'anti-slop',\n description:\n 'Voice and signal quality for content aimed at senior engineers. Catches AI cadence, marketing tone, and engagement-bait shapes.',\n systemPrompt: `You are evaluating a piece of content written for senior engineers and technical founders.\n\nYou score three things:\n- buyer_quality (0..1): would a senior engineer in the target ICP find this worth their attention? High = specific, earned, technically interesting. Low = generic, hyped, off-target.\n- voice (0..1): does it read like a person who built the thing, or like AI/marketing copy?\n- signal (0..1): does it contain a non-obvious detail, constraint, or claim a reader couldn't get from the public docs?\n\nDetect failure modes (return ids matching):\n- ai-cadence: rule-of-three openings, em-dash flourish, \"Let me explain\", \"Here's the thing\", AI rhythm\n- marketing-tone: \"We're excited to announce\", \"thrilled\", \"delighted\", \"game-changer\", buzzword stack\n- vague-claim: technical claim without a specific component, file, or measurement\n- no-hook: opening doesn't earn attention from the target reader\n- engagement-bait: \"agree?\", \"thoughts?\", listicles, controversy-fishing, hook-detail-pitch\n- off-icp: content shape would attract motivational/grift/hype audiences instead of buyers\n- stale-claim: repeats a positioning line we've used many times this month\n\nDetect wins (return ids matching):\n- specific-component: names a real file, component, or measurement\n- earned-detail: shares a non-obvious detail not derivable from public docs\n- constraint-articulated: names a real tradeoff and the side chosen\n- honest-failure: describes a real failure mode and what was done about it\n\nReturn ONLY JSON matching the response schema. Be conservative — most content has 0-1 wins and 1-2 failure modes, not many of each.`,\n dimensions: [\n {\n id: 'buyer_quality',\n description: 'Would the target buyer find this worth attention?',\n weight: 0.5,\n min: 0,\n max: 1,\n },\n {\n id: 'voice',\n description: 'Does it sound like a builder, not AI or marketing?',\n weight: 0.3,\n min: 0,\n max: 1,\n },\n {\n id: 'signal',\n description: 'Non-obvious detail, constraint, or claim?',\n weight: 0.2,\n min: 0,\n max: 1,\n },\n ],\n failureModes: [\n { id: 'ai-cadence', description: 'AI-rhythm openings and transitions' },\n { id: 'marketing-tone', description: 'Buzzwords, hype, corporate-PR voice' },\n { id: 'vague-claim', description: 'Technical claim without specifics' },\n { id: 'no-hook', description: 'Opening fails to earn attention' },\n { id: 'engagement-bait', description: 'Listicle/controversy/agree-pattern' },\n { id: 'off-icp', description: 'Voice attracts the wrong audience' },\n { id: 'stale-claim', description: 'Reuses an over-used positioning line' },\n ],\n wins: [\n { id: 'specific-component', description: 'Names a real file/component/number' },\n { id: 'earned-detail', description: 'Detail not in public docs' },\n { id: 'constraint-articulated', description: 'Names a real tradeoff' },\n { id: 'honest-failure', description: 'Describes a real failure honestly' },\n ],\n}\n\n// ── Registry ────────────────────────────────────────────────────────\n\nconst BUILTIN_RUBRICS: Record<string, Rubric> = {\n 'anti-slop': ANTI_SLOP,\n}\n\n/** Get a built-in rubric by name, or undefined. */\nexport function getBuiltinRubric(name: string): Rubric | undefined {\n return BUILTIN_RUBRICS[name]\n}\n\n/** List built-in rubrics with their stable versions. */\nexport function listBuiltinRubrics() {\n return Object.values(BUILTIN_RUBRICS).map((r) => ({\n name: r.name,\n description: r.description,\n dimensions: r.dimensions.map((d) => ({\n id: d.id,\n description: d.description,\n weight: d.weight,\n })),\n failureModes: r.failureModes.map((f) => f.id),\n rubricVersion: hashRubric(r),\n }))\n}\n","/**\n * Pure handler functions — the \"business logic\" behind every wire-protocol\n * method. The HTTP server (`server.ts`) and the stdio RPC (`rpc.ts`) both\n * call these. Tests call these directly without spinning a server.\n *\n * Each handler:\n * - Takes a parsed request (already Zod-validated by the transport).\n * - Returns a result that matches the response schema.\n * - Throws `WireError` for caller-fixable errors (404, 400, 422).\n * - Lets unexpected errors bubble — the transport maps them to 500.\n */\n\nimport type { ChatClient } from '../analyst/chat-client'\nimport { paidJsonChat } from '../chat-json-call'\nimport { CostLedger, type CostLedgerHandle, type CustomTokenPricing } from '../cost-ledger'\nimport type { FeedbackTrajectoryStore } from '../feedback-trajectory'\nimport type { LlmCallRequest } from '../llm-client'\nimport { packageVersion } from '../package-version'\nimport type { TraceEvent as InternalTraceEvent } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\nimport { getBuiltinRubric, listBuiltinRubrics } from './rubrics'\nimport {\n type FeedbackIngestResponse,\n hashRubric,\n type JudgeRequest,\n type JudgeResult,\n type ListRubricsResponse,\n type Rubric,\n type TracesIngestRequest,\n type TracesIngestResponse,\n type VersionResponse,\n WIRE_VERSION,\n type WireFeedbackTrajectory,\n} from './schemas'\n\n/** Caller-fixable error. The transport renders this to 4xx + ErrorResponse. */\nexport class WireError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly status: number = 400,\n public readonly details?: unknown,\n ) {\n super(message)\n this.name = 'WireError'\n }\n}\n\n// ── judge ───────────────────────────────────────────────────────────\n\n/** The JSON schema we ask the judging LLM to fill in. */\nfunction judgeOutputSchema(rubric: Rubric) {\n return {\n name: 'JudgeOutput',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n dimensions: {\n type: 'object',\n additionalProperties: false,\n properties: Object.fromEntries(\n rubric.dimensions.map((d) => [\n d.id,\n { type: 'number', minimum: d.min, maximum: d.max },\n ]),\n ),\n required: rubric.dimensions.map((d) => d.id),\n },\n failureModes: {\n type: 'array',\n items: { type: 'string', enum: rubric.failureModes.map((f) => f.id) },\n },\n wins: {\n type: 'array',\n items: { type: 'string', enum: rubric.wins.map((w) => w.id) },\n },\n rationale: { type: 'string' },\n },\n required: ['dimensions', 'rationale'],\n } as Record<string, unknown>,\n }\n}\n\ninterface JudgeOutput {\n dimensions: Record<string, number>\n failureModes?: string[]\n wins?: string[]\n rationale: string\n}\n\nfunction validateJudgeOutput(value: unknown, rubric: Rubric): JudgeOutput {\n if (!value || typeof value !== 'object') {\n throw new WireError('judge_error', 'Judge returned malformed output.', 500, value)\n }\n const raw = value as Record<string, unknown>\n const rawDimensions = raw.dimensions\n if (!rawDimensions || typeof rawDimensions !== 'object' || Array.isArray(rawDimensions)) {\n throw new WireError('judge_error', 'Judge returned malformed dimensions.', 500, value)\n }\n\n const dimensions: Record<string, number> = {}\n const dimensionRecord = rawDimensions as Record<string, unknown>\n for (const dim of rubric.dimensions) {\n const score = dimensionRecord[dim.id]\n if (\n typeof score !== 'number' ||\n !Number.isFinite(score) ||\n score < dim.min ||\n score > dim.max\n ) {\n throw new WireError(\n 'judge_error',\n `Judge returned invalid score for dimension \"${dim.id}\".`,\n 500,\n value,\n )\n }\n dimensions[dim.id] = score\n }\n\n const allowedFailures = new Set(rubric.failureModes.map((mode) => mode.id))\n const allowedWins = new Set(rubric.wins.map((win) => win.id))\n const failureModes = validateIdArray(raw.failureModes, allowedFailures, 'failureModes', value)\n const wins = validateIdArray(raw.wins, allowedWins, 'wins', value)\n if (typeof raw.rationale !== 'string' || raw.rationale.trim().length === 0) {\n throw new WireError('judge_error', 'Judge returned missing rationale.', 500, value)\n }\n\n return { dimensions, failureModes, wins, rationale: raw.rationale }\n}\n\nfunction validateIdArray(\n raw: unknown,\n allowed: Set<string>,\n field: 'failureModes' | 'wins',\n original: unknown,\n): string[] {\n if (raw === undefined) return []\n if (!Array.isArray(raw)) {\n throw new WireError('judge_error', `Judge returned non-array ${field}.`, 500, original)\n }\n const out: string[] = []\n for (const item of raw) {\n if (typeof item !== 'string' || !allowed.has(item)) {\n throw new WireError(\n 'judge_error',\n `Judge returned unknown ${field} id \"${String(item)}\".`,\n 500,\n original,\n )\n }\n out.push(item)\n }\n return out\n}\n\nfunction compositeScore(dimensions: Record<string, number>, rubric: Rubric): number {\n let weighted = 0\n let totalWeight = 0\n for (const dim of rubric.dimensions) {\n const raw = dimensions[dim.id] ?? 0\n const range = dim.max - dim.min || 1\n const normalized = Math.max(0, Math.min(1, (raw - dim.min) / range))\n weighted += normalized * dim.weight\n totalWeight += dim.weight\n }\n return totalWeight > 0 ? weighted / totalWeight : 0\n}\n\nfunction buildJudgePrompt(content: string, context: unknown): string {\n const ctx = context && Object.keys(context as object).length ? JSON.stringify(context) : ''\n return [\n `CONTENT TO JUDGE:`,\n content,\n '',\n ctx ? `CONTEXT (metadata, analytics, etc.):` : '',\n ctx ? ctx : '',\n ]\n .filter(Boolean)\n .join('\\n')\n}\n\nconst DEFAULT_JUDGE_MODEL = 'claude-sonnet-4-6'\n\nexport interface HandleJudgeOptions {\n costLedger?: CostLedgerHandle\n costPhase?: string\n /**\n * Caller-owned transport for the judge call. agent-eval holds no provider\n * credential: the process that serves this endpoint binds its own client.\n * Omitting it makes `/v1/judge` refuse with `llm_not_configured`.\n */\n chat?: ChatClient\n defaultModel?: string\n /** Endpoint rates used when the transport reports no billed amount. */\n pricing?: CustomTokenPricing\n signal?: AbortSignal\n}\n\nexport async function handleJudge(\n req: JudgeRequest,\n options: HandleJudgeOptions = {},\n): Promise<JudgeResult> {\n // Resolve rubric\n let rubric: Rubric\n if (req.rubricName) {\n const found = getBuiltinRubric(req.rubricName)\n if (!found) {\n throw new WireError('rubric_not_found', `No built-in rubric named \"${req.rubricName}\".`, 404)\n }\n rubric = found\n } else if (req.rubric) {\n rubric = req.rubric\n } else {\n // refine() in the schema should already have caught this — defense in depth\n throw new WireError('validation_error', 'Provide either `rubricName` or `rubric`.', 422)\n }\n\n if (!options.chat) {\n throw new WireError(\n 'llm_not_configured',\n 'No model transport is configured. Pass a ChatClient, or configure the CLI provider environment variables.',\n 503,\n )\n }\n\n const startedAt = Date.now()\n const model =\n req.model ?? options.defaultModel ?? options.chat.defaultModel ?? DEFAULT_JUDGE_MODEL\n\n const request = {\n model,\n messages: [\n { role: 'system', content: rubric.systemPrompt },\n { role: 'user', content: buildJudgePrompt(req.content, req.context) },\n ],\n jsonSchema: judgeOutputSchema(rubric),\n temperature: 0.0,\n maxTokens: 4_000,\n timeoutMs: 60_000,\n } satisfies LlmCallRequest\n const paid = await paidJsonChat<JudgeOutput>({\n chat: options.chat,\n request,\n ledger: options.costLedger ?? new CostLedger(),\n channel: 'judge',\n phase: options.costPhase ?? 'wire.judge',\n actor: `wire.${req.rubricName ?? 'inline'}`,\n ...(options.signal ? { signal: options.signal } : {}),\n ...(options.pricing ? { pricing: options.pricing } : {}),\n })\n if (!paid.succeeded) throw paid.error\n const { value, response } = paid\n\n const output = validateJudgeOutput(value, rubric)\n\n const composite = compositeScore(output.dimensions, rubric)\n const durationMs = Date.now() - startedAt\n\n return {\n composite,\n dimensions: output.dimensions,\n failureModes: output.failureModes ?? [],\n wins: output.wins ?? [],\n rationale: output.rationale,\n rubricVersion: hashRubric(rubric),\n model: response.model,\n durationMs,\n }\n}\n\n// ── listRubrics ─────────────────────────────────────────────────────\n\nexport function handleListRubrics(): ListRubricsResponse {\n return { rubrics: listBuiltinRubrics() }\n}\n\n// ── version ─────────────────────────────────────────────────────────\n\nexport function handleVersion(): VersionResponse {\n return {\n package: '@tangle-network/agent-eval',\n version: packageVersion(),\n wireVersion: WIRE_VERSION,\n apiSurface: ['judge', 'listRubrics', 'version', 'feedback.ingest', 'traces.ingest'],\n }\n}\n\n// ── Ingestion handlers ───────────────────────────────────────────────\n\n/**\n * Pluggable stores the wire layer routes ingestion writes into. Both\n * are optional — when omitted, the corresponding endpoint returns 503.\n *\n * Production deployments wire a `FileSystemTraceStore` and\n * `FileSystemFeedbackTrajectoryStore` here. Tests substitute in-memory\n * stores.\n */\nexport interface IngestionStores {\n traceStore?: TraceStore\n feedbackStore?: FeedbackTrajectoryStore\n}\n\n/**\n * `POST /v1/traces/ingest` — accept a batch of `TraceEvent`s from the\n * production runtime. Best-effort: each event is appended independently;\n * one bad event does not poison the batch.\n *\n * Idempotency: the underlying store is append-only; consumers retrying\n * the same payload will get duplicate events. Consumers should\n * de-duplicate by `eventId` downstream — production traces frequently\n * land via at-least-once buses (Kafka, SQS) where dedup is unavoidable.\n */\nexport async function handleTracesIngest(\n req: TracesIngestRequest,\n stores: IngestionStores,\n): Promise<TracesIngestResponse> {\n if (!stores.traceStore) {\n throw new WireError(\n 'service_unavailable',\n 'No trace store configured on this server. Pass `traceStore` to `createApp`.',\n 503,\n )\n }\n const errors: Array<{ eventId: string; message: string }> = []\n let accepted = 0\n for (const event of req.events) {\n try {\n // The wire `TraceEvent` is structurally identical to the internal one.\n await stores.traceStore.appendEvent(event as InternalTraceEvent)\n accepted++\n } catch (err) {\n errors.push({\n eventId: event.eventId,\n message: err instanceof Error ? err.message : String(err),\n })\n }\n }\n return { accepted, rejected: errors.length, errors }\n}\n\n/**\n * `POST /v1/feedback` — accept a single `WireFeedbackTrajectory` from the\n * production runtime. Idempotent on `id`: re-posting the same trajectory\n * replaces the prior record.\n */\nexport async function handleFeedbackIngest(\n req: WireFeedbackTrajectory,\n stores: IngestionStores,\n): Promise<FeedbackIngestResponse> {\n if (!stores.feedbackStore) {\n throw new WireError(\n 'service_unavailable',\n 'No feedback store configured on this server. Pass `feedbackStore` to `createApp`.',\n 503,\n )\n }\n // The wire `WireFeedbackTrajectory` aligns 1:1 with the internal type;\n // cast through `unknown` since the wire schema is a Zod-inferred\n // structural type with optional fields the internal store consumes.\n await stores.feedbackStore.save(req as unknown as Parameters<FeedbackTrajectoryStore['save']>[0])\n return { id: req.id, persisted: true }\n}\n","/**\n * stdio RPC transport.\n *\n * For batch / cron use without a running server. The Python client falls\n * back to this when no server is reachable.\n *\n * Protocol (line-delimited JSON over stdin/stdout):\n * IN: one JSON object on stdin: {\"method\":\"judge\",\"params\":{...}}\n * OUT: one JSON object on stdout: {\"result\":{...}} or {\"error\":{...}}\n *\n * One request per process invocation. To pipeline many calls, the client\n * writes JSONL to stdin and reads JSONL from stdout — see batch mode below.\n */\nimport type { ChatClient } from '../analyst/chat-client'\nimport { handleJudge, handleListRubrics, handleVersion, WireError } from './handlers'\nimport { JudgeRequestSchema } from './schemas'\n\ninterface RpcRequest {\n method: 'judge' | 'listRubrics' | 'version'\n params?: unknown\n}\n\ninterface RpcSuccess {\n result: unknown\n}\n\ninterface RpcError {\n error: { code: string; message: string; details?: unknown }\n}\n\nexport interface RpcOptions {\n /** Caller-owned transport for `/v1/judge`. Without it the method refuses. */\n chat?: ChatClient\n judgeModel?: string\n}\n\nexport async function dispatchRpc(\n req: RpcRequest,\n options: RpcOptions = {},\n): Promise<RpcSuccess | RpcError> {\n try {\n switch (req.method) {\n case 'judge': {\n const parsed = JudgeRequestSchema.safeParse(req.params)\n if (!parsed.success) {\n return {\n error: {\n code: 'validation_error',\n message: 'params did not match JudgeRequest schema.',\n details: parsed.error.issues,\n },\n }\n }\n return {\n result: await handleJudge(parsed.data, {\n chat: options.chat,\n defaultModel: options.judgeModel,\n }),\n }\n }\n case 'listRubrics':\n return { result: handleListRubrics() }\n case 'version':\n return { result: handleVersion() }\n default:\n return {\n error: {\n code: 'unknown_method',\n message: `No such method: ${(req as { method: string }).method}`,\n },\n }\n }\n } catch (err) {\n if (err instanceof WireError) {\n return { error: { code: err.code, message: err.message, details: err.details } }\n }\n const message = err instanceof Error ? err.message : String(err)\n return { error: { code: 'internal_error', message } }\n }\n}\n\n// ── stdin/stdout driver ─────────────────────────────────────────────\n\nasync function readAll(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = []\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as string))\n }\n return Buffer.concat(chunks).toString('utf-8')\n}\n\n/** Read one JSON request from stdin, write one JSON response to stdout. */\nexport async function runRpcOnce(method?: string, options: RpcOptions = {}): Promise<number> {\n const raw = await readAll(process.stdin)\n let req: RpcRequest\n try {\n const body = JSON.parse(raw)\n req = method ? { method: method as RpcRequest['method'], params: body } : (body as RpcRequest)\n } catch (err) {\n process.stdout.write(\n `${JSON.stringify({\n error: {\n code: 'parse_error',\n message: `stdin was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n })}\\n`,\n )\n return 1\n }\n const out = await dispatchRpc(req, options)\n process.stdout.write(`${JSON.stringify(out)}\\n`)\n return 'error' in out ? 1 : 0\n}\n\n/** Read JSONL requests from stdin, write JSONL responses to stdout. */\nexport async function runRpcBatch(method?: string, options: RpcOptions = {}): Promise<number> {\n const raw = await readAll(process.stdin)\n const lines = raw.split('\\n').filter((l) => l.trim().length > 0)\n let exitCode = 0\n for (const line of lines) {\n let req: RpcRequest\n try {\n const body = JSON.parse(line)\n req = method ? { method: method as RpcRequest['method'], params: body } : (body as RpcRequest)\n } catch (err) {\n process.stdout.write(\n `${JSON.stringify({\n error: {\n code: 'parse_error',\n message: `line was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n })}\\n`,\n )\n exitCode = 1\n continue\n }\n const out = await dispatchRpc(req, options)\n process.stdout.write(`${JSON.stringify(out)}\\n`)\n if ('error' in out) exitCode = 1\n }\n return exitCode\n}\n","/**\n * Build an OpenAPI spec from the wire schemas.\n *\n * The spec is the contract that other-language clients (Python, Rust,\n * Go, …) generate from. There is no hand-written client — clients are\n * derived artifacts of this file plus `schemas.ts`.\n *\n * Run `pnpm openapi` (defined in package.json) to write the spec to\n * `dist/openapi.json`. CI uses that file to regenerate the Python\n * client and gate the dual-publish workflow.\n */\nimport { OpenAPIRegistry, OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi'\nimport type { OpenAPIObject } from 'openapi3-ts/oas31'\n\nimport {\n ErrorResponseSchema,\n FeedbackIngestResponseSchema,\n FeedbackTrajectorySchema,\n HealthResponseSchema,\n JudgeRequestSchema,\n JudgeResultSchema,\n ListRubricsResponseSchema,\n TracesIngestRequestSchema,\n TracesIngestResponseSchema,\n VersionResponseSchema,\n WIRE_VERSION,\n} from './schemas'\n\nexport function buildOpenApi(packageVersion: string): OpenAPIObject {\n const registry = new OpenAPIRegistry()\n\n // Components — each schema becomes a $ref-able component\n registry.register('JudgeRequest', JudgeRequestSchema)\n registry.register('JudgeResult', JudgeResultSchema)\n registry.register('ListRubricsResponse', ListRubricsResponseSchema)\n registry.register('VersionResponse', VersionResponseSchema)\n registry.register('HealthResponse', HealthResponseSchema)\n registry.register('ErrorResponse', ErrorResponseSchema)\n registry.register('TracesIngestRequest', TracesIngestRequestSchema)\n registry.register('TracesIngestResponse', TracesIngestResponseSchema)\n registry.register('FeedbackTrajectory', FeedbackTrajectorySchema)\n registry.register('FeedbackIngestResponse', FeedbackIngestResponseSchema)\n\n // Routes\n registry.registerPath({\n method: 'post',\n path: '/v1/judge',\n summary: 'Score a piece of content against a rubric',\n description:\n 'Runs the judging LLM with the named (or inline) rubric and returns dimension scores, detected failure modes, wins, and a composite score in 0..1.',\n request: {\n body: {\n content: {\n 'application/json': { schema: JudgeRequestSchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Successful judgement',\n content: { 'application/json': { schema: JudgeResultSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 404: {\n description: 'Rubric not found',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 500: {\n description: 'Judge error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/v1/rubrics',\n summary: 'List built-in rubrics',\n description:\n 'Returns every rubric registered server-side, with their dimensions and stable rubricVersion hash.',\n responses: {\n 200: {\n description: 'Listing',\n content: { 'application/json': { schema: ListRubricsResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/v1/version',\n summary: 'Server and wire-protocol version',\n description: 'Match your client version to `version`; check `wireVersion` for compatibility.',\n responses: {\n 200: {\n description: 'Version info',\n content: { 'application/json': { schema: VersionResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'get',\n path: '/healthz',\n summary: 'Liveness check',\n responses: {\n 200: {\n description: 'OK',\n content: { 'application/json': { schema: HealthResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'post',\n path: '/v1/traces/ingest',\n summary: 'Ingest a batch of production TraceEvents',\n description:\n 'Append a batch of TraceEvents to the configured TraceStore. Accepts application/json ({events:[...]}) or application/x-ndjson (one event per line). Returns counts of accepted + rejected events.',\n request: {\n body: {\n content: {\n 'application/json': { schema: TracesIngestRequestSchema },\n 'application/x-ndjson': { schema: TracesIngestRequestSchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Ingestion summary',\n content: { 'application/json': { schema: TracesIngestResponseSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 401: {\n description: 'Unauthorized (when bearer auth is configured)',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 503: {\n description: 'No trace store configured',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n registry.registerPath({\n method: 'post',\n path: '/v1/feedback',\n summary: 'Ingest a FeedbackTrajectory from production',\n description:\n 'Persist a single FeedbackTrajectory. Idempotent on trajectory.id — re-posting replaces the prior record. Used by production runtimes to forward user 👍/👎/edits into the eval substrate.',\n request: {\n body: {\n content: {\n 'application/json': { schema: FeedbackTrajectorySchema },\n },\n },\n },\n responses: {\n 200: {\n description: 'Persisted',\n content: { 'application/json': { schema: FeedbackIngestResponseSchema } },\n },\n 400: {\n description: 'Validation error',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 401: {\n description: 'Unauthorized (when bearer auth is configured)',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n 503: {\n description: 'No feedback store configured',\n content: { 'application/json': { schema: ErrorResponseSchema } },\n },\n },\n })\n\n const generator = new OpenApiGeneratorV31(registry.definitions)\n const doc = generator.generateDocument({\n openapi: '3.1.0',\n info: {\n title: '@tangle-network/agent-eval — wire protocol',\n version: packageVersion,\n 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: ${WIRE_VERSION}. Bumps on breaking changes to request/response schemas.`,\n contact: { name: 'Tangle Network', url: 'https://github.com/tangle-network/agent-eval' },\n license: { name: 'MIT' },\n },\n servers: [{ url: 'http://localhost:5005', description: 'Local agent-eval serve' }],\n })\n const rubricRef = { $ref: '#/components/schemas/Rubric' } as const\n const commonJudgeFields = {\n content: { type: 'string', minLength: 1 },\n context: { type: 'object', additionalProperties: true },\n model: { type: 'string' },\n } as const\n doc.components ??= {}\n doc.components.schemas ??= {}\n doc.components.schemas.JudgeRequest = {\n oneOf: [\n {\n type: 'object',\n additionalProperties: false,\n required: ['rubricName', 'content'],\n properties: {\n rubricName: { type: 'string', minLength: 1 },\n ...commonJudgeFields,\n },\n },\n {\n type: 'object',\n additionalProperties: false,\n required: ['rubric', 'content'],\n properties: {\n rubric: rubricRef,\n ...commonJudgeFields,\n },\n },\n ],\n description: 'Judge request. Provide exactly one of rubricName or rubric.',\n }\n return doc\n}\n","/**\n * HTTP transport for the wire protocol.\n *\n * Hono + @hono/node-server. Every endpoint:\n * 1. Validates the request against its Zod schema.\n * 2. Calls the matching handler in `handlers.ts`.\n * 3. Renders 4xx for `WireError` with structured body, 500 for unexpected.\n *\n * The server holds optional `IngestionStores` (passed to `createApp`)\n * to receive production traces and user feedback. With no stores wired,\n * the ingestion endpoints return 503 — read endpoints (`/v1/judge`,\n * `/v1/rubrics`, `/v1/version`) remain fully functional.\n *\n * Run via `agent-eval serve --port 5005`.\n */\nimport { type ServerType, serve } from '@hono/node-server'\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\nimport type { ChatClient } from '../analyst/chat-client'\nimport {\n handleFeedbackIngest,\n handleJudge,\n handleListRubrics,\n handleTracesIngest,\n handleVersion,\n type IngestionStores,\n WireError,\n} from './handlers'\nimport { buildOpenApi } from './openapi'\nimport { FeedbackTrajectorySchema, JudgeRequestSchema, TracesIngestRequestSchema } from './schemas'\n\nconst STARTED_AT = Date.now()\n\ninterface CreateAppOptions {\n /** Stores wired to the ingestion endpoints. */\n stores?: IngestionStores\n /**\n * Caller-owned transport used by `/v1/judge`. agent-eval holds no provider\n * credential; without a client the endpoint refuses with\n * `llm_not_configured`.\n */\n chat?: ChatClient\n /** Default judge model when a request does not provide one. */\n judgeModel?: string\n /**\n * Bearer-token auth. When provided, every endpoint EXCEPT `/healthz`\n * and `/v1/version` requires `Authorization: Bearer <token>`. The\n * token may be a static string OR a function for time-bounded /\n * rotating tokens.\n *\n * Recommended for any server that accepts ingestion writes from the\n * public internet. Read-only deployments may omit it.\n */\n auth?: {\n bearer: string | ((token: string) => boolean | Promise<boolean>)\n }\n}\n\nconst AUTH_EXEMPT_PATHS = new Set(['/healthz', '/v1/version', '/openapi.json'])\n\nexport function createApp(opts: CreateAppOptions = {}) {\n const app = new Hono()\n\n app.use('*', cors())\n\n // Bearer-token middleware (only attached when configured).\n if (opts.auth) {\n const verify = opts.auth.bearer\n app.use('*', async (c, next) => {\n const path = new URL(c.req.url).pathname\n if (AUTH_EXEMPT_PATHS.has(path)) return next()\n const raw = c.req.header('authorization') ?? ''\n const match = raw.match(/^Bearer\\s+(.+)$/i)\n if (!match) {\n throw new WireError('unauthorized', 'Missing or malformed Authorization header.', 401)\n }\n const token = match[1] as string\n const ok = typeof verify === 'string' ? token === verify : await verify(token)\n if (!ok) {\n throw new WireError('unauthorized', 'Invalid bearer token.', 401)\n }\n return next()\n })\n }\n\n app.onError((err, c) => {\n if (err instanceof WireError) {\n const status = err.status as 400 | 401 | 404 | 422 | 500 | 503\n return c.json(\n { error: { code: err.code, message: err.message, details: err.details } },\n status,\n )\n }\n // Unexpected — log and return generic 500 without leaking internals.\n console.error('[agent-eval] unhandled error:', err)\n return c.json({ error: { code: 'internal_error', message: 'Internal server error.' } }, 500)\n })\n\n // ── Health ──\n app.get('/healthz', (c) =>\n c.json({ status: 'ok' as const, uptimeSec: (Date.now() - STARTED_AT) / 1000 }),\n )\n\n // ── Version ──\n app.get('/v1/version', (c) => c.json(handleVersion()))\n\n // ── Rubrics ──\n app.get('/v1/rubrics', (c) => c.json(handleListRubrics()))\n\n // ── Judge ──\n app.post('/v1/judge', async (c) => {\n const raw = await c.req.json().catch(() => null)\n if (raw == null) {\n throw new WireError('validation_error', 'Request body must be JSON.', 400)\n }\n const parsed = JudgeRequestSchema.safeParse(raw)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match JudgeRequest schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleJudge(parsed.data, {\n chat: opts.chat,\n defaultModel: opts.judgeModel,\n })\n return c.json(result)\n })\n\n // ── Traces ingest (NDJSON-friendly: accepts either {events:[...]} or NDJSON) ──\n app.post('/v1/traces/ingest', async (c) => {\n const contentType = c.req.header('content-type') ?? ''\n let payload: unknown\n if (contentType.includes('application/x-ndjson')) {\n const text = await c.req.text()\n const events = text\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n try {\n return JSON.parse(line)\n } catch {\n throw new WireError(\n 'validation_error',\n 'NDJSON line did not parse as JSON.',\n 400,\n line.slice(0, 200),\n )\n }\n })\n payload = { events }\n } else {\n payload = await c.req.json().catch(() => null)\n }\n if (payload == null) {\n throw new WireError('validation_error', 'Request body must be JSON or NDJSON.', 400)\n }\n const parsed = TracesIngestRequestSchema.safeParse(payload)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match TracesIngestRequest schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleTracesIngest(parsed.data, opts.stores ?? {})\n return c.json(result)\n })\n\n // ── Feedback ingest ──\n app.post('/v1/feedback', async (c) => {\n const raw = await c.req.json().catch(() => null)\n if (raw == null) {\n throw new WireError('validation_error', 'Request body must be JSON.', 400)\n }\n const parsed = FeedbackTrajectorySchema.safeParse(raw)\n if (!parsed.success) {\n throw new WireError(\n 'validation_error',\n 'Request did not match FeedbackTrajectory schema.',\n 400,\n parsed.error.issues,\n )\n }\n const result = await handleFeedbackIngest(parsed.data, opts.stores ?? {})\n return c.json(result)\n })\n\n // ── OpenAPI spec ──\n app.get('/openapi.json', (c) => c.json(buildOpenApi(handleVersion().version)))\n\n return app\n}\n\nexport interface ServeOptions extends CreateAppOptions {\n /** Default 5005. */\n port?: number\n /** Default '127.0.0.1'. Set to '0.0.0.0' to listen on all interfaces. */\n host?: string\n}\n\nexport function startServer(opts: ServeOptions = {}): ServerType {\n const app = createApp(opts)\n const port = opts.port ?? 5005\n const host = opts.host ?? '127.0.0.1'\n return serve({ fetch: app.fetch, port, hostname: host }, ({ address, port: actualPort }) => {\n // eslint-disable-next-line no-console\n console.log(`[agent-eval] serving on http://${address}:${actualPort}`)\n })\n}\n\nexport interface StartedServer {\n server: ServerType\n /** The OS-assigned port. When opts.port was 0, this is the actual port the\n * kernel bound — callers that need to dial back (smoke tests, sidecars\n * registering with a parent) read this rather than guessing a free port. */\n port: number\n /** Resolved host the server bound to (defaults to 127.0.0.1). */\n host: string\n /** Close the server. Resolves once active connections have drained. */\n close(): Promise<void>\n}\n\n/**\n * Promise-returning variant of `startServer` that resolves once the server is\n * listening and surfaces the resolved bound port. Use this from smoke tests\n * (`startServerAsync({ port: 0 })`) and any caller that needs to dial back.\n */\nexport function startServerAsync(opts: ServeOptions = {}): Promise<StartedServer> {\n const app = createApp(opts)\n const port = opts.port ?? 5005\n const host = opts.host ?? '127.0.0.1'\n return new Promise((resolve, reject) => {\n let settled = false\n let server: ServerType | undefined\n server = serve({ fetch: app.fetch, port, hostname: host }, ({ address, port: actualPort }) => {\n if (settled) return\n settled = true\n // eslint-disable-next-line no-console\n console.log(`[agent-eval] serving on http://${address}:${actualPort}`)\n resolve({\n server: server!,\n port: actualPort,\n host: address,\n close: () =>\n new Promise<void>((res, rej) => {\n server!.close((err) => (err ? rej(err) : res()))\n }),\n })\n })\n server.on('error', (err) => {\n if (settled) return\n settled = true\n reject(err)\n })\n })\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-groups-R5RO9OHn.d.ts","names":[],"sources":["../src/analyst/tool-groups.ts"],"mappings":";;;KAmBY;;;;;;;;;;;;;;;;;;;;iBAyDI,wBACd,OAAO,oBACP,OAAO,qBACN"}
|