@tangle-network/agent-eval 0.144.11 → 0.144.13
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 +11 -0
- package/dist/agent-profile-B9_GGsG8.d.ts +84 -0
- package/dist/agent-profile-B9_GGsG8.d.ts.map +1 -0
- package/dist/{agent-profile-cell-BOP-iA9Q.d.ts → agent-profile-cell-BkcRDikH.d.ts} +2 -2
- package/dist/{agent-profile-cell-BOP-iA9Q.d.ts.map → agent-profile-cell-BkcRDikH.d.ts.map} +1 -1
- package/dist/analyst/index.d.ts +134 -16
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +364 -10
- package/dist/analyst/index.js.map +1 -1
- package/dist/backend-integrity-CsVin_Wb.d.ts +280 -0
- package/dist/backend-integrity-CsVin_Wb.d.ts.map +1 -0
- package/dist/{baseline-C-GocmIW.js → baseline-BhPRQBVn.js} +3 -2
- package/dist/{baseline-C-GocmIW.js.map → baseline-BhPRQBVn.js.map} +1 -1
- package/dist/{benchmark-CWeqGl7x.js → benchmark-BhT16ep9.js} +2 -2
- package/dist/{benchmark-CWeqGl7x.js.map → benchmark-BhT16ep9.js.map} +1 -1
- package/dist/{agent-profile-DPi7IZg7.d.ts → benchmark-Ceoan7vk.d.ts} +4 -91
- package/dist/benchmark-Ceoan7vk.d.ts.map +1 -0
- package/dist/{benchmark-command-BteMFN62.js → benchmark-command-CY6cbhOB.js} +36 -79
- package/dist/benchmark-command-CY6cbhOB.js.map +1 -0
- package/dist/benchmarks/index.d.ts +244 -2
- package/dist/benchmarks/index.d.ts.map +1 -0
- package/dist/benchmarks/index.js +733 -1
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/builder-eval/index.d.ts +23 -2
- package/dist/builder-eval/index.d.ts.map +1 -1
- package/dist/builder-eval/index.js +227 -3
- package/dist/builder-eval/index.js.map +1 -1
- package/dist/campaign/index.d.ts +10 -8
- package/dist/campaign/index.js +9 -6
- package/dist/{campaign-C2TTzQII.js → campaign-BYjBAypg.js} +21 -634
- package/dist/campaign-BYjBAypg.js.map +1 -0
- package/dist/{canonical-D011XM8r.js → canonical-D-XsTQ6_.js} +2 -2
- package/dist/{canonical-D011XM8r.js.map → canonical-D-XsTQ6_.js.map} +1 -1
- package/dist/{index-CQTZ-4XN.d.ts → capture-fetch-DDvpjVRU.d.ts} +3 -3
- package/dist/capture-fetch-DDvpjVRU.d.ts.map +1 -0
- package/dist/{default-registry-BmktKy8r.js → chat-client-Bp4Ebuuc.js} +1276 -1276
- package/dist/chat-client-Bp4Ebuuc.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{client-C9gzZE59.d.ts → client-KUbGulm_.d.ts} +4 -4
- package/dist/{client-C9gzZE59.d.ts.map → client-KUbGulm_.d.ts.map} +1 -1
- package/dist/contract/index.d.ts +13 -390
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +18 -542
- package/dist/contract/index.js.map +1 -1
- package/dist/{cost-ledger-DMFxsLKr.js → cost-ledger-BSe92yAV.js} +3 -3
- package/dist/{cost-ledger-DMFxsLKr.js.map → cost-ledger-BSe92yAV.js.map} +1 -1
- package/dist/{cost-ledger-Bv_e8XHY.d.ts → cost-ledger-DbQdN3nO.d.ts} +2 -2
- package/dist/{cost-ledger-Bv_e8XHY.d.ts.map → cost-ledger-DbQdN3nO.d.ts.map} +1 -1
- package/dist/{counterfactual-CxmxAONP.d.ts → counterfactual--bpysZF0.d.ts} +2 -14
- package/dist/{counterfactual-CxmxAONP.d.ts.map → counterfactual--bpysZF0.d.ts.map} +1 -1
- package/dist/{counterfactual-CWPTrMH7.js → counterfactual-lDfCx0Uz.js} +3 -31
- package/dist/{counterfactual-CWPTrMH7.js.map → counterfactual-lDfCx0Uz.js.map} +1 -1
- package/dist/{dataset-C8xaLXdY.d.ts → dataset-CJjKqQfA.d.ts} +2 -8
- package/dist/dataset-CJjKqQfA.d.ts.map +1 -0
- package/dist/{default-registry-Bf8Woqmq.d.ts → default-registry-Di6HP6pG.d.ts} +7 -12
- package/dist/default-registry-Di6HP6pG.d.ts.map +1 -0
- package/dist/{analyze-runs-C30yljDJ.js → define-agent-eval-iqjT--ZZ.js} +542 -130
- package/dist/define-agent-eval-iqjT--ZZ.js.map +1 -0
- package/dist/define-agent-eval-sH24zBfM.d.ts +388 -0
- package/dist/define-agent-eval-sH24zBfM.d.ts.map +1 -0
- package/dist/descriptive-B5MwKfbf.js +144 -0
- package/dist/descriptive-B5MwKfbf.js.map +1 -0
- package/dist/{dspy-rlm-engine-DbTk4JdR.js → dspy-rlm-engine-B_qhSc21.js} +4 -4
- package/dist/{dspy-rlm-engine-DbTk4JdR.js.map → dspy-rlm-engine-B_qhSc21.js.map} +1 -1
- package/dist/effect-sizes-DiH8MGOH.js +82 -0
- package/dist/effect-sizes-DiH8MGOH.js.map +1 -0
- package/dist/{engine-3hL-XqwJ.d.ts → engine-otFpE2gF.d.ts} +10 -38
- package/dist/engine-otFpE2gF.d.ts.map +1 -0
- package/dist/{errors-CKPfb2aH.d.ts → errors-DEE6u6ot.d.ts} +2 -14
- package/dist/{errors-CKPfb2aH.d.ts.map → errors-DEE6u6ot.d.ts.map} +1 -1
- package/dist/{errors-D-LKuDhb.js → errors-Dngq5h35.js} +2 -8
- package/dist/{errors-D-LKuDhb.js.map → errors-Dngq5h35.js.map} +1 -1
- package/dist/{eval-campaign-B_7wcnav.js → eval-campaign-UB-usSQ2.js} +6 -6
- package/dist/{eval-campaign-B_7wcnav.js.map → eval-campaign-UB-usSQ2.js.map} +1 -1
- package/dist/{exact-types-DSFFpLLI.d.ts → exact-types-BH1twmAJ.d.ts} +2 -2
- package/dist/{exact-types-DSFFpLLI.d.ts.map → exact-types-BH1twmAJ.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +9 -6
- package/dist/experiment/index.d.ts.map +1 -1
- package/dist/experiment/index.js +11 -7
- package/dist/experiment/index.js.map +1 -1
- package/dist/experiment-tracker-C29gXM4B.js +269 -0
- package/dist/experiment-tracker-C29gXM4B.js.map +1 -0
- package/dist/{experiment-tracker-IMntXr6J.d.ts → experiment-tracker-DWHZBAYL.d.ts} +77 -121
- package/dist/experiment-tracker-DWHZBAYL.d.ts.map +1 -0
- package/dist/{external-optimizer-contracts-CZuJNcT5.d.ts → external-optimizer-contracts-lixrOZdX.d.ts} +3 -3
- package/dist/{external-optimizer-contracts-CZuJNcT5.d.ts.map → external-optimizer-contracts-lixrOZdX.d.ts.map} +1 -1
- package/dist/external-optimizer-process-BTiNB-RH.js +301 -0
- package/dist/external-optimizer-process-BTiNB-RH.js.map +1 -0
- package/dist/{single-run-lock-DFWHEB09.js → external-optimizer-subprocess-DrJ9hR8u.js} +144 -438
- package/dist/external-optimizer-subprocess-DrJ9hR8u.js.map +1 -0
- package/dist/extract-usage-BrQ8mCLX.js +155 -0
- package/dist/extract-usage-BrQ8mCLX.js.map +1 -0
- package/dist/{failure-cluster-CqcvCcdR.d.ts → failure-cluster-BLURuWG4.d.ts} +2 -3
- package/dist/failure-cluster-BLURuWG4.d.ts.map +1 -0
- package/dist/{feedback-trajectory-CacHpxsp.d.ts → feedback-trajectory-juOozjAc.d.ts} +5 -36
- package/dist/feedback-trajectory-juOozjAc.d.ts.map +1 -0
- package/dist/fuzz.d.ts +2 -2
- package/dist/fuzz.js +2 -2
- package/dist/hosted/index.d.ts +3 -3
- package/dist/{index-CvSN3IG1.d.ts → index-B8Ui1mr1.d.ts} +2 -2
- package/dist/{index-CvSN3IG1.d.ts.map → index-B8Ui1mr1.d.ts.map} +1 -1
- package/dist/{skill-usage-CO9OLRBx.d.ts → index-BWDrSVfw.d.ts} +11 -136
- package/dist/index-BWDrSVfw.d.ts.map +1 -0
- package/dist/index-Ba3YrbAL.d.ts +1 -0
- package/dist/{index-BnEuDAK2.d.ts → index-COQYtuRF.d.ts} +3 -3
- package/dist/{index-BnEuDAK2.d.ts.map → index-COQYtuRF.d.ts.map} +1 -1
- package/dist/{index-C3ssXVLv.d.ts → index-CvjYbU0D.d.ts} +2 -2
- package/dist/{index-C3ssXVLv.d.ts.map → index-CvjYbU0D.d.ts.map} +1 -1
- package/dist/{index-DPPGNJ_R.d.ts → index-DSmEylT9.d.ts} +17 -115
- package/dist/index-DSmEylT9.d.ts.map +1 -0
- package/dist/index.d.ts +2397 -5308
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5914 -10496
- package/dist/index.js.map +1 -1
- package/dist/{insight-report-CgX_s0Ez.d.ts → insight-report-CRi-Ufrj.d.ts} +4 -4
- package/dist/{insight-report-CgX_s0Ez.d.ts.map → insight-report-CRi-Ufrj.d.ts.map} +1 -1
- package/dist/{integrity-MLzHOfV9.js → integrity-Cy9WHAtb.js} +2 -2
- package/dist/{integrity-MLzHOfV9.js.map → integrity-Cy9WHAtb.js.map} +1 -1
- package/dist/{integrity-DY6tIbl0.js → integrity-DysDBWDu.js} +2 -2
- package/dist/{integrity-DY6tIbl0.js.map → integrity-DysDBWDu.js.map} +1 -1
- package/dist/{integrity-BuqEKu-x.d.ts → integrity-OrcI9Nau.d.ts} +3 -3
- package/dist/{integrity-BuqEKu-x.d.ts.map → integrity-OrcI9Nau.d.ts.map} +1 -1
- package/dist/internal-BDHPCnjk.js +230 -0
- package/dist/internal-BDHPCnjk.js.map +1 -0
- package/dist/judge-calibration-C5CbMYce.d.ts +117 -0
- package/dist/judge-calibration-C5CbMYce.d.ts.map +1 -0
- package/dist/judge-calibration-DZkWrm5H.js +317 -0
- package/dist/judge-calibration-DZkWrm5H.js.map +1 -0
- package/dist/{kind-factory-B8-r8-y8.js → kind-factory-CPmSd58s.js} +208 -208
- package/dist/{kind-factory-B8-r8-y8.js.map → kind-factory-CPmSd58s.js.map} +1 -1
- package/dist/ledger-core/index.d.ts +1 -1
- package/dist/ledger-core/index.js +2 -2
- package/dist/{ledger-core-DXZIqu17.js → ledger-core-BmZt19oQ.js} +110 -110
- package/dist/{ledger-core-DXZIqu17.js.map → ledger-core-BmZt19oQ.js.map} +1 -1
- package/dist/{llm-client-DzvMUsS_.js → llm-client-d0-2TT1g.js} +4 -64
- package/dist/{llm-client-DzvMUsS_.js.map → llm-client-d0-2TT1g.js.map} +1 -1
- package/dist/{skillopt-optimization-method-CQdVeM8k.js → llm-judge-dZ8P6nGI.js} +3349 -5401
- package/dist/llm-judge-dZ8P6nGI.js.map +1 -0
- package/dist/matrix/index.d.ts +2 -2
- package/dist/meta-eval/index.d.ts +3 -3
- package/dist/meta-eval/index.js +3 -3
- package/dist/{metrics-C9YY1OcL.js → metrics-Cl0L1KUy.js} +2 -108
- package/dist/{metrics-C9YY1OcL.js.map → metrics-Cl0L1KUy.js.map} +1 -1
- package/dist/{mint-B2O60ACG.js → mint-Dj9Ww_3I.js} +4 -4
- package/dist/{mint-B2O60ACG.js.map → mint-Dj9Ww_3I.js.map} +1 -1
- package/dist/{multi-layer-verifier-DnAqwl0h.d.ts → multi-layer-verifier-DIguZc8Z.d.ts} +3 -3
- package/dist/{multi-layer-verifier-DnAqwl0h.d.ts.map → multi-layer-verifier-DIguZc8Z.d.ts.map} +1 -1
- package/dist/multiplicity-DIWHvysC.d.ts +43 -0
- package/dist/multiplicity-DIWHvysC.d.ts.map +1 -0
- package/dist/multishot/index.d.ts +3 -3
- package/dist/multishot/index.js +1 -1
- package/dist/openapi.json +1 -1
- package/dist/{opencode-sqlite-8r6WUfHc.js → opencode-sqlite-DJWAXLms.js} +2 -2
- package/dist/{opencode-sqlite-8r6WUfHc.js.map → opencode-sqlite-DJWAXLms.js.map} +1 -1
- package/dist/package-version-D7lQHt_-.js +34 -0
- package/dist/package-version-D7lQHt_-.js.map +1 -0
- package/dist/paired-arms-D-XRF_fy.js +1045 -0
- package/dist/paired-arms-D-XRF_fy.js.map +1 -0
- package/dist/paired-promotion-decision-CGzg0cI_.d.ts +251 -0
- package/dist/paired-promotion-decision-CGzg0cI_.d.ts.map +1 -0
- package/dist/paired-tests-BHIhYVdu.js +213 -0
- package/dist/paired-tests-BHIhYVdu.js.map +1 -0
- package/dist/pareto-BqNW3LJR.d.ts +117 -0
- package/dist/pareto-BqNW3LJR.d.ts.map +1 -0
- package/dist/pipelines/index.d.ts +3 -64
- package/dist/pipelines/index.d.ts.map +1 -1
- package/dist/pipelines/index.js +4 -284
- package/dist/pipelines/index.js.map +1 -1
- package/dist/power-and-mde-CHIrXJll.js +195 -0
- package/dist/power-and-mde-CHIrXJll.js.map +1 -0
- package/dist/{promotion-policy-CrLrmys8.js → power-preflight-DEw-uC7q.js} +4 -184
- package/dist/power-preflight-DEw-uC7q.js.map +1 -0
- package/dist/pre-registration-CZwSFQS4.d.ts +577 -0
- package/dist/pre-registration-CZwSFQS4.d.ts.map +1 -0
- package/dist/{prime-protocol-BfSalTfR.js → prime-protocol-6tZTVsWm.js} +72 -21
- package/dist/prime-protocol-6tZTVsWm.js.map +1 -0
- package/dist/produced-state-DU79a81m.js +586 -0
- package/dist/produced-state-DU79a81m.js.map +1 -0
- package/dist/profile-cell.d.ts +1 -1
- package/dist/profile-cell.js +1 -1
- package/dist/promotion-policy-D0nPhkSy.d.ts +134 -0
- package/dist/promotion-policy-D0nPhkSy.d.ts.map +1 -0
- package/dist/promotion-policy-xzA40Evo.js +186 -0
- package/dist/promotion-policy-xzA40Evo.js.map +1 -0
- package/dist/{skillopt-optimization-method-USDKhxSA.d.ts → provenance-CCdxgLDT.d.ts} +57 -478
- package/dist/provenance-CCdxgLDT.d.ts.map +1 -0
- package/dist/registry-oJeeI4-a.d.ts +178 -0
- package/dist/registry-oJeeI4-a.d.ts.map +1 -0
- package/dist/{release-report-DA2BCu5a.d.ts → release-confidence-BFRE5WSp.d.ts} +180 -112
- package/dist/release-confidence-BFRE5WSp.d.ts.map +1 -0
- package/dist/{release-report-BUYmoKo2.js → release-confidence-CxDuiAev.js} +125 -217
- package/dist/release-confidence-CxDuiAev.js.map +1 -0
- package/dist/reporting.d.ts +6 -5
- package/dist/reporting.js +7 -5
- package/dist/{researcher-BchpD55R.d.ts → researcher-DaN4GST-.d.ts} +7 -40
- package/dist/{researcher-BchpD55R.d.ts.map → researcher-DaN4GST-.d.ts.map} +1 -1
- package/dist/{reward-hacking-BDToousL.js → reward-hacking-DNgjilrV.js} +3 -3
- package/dist/reward-hacking-DNgjilrV.js.map +1 -0
- package/dist/{reward-hacking-BI0OMAlo.d.ts → reward-hacking-DSSTuI9r.d.ts} +5 -5
- package/dist/{reward-hacking-BI0OMAlo.d.ts.map → reward-hacking-DSSTuI9r.d.ts.map} +1 -1
- package/dist/rl.d.ts +7 -7
- package/dist/rl.js +11 -10
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +2 -2
- package/dist/rollout/index.js +4 -4
- package/dist/{rollout-DRrksrcV.js → rollout-BWtw0I_6.js} +3 -3
- package/dist/{rollout-DRrksrcV.js.map → rollout-BWtw0I_6.js.map} +1 -1
- package/dist/{rubric-predictive-validity-DvkjPYCe.d.ts → rubric-predictive-validity-BgxtKe4G.d.ts} +2 -2
- package/dist/{rubric-predictive-validity-DvkjPYCe.d.ts.map → rubric-predictive-validity-BgxtKe4G.d.ts.map} +1 -1
- package/dist/{rubric-predictive-validity-BRR632r1.js → rubric-predictive-validity-Cwwyd7ah.js} +2 -2
- package/dist/{rubric-predictive-validity-BRR632r1.js.map → rubric-predictive-validity-Cwwyd7ah.js.map} +1 -1
- package/dist/{run-record-BmSPWXJR.js → run-record-BvHPVS-i.js} +3 -3
- package/dist/{run-record-BmSPWXJR.js.map → run-record-BvHPVS-i.js.map} +1 -1
- package/dist/{run-record-CF4Dwpxr.d.ts → run-record-CKiihE6f.d.ts} +4 -4
- package/dist/{run-record-CF4Dwpxr.d.ts.map → run-record-CKiihE6f.d.ts.map} +1 -1
- package/dist/{proposal-findings-2GIUo1et.js → run-score-lDzV0X8j.js} +31 -31
- package/dist/run-score-lDzV0X8j.js.map +1 -0
- package/dist/sandbox-harness-BlSOu4LX.d.ts +70 -0
- package/dist/sandbox-harness-BlSOu4LX.d.ts.map +1 -0
- package/dist/{schema-Cef2cFmb2.d.ts → schema-Cef2cFmb.d.ts} +1 -1
- package/dist/schema-Cef2cFmb.d.ts.map +1 -0
- package/dist/semantic-concept-judge-BiJxScqe.js +406 -0
- package/dist/semantic-concept-judge-BiJxScqe.js.map +1 -0
- package/dist/{sequential-D-BLJBKU.js → sequential-C458DXNf.js} +4 -3
- package/dist/{sequential-D-BLJBKU.js.map → sequential-C458DXNf.js.map} +1 -1
- package/dist/sequential-eprocess-CbUt2htw.js +83 -0
- package/dist/sequential-eprocess-CbUt2htw.js.map +1 -0
- package/dist/series-convergence-D1cL1f-4.d.ts +129 -0
- package/dist/series-convergence-D1cL1f-4.d.ts.map +1 -0
- package/dist/{server-iu0ede49.js → server-ulsOdrTI.js} +5 -21
- package/dist/server-ulsOdrTI.js.map +1 -0
- package/dist/skillopt-optimization-method-C5cotF4E.d.ts +427 -0
- package/dist/skillopt-optimization-method-C5cotF4E.d.ts.map +1 -0
- package/dist/skillopt-optimization-method-jjdnc3YK.js +1999 -0
- package/dist/skillopt-optimization-method-jjdnc3YK.js.map +1 -0
- package/dist/{statistical-heldout-TQ-4CYiN.d.ts → statistical-heldout-DoFF5KJX.d.ts} +5 -278
- package/dist/statistical-heldout-DoFF5KJX.d.ts.map +1 -0
- package/dist/{store-otlp-Dw8PPIlL.js → store-otlp-CsptLYpN.js} +3 -3
- package/dist/{store-otlp-Dw8PPIlL.js.map → store-otlp-CsptLYpN.js.map} +1 -1
- package/dist/store-tool-spans-Cq9mFd-q.js +667 -0
- package/dist/store-tool-spans-Cq9mFd-q.js.map +1 -0
- package/dist/store-tool-spans-DbDLOBOb.d.ts +342 -0
- package/dist/store-tool-spans-DbDLOBOb.d.ts.map +1 -0
- package/dist/student-t-CvBq2mve.js +38 -0
- package/dist/student-t-CvBq2mve.js.map +1 -0
- package/dist/{summary-report-Lf-5I7xh.js → summary-report-Blysd6Z2.js} +6 -3
- package/dist/{summary-report-Lf-5I7xh.js.map → summary-report-Blysd6Z2.js.map} +1 -1
- package/dist/{summary-report-BNR7DWTj.d.ts → summary-report-CaL-Hnxt.d.ts} +5 -5
- package/dist/{summary-report-BNR7DWTj.d.ts.map → summary-report-CaL-Hnxt.d.ts.map} +1 -1
- package/dist/supervisor-run/index.d.ts +391 -3
- package/dist/supervisor-run/index.d.ts.map +1 -0
- package/dist/supervisor-run/index.js +1689 -2
- package/dist/{supervisor-run-D_sokXcO.js.map → supervisor-run/index.js.map} +1 -1
- package/dist/{extract-usage-CdZdoj1s.js → task-failure-attributes-CpQ4y5RD.js} +5 -157
- package/dist/task-failure-attributes-CpQ4y5RD.js.map +1 -0
- package/dist/{tool-groups-CZPGGlHf.d.ts → tool-groups-Cteb03Ps.d.ts} +3 -3
- package/dist/tool-groups-Cteb03Ps.d.ts.map +1 -0
- package/dist/tool-waste-BDdBZG1F.js +803 -0
- package/dist/tool-waste-BDdBZG1F.js.map +1 -0
- package/dist/tool-waste-DjRDEsuI.d.ts +128 -0
- package/dist/tool-waste-DjRDEsuI.d.ts.map +1 -0
- package/dist/trace-repair/index.d.ts +14 -5
- package/dist/trace-repair/index.d.ts.map +1 -1
- package/dist/trace-repair/index.js +35 -7
- package/dist/trace-repair/index.js.map +1 -1
- package/dist/traces.d.ts +406 -7
- package/dist/traces.d.ts.map +1 -0
- package/dist/traces.js +1011 -10
- package/dist/traces.js.map +1 -0
- package/dist/trajectory-replay/index.d.ts +16 -3
- package/dist/trajectory-replay/index.d.ts.map +1 -1
- package/dist/trajectory-replay/index.js +52 -5
- package/dist/trajectory-replay/index.js.map +1 -1
- package/dist/types-BEPZc6eo.d.ts +93 -0
- package/dist/types-BEPZc6eo.d.ts.map +1 -0
- package/dist/{usage-receipt-t7vAzCRQ.js → types-BI4fT3HN.js} +67 -67
- package/dist/types-BI4fT3HN.js.map +1 -0
- package/dist/{types-BnjdJ70P.d.ts → types-BZ59Ahr8.d.ts} +5 -5
- package/dist/{types-BnjdJ70P.d.ts.map → types-BZ59Ahr8.d.ts.map} +1 -1
- package/dist/{types-D216SgwM.d.ts → types-Cx3YUh2r.d.ts} +4 -241
- package/dist/types-Cx3YUh2r.d.ts.map +1 -0
- package/dist/{types-BvDKaULh.d.ts → types-DLQx4mKU.d.ts} +4 -4
- package/dist/{types-BvDKaULh.d.ts.map → types-DLQx4mKU.d.ts.map} +1 -1
- package/dist/{types-D4mog56g.d.ts → types-yLK8gXE9.d.ts} +2 -2
- package/dist/{types-D4mog56g.d.ts.map → types-yLK8gXE9.d.ts.map} +1 -1
- package/dist/verdict-BndeTAh_.js +61 -0
- package/dist/verdict-BndeTAh_.js.map +1 -0
- package/dist/verdict-E4eRNf7-.d.ts +392 -0
- package/dist/verdict-E4eRNf7-.d.ts.map +1 -0
- package/dist/{verdict-cache-BCcOh0kF.js → verdict-cache-mZf5FEiY.js} +3 -55
- package/dist/{verdict-cache-BCcOh0kF.js.map → verdict-cache-mZf5FEiY.js.map} +1 -1
- package/dist/wire/index.d.ts +3 -3
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +1 -1
- package/docs/charter.md +3 -3
- package/docs/control-runtime.md +3 -42
- package/docs/experiment.md +0 -1
- package/docs/feature-guide.md +2 -2
- package/docs/trace-repair-grader.md +1 -0
- package/docs/trajectory-replay.md +1 -0
- package/docs/verdicts.md +43 -0
- package/docs/verification-strategies.md +3 -2
- package/package.json +6 -11
- package/dist/agent-profile-DPi7IZg7.d.ts.map +0 -1
- package/dist/analyze-runs-C30yljDJ.js.map +0 -1
- package/dist/baseline-CavEbRyH.d.ts +0 -136
- package/dist/baseline-CavEbRyH.d.ts.map +0 -1
- package/dist/benchmark-command-BteMFN62.js.map +0 -1
- package/dist/benchmarks-Dzs8CKb1.js +0 -755
- package/dist/benchmarks-Dzs8CKb1.js.map +0 -1
- package/dist/campaign-C2TTzQII.js.map +0 -1
- package/dist/completion-verifier-DJA5BhPb.d.ts +0 -414
- package/dist/completion-verifier-DJA5BhPb.d.ts.map +0 -1
- package/dist/control.d.ts +0 -3
- package/dist/control.js +0 -2
- package/dist/dataset-C8xaLXdY.d.ts.map +0 -1
- package/dist/default-registry-Bf8Woqmq.d.ts.map +0 -1
- package/dist/default-registry-BmktKy8r.js.map +0 -1
- package/dist/engine-3hL-XqwJ.d.ts.map +0 -1
- package/dist/experiment-tracker-CnRICnMl.js +0 -500
- package/dist/experiment-tracker-CnRICnMl.js.map +0 -1
- package/dist/experiment-tracker-IMntXr6J.d.ts.map +0 -1
- package/dist/extract-usage-CdZdoj1s.js.map +0 -1
- package/dist/failure-cluster-CqcvCcdR.d.ts.map +0 -1
- package/dist/feedback-trajectory-CacHpxsp.d.ts.map +0 -1
- package/dist/index-BZ3-y4YL.d.ts +0 -391
- package/dist/index-BZ3-y4YL.d.ts.map +0 -1
- package/dist/index-CQTZ-4XN.d.ts.map +0 -1
- package/dist/index-DPPGNJ_R.d.ts.map +0 -1
- package/dist/index-YE4KdKbO2.d.ts +0 -335
- package/dist/index-YE4KdKbO2.d.ts.map +0 -1
- package/dist/paired-arms-iZ08VFMN.js +0 -260
- package/dist/paired-arms-iZ08VFMN.js.map +0 -1
- package/dist/paired-promotion-decision-B6zJ3gYM.d.ts +0 -114
- package/dist/paired-promotion-decision-B6zJ3gYM.d.ts.map +0 -1
- package/dist/prime-protocol-BfSalTfR.js.map +0 -1
- package/dist/promotion-policy-Ckjhzg_4.d.ts +0 -289
- package/dist/promotion-policy-Ckjhzg_4.d.ts.map +0 -1
- package/dist/promotion-policy-CrLrmys8.js.map +0 -1
- package/dist/proposal-findings-2GIUo1et.js.map +0 -1
- package/dist/propose-review-control-dSNPjFUH.js +0 -1458
- package/dist/propose-review-control-dSNPjFUH.js.map +0 -1
- package/dist/release-report-BUYmoKo2.js.map +0 -1
- package/dist/release-report-DA2BCu5a.d.ts.map +0 -1
- package/dist/replay-CohS93nE.js +0 -1859
- package/dist/replay-CohS93nE.js.map +0 -1
- package/dist/replay-DbhZ4Ked.d.ts +0 -834
- package/dist/replay-DbhZ4Ked.d.ts.map +0 -1
- package/dist/reward-hacking-BDToousL.js.map +0 -1
- package/dist/run-evidence-Dhi3C81V.d.ts +0 -225
- package/dist/run-evidence-Dhi3C81V.d.ts.map +0 -1
- package/dist/schema-Cef2cFmb2.d.ts.map +0 -1
- package/dist/semantic-concept-judge-D1z-KepS.js +0 -767
- package/dist/semantic-concept-judge-D1z-KepS.js.map +0 -1
- package/dist/series-convergence-ofsqPWhs.d.ts +0 -35
- package/dist/series-convergence-ofsqPWhs.d.ts.map +0 -1
- package/dist/server-iu0ede49.js.map +0 -1
- package/dist/single-run-lock-DFWHEB09.js.map +0 -1
- package/dist/skill-usage-CO9OLRBx.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-CQdVeM8k.js.map +0 -1
- package/dist/skillopt-optimization-method-USDKhxSA.d.ts.map +0 -1
- package/dist/statistical-heldout-TQ-4CYiN.d.ts.map +0 -1
- package/dist/statistics-ByxzSiOM.js +0 -2212
- package/dist/statistics-ByxzSiOM.js.map +0 -1
- package/dist/statistics-D6Uebe_4.d.ts +0 -968
- package/dist/statistics-D6Uebe_4.d.ts.map +0 -1
- package/dist/supervisor-run-D_sokXcO.js +0 -1690
- package/dist/test-graded-scenario-D1TaI2va.d.ts +0 -141
- package/dist/test-graded-scenario-D1TaI2va.d.ts.map +0 -1
- package/dist/test-graded-scenario-JHcKQNpq.js +0 -318
- package/dist/test-graded-scenario-JHcKQNpq.js.map +0 -1
- package/dist/tool-groups-CZPGGlHf.d.ts.map +0 -1
- package/dist/tool-use-metrics-DEGMKycK.js +0 -370
- package/dist/tool-use-metrics-DEGMKycK.js.map +0 -1
- package/dist/types-D216SgwM.d.ts.map +0 -1
- package/dist/usage-receipt-t7vAzCRQ.js.map +0 -1
- package/dist/verdict-DExhxfgR.d.ts +0 -201
- package/dist/verdict-DExhxfgR.d.ts.map +0 -1
|
@@ -1,500 +0,0 @@
|
|
|
1
|
-
import { c as ValidationError } from "./errors-D-LKuDhb.js";
|
|
2
|
-
import { C as mulberry32 } from "./statistics-ByxzSiOM.js";
|
|
3
|
-
import { n as pairArms } from "./paired-arms-iZ08VFMN.js";
|
|
4
|
-
import { n as iqr } from "./baseline-C-GocmIW.js";
|
|
5
|
-
import { execSync } from "node:child_process";
|
|
6
|
-
//#region src/clustered-paired-binary.ts
|
|
7
|
-
/**
|
|
8
|
-
* Paired binary comparison for work items nested inside independent clusters.
|
|
9
|
-
*
|
|
10
|
-
* Pairing is delegated to {@link pairArms}; this module adds the cluster-aware
|
|
11
|
-
* estimands and inference that task-level McNemar/bootstrap utilities cannot
|
|
12
|
-
* provide. Callers keep their own row shape through accessors, and every
|
|
13
|
-
* matched or unpaired result returns the original row object unchanged.
|
|
14
|
-
*/
|
|
15
|
-
const DEFAULT_BOOTSTRAP_RESAMPLES = 1e4;
|
|
16
|
-
const DEFAULT_SIGN_FLIP_RESAMPLES = 1e5;
|
|
17
|
-
const MAX_RESAMPLES = 1e6;
|
|
18
|
-
const DEFAULT_EXACT_CLUSTER_LIMIT = 20;
|
|
19
|
-
const SIGN_FLIP_SEED_SALT = 2654435769;
|
|
20
|
-
/**
|
|
21
|
-
* Compare binary outcomes on matched work items while respecting independent
|
|
22
|
-
* clusters. The confidence interval resamples whole clusters and recomputes the
|
|
23
|
-
* task-weighted risk difference. The sign-flip test flips whole-cluster outcome
|
|
24
|
-
* totals and tests that same task-weighted estimand.
|
|
25
|
-
*/
|
|
26
|
-
function clusteredPairedBinary(rows, options) {
|
|
27
|
-
const config = validateOptions(options);
|
|
28
|
-
const paired = pairArms(projectSelectedRows(rows, options), {
|
|
29
|
-
baselineArm: options.baselineArm,
|
|
30
|
-
treatmentArm: options.treatmentArm
|
|
31
|
-
});
|
|
32
|
-
const matchedPairs = paired.pairs.map((pair) => {
|
|
33
|
-
const baseline = pair.baseline;
|
|
34
|
-
const treatment = pair.treatment;
|
|
35
|
-
if (baseline.clusterKey !== treatment.clusterKey) throw new ValidationError(`clusteredPairedBinary: pairKey '${pair.pairKey}' rep ${pair.repIndex} crosses clusters ('${baseline.clusterKey}' vs '${treatment.clusterKey}')`);
|
|
36
|
-
return {
|
|
37
|
-
pairKey: pair.pairKey,
|
|
38
|
-
repIndex: pair.repIndex,
|
|
39
|
-
clusterKey: baseline.clusterKey,
|
|
40
|
-
baseline: baseline.original,
|
|
41
|
-
treatment: treatment.original,
|
|
42
|
-
baselinePass: baseline.pass,
|
|
43
|
-
treatmentPass: treatment.pass
|
|
44
|
-
};
|
|
45
|
-
});
|
|
46
|
-
const unpairedBaseline = paired.unpairedBaseline.map((row) => row.original);
|
|
47
|
-
const unpairedTreatment = paired.unpairedTreatment.map((row) => row.original);
|
|
48
|
-
if (matchedPairs.length === 0) return {
|
|
49
|
-
matchedPairs,
|
|
50
|
-
unpairedBaseline,
|
|
51
|
-
unpairedTreatment,
|
|
52
|
-
statistics: null
|
|
53
|
-
};
|
|
54
|
-
const clusters = summarizeClusters(matchedPairs);
|
|
55
|
-
const b10 = clusters.reduce((sum, cluster) => sum + cluster.b10, 0);
|
|
56
|
-
const b01 = clusters.reduce((sum, cluster) => sum + cluster.b01, 0);
|
|
57
|
-
const taskWeightedRiskDifference = (b10 - b01) / matchedPairs.length;
|
|
58
|
-
const equalClusterMean = mean(clusters.map((cluster) => cluster.meanDifference));
|
|
59
|
-
const bootstrap = clusters.length < 2 ? null : clusterBootstrap(clusters, config);
|
|
60
|
-
const signFlip = clusterSignFlip(clusters, config);
|
|
61
|
-
return {
|
|
62
|
-
matchedPairs,
|
|
63
|
-
unpairedBaseline,
|
|
64
|
-
unpairedTreatment,
|
|
65
|
-
statistics: {
|
|
66
|
-
nPairs: matchedPairs.length,
|
|
67
|
-
nClusters: clusters.length,
|
|
68
|
-
b10,
|
|
69
|
-
b01,
|
|
70
|
-
taskWeightedRiskDifference,
|
|
71
|
-
equalClusterMean,
|
|
72
|
-
clusters,
|
|
73
|
-
bootstrap,
|
|
74
|
-
signFlip
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function validateOptions(options) {
|
|
79
|
-
assertNonEmptyString("baselineArm", options.baselineArm);
|
|
80
|
-
assertNonEmptyString("treatmentArm", options.treatmentArm);
|
|
81
|
-
if (options.baselineArm === options.treatmentArm) throw new ValidationError(`clusteredPairedBinary: baselineArm and treatmentArm are both '${options.baselineArm}'`);
|
|
82
|
-
if (!Number.isInteger(options.seed)) throw new ValidationError(`clusteredPairedBinary: seed must be an integer, got ${options.seed}`);
|
|
83
|
-
const confidence = options.confidence ?? .95;
|
|
84
|
-
if (!Number.isFinite(confidence) || confidence <= 0 || confidence >= 1) throw new ValidationError(`clusteredPairedBinary: confidence must be in (0,1), got ${confidence}`);
|
|
85
|
-
const bootstrapResamples = options.bootstrapResamples ?? DEFAULT_BOOTSTRAP_RESAMPLES;
|
|
86
|
-
assertResampleCount("bootstrapResamples", bootstrapResamples);
|
|
87
|
-
const rawMinimumBootstrapResamples = 2 / (1 - confidence);
|
|
88
|
-
const minimumBootstrapResamples = Math.ceil(rawMinimumBootstrapResamples - Number.EPSILON * Math.max(1, rawMinimumBootstrapResamples) * 8);
|
|
89
|
-
if (bootstrapResamples < minimumBootstrapResamples) throw new ValidationError(`clusteredPairedBinary: bootstrapResamples must be at least ${minimumBootstrapResamples} for confidence ${confidence} so both interval tails are represented, got ${bootstrapResamples}`);
|
|
90
|
-
const signFlipResamples = options.signFlipResamples ?? DEFAULT_SIGN_FLIP_RESAMPLES;
|
|
91
|
-
assertResampleCount("signFlipResamples", signFlipResamples);
|
|
92
|
-
const exactClusterLimit = options.exactClusterLimit ?? DEFAULT_EXACT_CLUSTER_LIMIT;
|
|
93
|
-
if (!Number.isInteger(exactClusterLimit) || exactClusterLimit < 0 || exactClusterLimit > DEFAULT_EXACT_CLUSTER_LIMIT) throw new ValidationError(`clusteredPairedBinary: exactClusterLimit must be an integer in [0,${DEFAULT_EXACT_CLUSTER_LIMIT}], got ${exactClusterLimit}`);
|
|
94
|
-
const alternative = options.alternative ?? "two-sided";
|
|
95
|
-
if (alternative !== "two-sided" && alternative !== "greater" && alternative !== "less") throw new ValidationError(`clusteredPairedBinary: alternative must be 'two-sided', 'greater', or 'less', got ${String(alternative)}`);
|
|
96
|
-
return {
|
|
97
|
-
seed: options.seed,
|
|
98
|
-
confidence,
|
|
99
|
-
bootstrapResamples,
|
|
100
|
-
alternative,
|
|
101
|
-
exactClusterLimit,
|
|
102
|
-
signFlipResamples
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
function assertResampleCount(name, value) {
|
|
106
|
-
if (!Number.isInteger(value) || value <= 0) throw new ValidationError(`clusteredPairedBinary: ${name} must be a positive integer, got ${value}`);
|
|
107
|
-
if (value > MAX_RESAMPLES) throw new ValidationError(`clusteredPairedBinary: ${name} must not exceed ${MAX_RESAMPLES}, got ${value}`);
|
|
108
|
-
}
|
|
109
|
-
function projectSelectedRows(rows, options) {
|
|
110
|
-
const projected = [];
|
|
111
|
-
for (const original of rows) {
|
|
112
|
-
const arm = options.arm(original);
|
|
113
|
-
assertNonEmptyString("arm", arm);
|
|
114
|
-
if (arm !== options.baselineArm && arm !== options.treatmentArm) continue;
|
|
115
|
-
const pairKey = options.pairKey(original);
|
|
116
|
-
const clusterKey = options.clusterKey(original);
|
|
117
|
-
const pass = options.pass(original);
|
|
118
|
-
const repKey = options.repKey?.(original);
|
|
119
|
-
assertNonEmptyString("pairKey", pairKey);
|
|
120
|
-
assertNonEmptyString("clusterKey", clusterKey);
|
|
121
|
-
if (typeof pass !== "boolean") throw new ValidationError(`clusteredPairedBinary: pass accessor must return boolean for pairKey '${pairKey}'`);
|
|
122
|
-
if (repKey !== void 0) assertNonEmptyString("repKey", repKey);
|
|
123
|
-
projected.push({
|
|
124
|
-
pairKey,
|
|
125
|
-
clusterKey,
|
|
126
|
-
arm,
|
|
127
|
-
pass,
|
|
128
|
-
repKey,
|
|
129
|
-
original
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return projected;
|
|
133
|
-
}
|
|
134
|
-
function assertNonEmptyString(name, value) {
|
|
135
|
-
if (typeof value !== "string" || value.trim().length === 0) throw new ValidationError(`clusteredPairedBinary: ${name} accessor must return a non-empty string`);
|
|
136
|
-
}
|
|
137
|
-
function summarizeClusters(pairs) {
|
|
138
|
-
const byCluster = /* @__PURE__ */ new Map();
|
|
139
|
-
for (const pair of pairs) {
|
|
140
|
-
const summary = byCluster.get(pair.clusterKey) ?? {
|
|
141
|
-
nPairs: 0,
|
|
142
|
-
b10: 0,
|
|
143
|
-
b01: 0
|
|
144
|
-
};
|
|
145
|
-
summary.nPairs++;
|
|
146
|
-
if (pair.treatmentPass && !pair.baselinePass) summary.b10++;
|
|
147
|
-
else if (pair.baselinePass && !pair.treatmentPass) summary.b01++;
|
|
148
|
-
byCluster.set(pair.clusterKey, summary);
|
|
149
|
-
}
|
|
150
|
-
return [...byCluster.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([clusterKey, summary]) => ({
|
|
151
|
-
clusterKey,
|
|
152
|
-
...summary,
|
|
153
|
-
meanDifference: (summary.b10 - summary.b01) / summary.nPairs
|
|
154
|
-
}));
|
|
155
|
-
}
|
|
156
|
-
function clusterBootstrap(clusters, config) {
|
|
157
|
-
const rng = mulberry32(config.seed);
|
|
158
|
-
const samples = new Array(config.bootstrapResamples);
|
|
159
|
-
for (let draw = 0; draw < config.bootstrapResamples; draw++) {
|
|
160
|
-
let differenceSum = 0;
|
|
161
|
-
let pairCount = 0;
|
|
162
|
-
for (let index = 0; index < clusters.length; index++) {
|
|
163
|
-
const cluster = clusters[Math.floor(rng() * clusters.length)];
|
|
164
|
-
differenceSum += cluster.b10 - cluster.b01;
|
|
165
|
-
pairCount += cluster.nPairs;
|
|
166
|
-
}
|
|
167
|
-
samples[draw] = differenceSum / pairCount;
|
|
168
|
-
}
|
|
169
|
-
samples.sort((a, b) => a - b);
|
|
170
|
-
const alpha = 1 - config.confidence;
|
|
171
|
-
const lowerIndex = Math.floor(alpha / 2 * config.bootstrapResamples);
|
|
172
|
-
const upperIndex = Math.min(config.bootstrapResamples - 1, Math.ceil((1 - alpha / 2) * config.bootstrapResamples) - 1);
|
|
173
|
-
return {
|
|
174
|
-
statistic: "task-weighted-risk-difference",
|
|
175
|
-
lower: samples[lowerIndex],
|
|
176
|
-
upper: samples[Math.max(lowerIndex, upperIndex)],
|
|
177
|
-
confidence: config.confidence,
|
|
178
|
-
resamples: config.bootstrapResamples,
|
|
179
|
-
seed: config.seed
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function clusterSignFlip(clusters, config) {
|
|
183
|
-
const clusterTotals = clusters.map((cluster) => cluster.b10 - cluster.b01);
|
|
184
|
-
const nonZero = clusterTotals.filter((delta) => delta !== 0);
|
|
185
|
-
const totalPairs = clusters.reduce((sum, cluster) => sum + cluster.nPairs, 0);
|
|
186
|
-
const statistic = clusterTotals.reduce((sum, delta) => sum + delta, 0) / totalPairs;
|
|
187
|
-
if (nonZero.length <= config.exactClusterLimit) {
|
|
188
|
-
const assignments = 2 ** nonZero.length;
|
|
189
|
-
let extreme = 0;
|
|
190
|
-
for (let mask = 0; mask < assignments; mask++) {
|
|
191
|
-
let sum = 0;
|
|
192
|
-
for (let index = 0; index < nonZero.length; index++) sum += (mask & 2 ** index ? 1 : -1) * nonZero[index];
|
|
193
|
-
if (isExtreme(sum / totalPairs, statistic, config.alternative)) extreme++;
|
|
194
|
-
}
|
|
195
|
-
return {
|
|
196
|
-
statistic,
|
|
197
|
-
pValue: extreme / assignments,
|
|
198
|
-
alternative: config.alternative,
|
|
199
|
-
method: "exact",
|
|
200
|
-
assignments,
|
|
201
|
-
nClusters: clusters.length,
|
|
202
|
-
nNonZeroClusters: nonZero.length,
|
|
203
|
-
seed: null
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
const signFlipSeed = (config.seed ^ SIGN_FLIP_SEED_SALT) >>> 0;
|
|
207
|
-
const rng = mulberry32(signFlipSeed);
|
|
208
|
-
let extreme = 0;
|
|
209
|
-
for (let draw = 0; draw < config.signFlipResamples; draw++) {
|
|
210
|
-
let sum = 0;
|
|
211
|
-
for (const delta of nonZero) sum += (rng() < .5 ? -1 : 1) * delta;
|
|
212
|
-
if (isExtreme(sum / totalPairs, statistic, config.alternative)) extreme++;
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
statistic,
|
|
216
|
-
pValue: (extreme + 1) / (config.signFlipResamples + 1),
|
|
217
|
-
alternative: config.alternative,
|
|
218
|
-
method: "monte-carlo",
|
|
219
|
-
assignments: config.signFlipResamples,
|
|
220
|
-
nClusters: clusters.length,
|
|
221
|
-
nNonZeroClusters: nonZero.length,
|
|
222
|
-
seed: signFlipSeed
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
function isExtreme(candidate, observed, alternative) {
|
|
226
|
-
const tolerance = Number.EPSILON * Math.max(1, Math.abs(observed)) * 16;
|
|
227
|
-
if (alternative === "greater") return candidate >= observed - tolerance;
|
|
228
|
-
if (alternative === "less") return candidate <= observed + tolerance;
|
|
229
|
-
return Math.abs(candidate) >= Math.abs(observed) - tolerance;
|
|
230
|
-
}
|
|
231
|
-
function mean(values) {
|
|
232
|
-
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
233
|
-
}
|
|
234
|
-
//#endregion
|
|
235
|
-
//#region src/experiment-tracker.ts
|
|
236
|
-
/**
|
|
237
|
-
* Experiment tracker — git-provenanced experiment log with N-rep stats and a
|
|
238
|
-
* KEEP / REGRESSION / NOISE verdict against a parent.
|
|
239
|
-
*
|
|
240
|
-
* Every loop the fleet runs reduces to the same question: "I ran the candidate
|
|
241
|
-
* N times — is the median measurably better than the parent, or is the delta
|
|
242
|
-
* inside the noise band?" The hand-rolled copies bake a fixed score scale
|
|
243
|
-
* (percentage points), a fixed store path (`.evolve/experiments-v2.json`), and
|
|
244
|
-
* `execSync('git …')` straight into the module. This is the canonical version:
|
|
245
|
-
* provenance and persistence are injected, thresholds are configurable, and the
|
|
246
|
-
* stats + verdict are pure functions you can unit-test without a git repo or a
|
|
247
|
-
* filesystem.
|
|
248
|
-
*
|
|
249
|
-
* Stats per experiment: median / mean / min / max / iqr / stddev / passRate /
|
|
250
|
-
* n, plus a `stable` flag (`iqr < iqrUnstableAbove && stddev < stddevUnstableAbove`).
|
|
251
|
-
*
|
|
252
|
-
* Verdict against a parent (both must have `n >= minRepsForVerdict`):
|
|
253
|
-
* - NOISE — the candidate is too unstable to judge (`!stable`)
|
|
254
|
-
* - KEEP — `medianDelta > keepThreshold`
|
|
255
|
-
* - REGRESSION — `medianDelta < -regressionThreshold`
|
|
256
|
-
* - NOISE — otherwise (delta inside the band)
|
|
257
|
-
* With no parent (or insufficient reps) the verdict is the neutral ITERATE.
|
|
258
|
-
*/
|
|
259
|
-
const DEFAULTS = {
|
|
260
|
-
keepThreshold: 5,
|
|
261
|
-
regressionThreshold: 5,
|
|
262
|
-
iqrUnstableAbove: 10,
|
|
263
|
-
stddevUnstableAbove: Number.POSITIVE_INFINITY,
|
|
264
|
-
minRepsForVerdict: 3
|
|
265
|
-
};
|
|
266
|
-
function resolveThresholds(t) {
|
|
267
|
-
const r = {
|
|
268
|
-
...DEFAULTS,
|
|
269
|
-
...t ?? {}
|
|
270
|
-
};
|
|
271
|
-
if (r.keepThreshold < 0) throw new ValidationError(`experiment-tracker: keepThreshold must be >= 0, got ${r.keepThreshold}`);
|
|
272
|
-
if (r.regressionThreshold < 0) throw new ValidationError(`experiment-tracker: regressionThreshold must be >= 0, got ${r.regressionThreshold}`);
|
|
273
|
-
if (r.minRepsForVerdict < 1) throw new ValidationError(`experiment-tracker: minRepsForVerdict must be >= 1, got ${r.minRepsForVerdict}`);
|
|
274
|
-
return r;
|
|
275
|
-
}
|
|
276
|
-
function median(sorted) {
|
|
277
|
-
const n = sorted.length;
|
|
278
|
-
if (n === 0) return 0;
|
|
279
|
-
const mid = Math.floor(n / 2);
|
|
280
|
-
return n % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
281
|
-
}
|
|
282
|
-
/** Population standard deviation (÷n). 0 for fewer than 2 values. */
|
|
283
|
-
function stddev(values, mean) {
|
|
284
|
-
if (values.length < 2) return 0;
|
|
285
|
-
const variance = values.reduce((acc, v) => acc + (v - mean) ** 2, 0) / values.length;
|
|
286
|
-
return Math.sqrt(variance);
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Compute the N-rep statistics for a set of reps. Pure — no I/O. The `stable`
|
|
290
|
-
* flag is the trust gate the verdict depends on: a sample whose spread exceeds
|
|
291
|
-
* the configured bounds can't distinguish a real delta from run-to-run noise.
|
|
292
|
-
*/
|
|
293
|
-
function computeExperimentStats(reps, thresholds) {
|
|
294
|
-
const t = resolveThresholds(thresholds);
|
|
295
|
-
const n = reps.length;
|
|
296
|
-
if (n === 0) return {
|
|
297
|
-
median: 0,
|
|
298
|
-
mean: 0,
|
|
299
|
-
min: 0,
|
|
300
|
-
max: 0,
|
|
301
|
-
iqr: 0,
|
|
302
|
-
stddev: 0,
|
|
303
|
-
passRate: null,
|
|
304
|
-
n: 0,
|
|
305
|
-
stable: false
|
|
306
|
-
};
|
|
307
|
-
const scores = reps.map((r) => {
|
|
308
|
-
if (!Number.isFinite(r.score)) throw new ValidationError(`experiment-tracker: rep ${r.rep} has non-finite score ${r.score}`);
|
|
309
|
-
return r.score;
|
|
310
|
-
});
|
|
311
|
-
const sorted = [...scores].sort((a, b) => a - b);
|
|
312
|
-
const mean = scores.reduce((s, v) => s + v, 0) / n;
|
|
313
|
-
const sd = stddev(scores, mean);
|
|
314
|
-
const spread = iqr(scores);
|
|
315
|
-
const rated = reps.filter((r) => typeof r.passed === "boolean");
|
|
316
|
-
const passRate = rated.length === 0 ? null : rated.filter((r) => r.passed).length / rated.length;
|
|
317
|
-
const stable = spread < t.iqrUnstableAbove && sd < t.stddevUnstableAbove;
|
|
318
|
-
return {
|
|
319
|
-
median: median(sorted),
|
|
320
|
-
mean,
|
|
321
|
-
min: sorted[0],
|
|
322
|
-
max: sorted[n - 1],
|
|
323
|
-
iqr: spread,
|
|
324
|
-
stddev: sd,
|
|
325
|
-
passRate,
|
|
326
|
-
n,
|
|
327
|
-
stable
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Verdict for a candidate against its parent. Pure — operates on already-computed
|
|
332
|
-
* stats. KEEP/REGRESSION require both sides to have `>= minRepsForVerdict` reps
|
|
333
|
-
* AND the candidate to be `stable`; otherwise the result is NOISE (unstable) or
|
|
334
|
-
* ITERATE (not enough reps / no parent).
|
|
335
|
-
*/
|
|
336
|
-
function improvementVerdict(candidate, parent, thresholds) {
|
|
337
|
-
const t = resolveThresholds(thresholds);
|
|
338
|
-
if (!parent) return {
|
|
339
|
-
verdict: "ITERATE",
|
|
340
|
-
medianDelta: null,
|
|
341
|
-
reason: "no parent experiment to compare against"
|
|
342
|
-
};
|
|
343
|
-
if (candidate.n < t.minRepsForVerdict || parent.n < t.minRepsForVerdict) return {
|
|
344
|
-
verdict: "ITERATE",
|
|
345
|
-
medianDelta: null,
|
|
346
|
-
reason: `need >= ${t.minRepsForVerdict} reps on both sides (candidate n=${candidate.n}, parent n=${parent.n})`
|
|
347
|
-
};
|
|
348
|
-
if (!candidate.stable) return {
|
|
349
|
-
verdict: "NOISE",
|
|
350
|
-
medianDelta: candidate.median - parent.median,
|
|
351
|
-
reason: `candidate unstable (iqr=${candidate.iqr}, stddev=${candidate.stddev.toFixed(2)})`
|
|
352
|
-
};
|
|
353
|
-
const medianDelta = candidate.median - parent.median;
|
|
354
|
-
if (medianDelta > t.keepThreshold) return {
|
|
355
|
-
verdict: "KEEP",
|
|
356
|
-
medianDelta,
|
|
357
|
-
reason: `median +${medianDelta} > +${t.keepThreshold}`
|
|
358
|
-
};
|
|
359
|
-
if (medianDelta < -t.regressionThreshold) return {
|
|
360
|
-
verdict: "REGRESSION",
|
|
361
|
-
medianDelta,
|
|
362
|
-
reason: `median ${medianDelta} < -${t.regressionThreshold}`
|
|
363
|
-
};
|
|
364
|
-
return {
|
|
365
|
-
verdict: "NOISE",
|
|
366
|
-
medianDelta,
|
|
367
|
-
reason: `median delta ${medianDelta} inside noise band [-${t.regressionThreshold}, +${t.keepThreshold}]`
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Default provenance reader: `git rev-parse HEAD`, the subject line, and the
|
|
372
|
-
* files changed vs `HEAD~1`. Fail-loud — a tracker that silently logs
|
|
373
|
-
* `commit: 'unknown'` corrupts the provenance the whole point of the log is to
|
|
374
|
-
* carry. When the working tree genuinely has no parent commit, pass an override.
|
|
375
|
-
*/
|
|
376
|
-
const gitProvenanceReader = () => {
|
|
377
|
-
const run = (cmd) => execSync(cmd, { encoding: "utf8" }).trim();
|
|
378
|
-
const commit = run("git rev-parse --short HEAD");
|
|
379
|
-
const message = run("git log -1 --format=%s");
|
|
380
|
-
const changedRaw = run("git diff --name-only HEAD~1");
|
|
381
|
-
return {
|
|
382
|
-
commit,
|
|
383
|
-
message,
|
|
384
|
-
changedFiles: changedRaw.length === 0 ? [] : changedRaw.split("\n").filter(Boolean)
|
|
385
|
-
};
|
|
386
|
-
};
|
|
387
|
-
/** In-memory store — the default when no persistence is wanted (tests, ephemeral
|
|
388
|
-
* runs). State lives on the instance. */
|
|
389
|
-
function inMemoryExperimentStore(initial = []) {
|
|
390
|
-
let state = initial.map((e) => structuredClone(e));
|
|
391
|
-
return {
|
|
392
|
-
async load() {
|
|
393
|
-
return state.map((e) => structuredClone(e));
|
|
394
|
-
},
|
|
395
|
-
async save(experiments) {
|
|
396
|
-
state = experiments.map((e) => structuredClone(e));
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
/** Filesystem store — a single JSON array at `path`, created on first save. */
|
|
401
|
-
function fileExperimentStore(path) {
|
|
402
|
-
return {
|
|
403
|
-
async load() {
|
|
404
|
-
const fs = await import("node:fs/promises");
|
|
405
|
-
try {
|
|
406
|
-
const raw = await fs.readFile(path, "utf8");
|
|
407
|
-
const parsed = JSON.parse(raw);
|
|
408
|
-
if (!Array.isArray(parsed)) throw new ValidationError(`experiment-tracker: store at ${path} is not a JSON array`);
|
|
409
|
-
return parsed;
|
|
410
|
-
} catch (err) {
|
|
411
|
-
if (err.code === "ENOENT") return [];
|
|
412
|
-
throw err;
|
|
413
|
-
}
|
|
414
|
-
},
|
|
415
|
-
async save(experiments) {
|
|
416
|
-
const fs = await import("node:fs/promises");
|
|
417
|
-
const pathMod = await import("node:path");
|
|
418
|
-
await fs.mkdir(pathMod.dirname(path), { recursive: true });
|
|
419
|
-
await fs.writeFile(path, JSON.stringify(experiments, null, 2), "utf8");
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Stateful tracker over an `ExperimentStore`. Create an experiment (provenance
|
|
425
|
-
* is captured once), append reps as they complete (stats + verdict recompute on
|
|
426
|
-
* every append), and read the log back for a dashboard. All persistence and git
|
|
427
|
-
* access flow through the injected seams, so the tracker is fully testable
|
|
428
|
-
* without a repo or disk.
|
|
429
|
-
*/
|
|
430
|
-
var ExperimentTracker = class {
|
|
431
|
-
store;
|
|
432
|
-
provenanceReader;
|
|
433
|
-
thresholds;
|
|
434
|
-
now;
|
|
435
|
-
constructor(options = {}) {
|
|
436
|
-
this.store = options.store ?? inMemoryExperimentStore();
|
|
437
|
-
this.provenanceReader = options.provenanceReader ?? gitProvenanceReader;
|
|
438
|
-
this.thresholds = resolveThresholds(options.thresholds);
|
|
439
|
-
this.now = options.now ?? Date.now;
|
|
440
|
-
}
|
|
441
|
-
async create(input) {
|
|
442
|
-
const experiments = await this.store.load();
|
|
443
|
-
if (experiments.some((e) => e.id === input.id)) throw new ValidationError(`experiment-tracker: experiment id "${input.id}" already exists`);
|
|
444
|
-
if (input.parentId && !experiments.some((e) => e.id === input.parentId)) throw new ValidationError(`experiment-tracker: parent experiment "${input.parentId}" not found`);
|
|
445
|
-
const provenance = input.provenance ?? await this.provenanceReader();
|
|
446
|
-
const experiment = {
|
|
447
|
-
id: input.id,
|
|
448
|
-
label: input.label,
|
|
449
|
-
provenance,
|
|
450
|
-
parentId: input.parentId,
|
|
451
|
-
changeSummary: input.changeSummary,
|
|
452
|
-
reps: [],
|
|
453
|
-
stats: computeExperimentStats([], this.thresholds),
|
|
454
|
-
verdict: "ITERATE",
|
|
455
|
-
createdAt: new Date(this.now()).toISOString()
|
|
456
|
-
};
|
|
457
|
-
experiments.push(experiment);
|
|
458
|
-
await this.store.save(experiments);
|
|
459
|
-
return structuredClone(experiment);
|
|
460
|
-
}
|
|
461
|
-
/** Append a rep (its `rep` index defaults to the current rep count) and
|
|
462
|
-
* recompute stats + verdict. Returns the updated experiment. */
|
|
463
|
-
async addRep(experimentId, rep) {
|
|
464
|
-
const experiments = await this.store.load();
|
|
465
|
-
const exp = experiments.find((e) => e.id === experimentId);
|
|
466
|
-
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
467
|
-
const fullRep = {
|
|
468
|
-
rep: rep.rep ?? exp.reps.length,
|
|
469
|
-
score: rep.score,
|
|
470
|
-
passed: rep.passed,
|
|
471
|
-
metrics: rep.metrics,
|
|
472
|
-
timestamp: rep.timestamp ?? new Date(this.now()).toISOString()
|
|
473
|
-
};
|
|
474
|
-
exp.reps.push(fullRep);
|
|
475
|
-
exp.stats = computeExperimentStats(exp.reps, this.thresholds);
|
|
476
|
-
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
477
|
-
exp.verdict = improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds).verdict;
|
|
478
|
-
await this.store.save(experiments);
|
|
479
|
-
return structuredClone(exp);
|
|
480
|
-
}
|
|
481
|
-
async get(experimentId) {
|
|
482
|
-
const found = (await this.store.load()).find((e) => e.id === experimentId);
|
|
483
|
-
return found ? structuredClone(found) : void 0;
|
|
484
|
-
}
|
|
485
|
-
async list() {
|
|
486
|
-
return this.store.load();
|
|
487
|
-
}
|
|
488
|
-
/** Full verdict (not just the enum) for an experiment vs its parent. */
|
|
489
|
-
async verdictFor(experimentId) {
|
|
490
|
-
const experiments = await this.store.load();
|
|
491
|
-
const exp = experiments.find((e) => e.id === experimentId);
|
|
492
|
-
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
493
|
-
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
494
|
-
return improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds);
|
|
495
|
-
}
|
|
496
|
-
};
|
|
497
|
-
//#endregion
|
|
498
|
-
export { improvementVerdict as a, gitProvenanceReader as i, computeExperimentStats as n, inMemoryExperimentStore as o, fileExperimentStore as r, clusteredPairedBinary as s, ExperimentTracker as t };
|
|
499
|
-
|
|
500
|
-
//# sourceMappingURL=experiment-tracker-CnRICnMl.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"experiment-tracker-CnRICnMl.js","names":[],"sources":["../src/clustered-paired-binary.ts","../src/experiment-tracker.ts"],"sourcesContent":["/**\n * Paired binary comparison for work items nested inside independent clusters.\n *\n * Pairing is delegated to {@link pairArms}; this module adds the cluster-aware\n * estimands and inference that task-level McNemar/bootstrap utilities cannot\n * provide. Callers keep their own row shape through accessors, and every\n * matched or unpaired result returns the original row object unchanged.\n */\n\nimport { ValidationError } from './errors'\nimport { type PairedArmRow, pairArms } from './paired-arms'\nimport { mulberry32 } from './statistics'\n\nexport type ClusterSignFlipAlternative = 'two-sided' | 'greater' | 'less'\n\nexport interface ClusteredPairedBinaryOptions<TRow> {\n /** Arm treated as the control side of every pair. */\n baselineArm: string\n /** Arm treated as the treatment side of every pair. */\n treatmentArm: string\n /** Stable work-item identity shared by both arms. */\n pairKey: (row: TRow) => string\n /** Independent-cluster identity, shared by both rows in a matched pair. */\n clusterKey: (row: TRow) => string\n /** Arm identity for this row. Rows from other arms are ignored. */\n arm: (row: TRow) => string\n /** Binary outcome. */\n pass: (row: TRow) => boolean\n /** Replicate identity when a work item has multiple rows in either arm. */\n repKey?: (row: TRow) => string | undefined\n /** Deterministic seed for bootstrap and Monte Carlo sign-flip draws. */\n seed: number\n /** Percentile confidence level. Default 0.95. */\n confidence?: number\n /** Whole-cluster bootstrap draws. Default 10,000; maximum 1,000,000. */\n bootstrapResamples?: number\n /** Sign-flip alternative. Default 'two-sided'. */\n alternative?: ClusterSignFlipAlternative\n /**\n * Enumerate every sign assignment at or below this many non-zero clusters;\n * otherwise use Monte Carlo. Default 20; maximum 20.\n */\n exactClusterLimit?: number\n /** Monte Carlo sign-flip draws when exact enumeration is not used. Default 100,000; maximum 1,000,000. */\n signFlipResamples?: number\n}\n\nexport interface ClusteredMatchedPair<TRow> {\n pairKey: string\n repIndex: number\n clusterKey: string\n baseline: TRow\n treatment: TRow\n baselinePass: boolean\n treatmentPass: boolean\n}\n\nexport interface ClusteredBinaryCluster {\n clusterKey: string\n nPairs: number\n /** Treatment passes and baseline fails. */\n b10: number\n /** Baseline passes and treatment fails. */\n b01: number\n /** Mean (treatment - baseline) binary outcome within this cluster. */\n meanDifference: number\n}\n\nexport interface ClusterBootstrapInterval {\n /** The interval resamples clusters and recomputes this task-weighted statistic. */\n statistic: 'task-weighted-risk-difference'\n lower: number\n upper: number\n confidence: number\n resamples: number\n seed: number\n}\n\nexport interface ClusterSignFlipResult {\n /** Task-weighted paired risk difference, matching the reported bootstrap estimand. */\n statistic: number\n /**\n * Randomization p-value under whole-cluster arm-label exchangeability.\n * `method: 'exact'` means every cluster-level sign assignment was enumerated;\n * it does not make the exchangeability assumption unnecessary.\n */\n pValue: number\n alternative: ClusterSignFlipAlternative\n method: 'exact' | 'monte-carlo'\n /** Exact assignments enumerated or Monte Carlo assignments drawn. */\n assignments: number\n nClusters: number\n nNonZeroClusters: number\n /** Null for exact enumeration, which has no random draws. */\n seed: number | null\n}\n\nexport interface ClusteredPairedBinaryStatistics {\n nPairs: number\n nClusters: number\n /** Treatment passes and baseline fails, across all matched pairs. */\n b10: number\n /** Baseline passes and treatment fails, across all matched pairs. */\n b01: number\n /** Mean paired difference across tasks, so every task has equal weight. */\n taskWeightedRiskDifference: number\n /** Mean of cluster-level paired differences, so every cluster has equal weight. */\n equalClusterMean: number\n clusters: ClusteredBinaryCluster[]\n /** Null below two independent clusters; one cluster cannot estimate cluster uncertainty. */\n bootstrap: ClusterBootstrapInterval | null\n signFlip: ClusterSignFlipResult\n}\n\nexport interface ClusteredPairedBinaryResult<TRow> {\n matchedPairs: ClusteredMatchedPair<TRow>[]\n unpairedBaseline: TRow[]\n unpairedTreatment: TRow[]\n /** Null when there are no matched rows; absence is never reported as a zero effect. */\n statistics: ClusteredPairedBinaryStatistics | null\n}\n\ninterface ProjectedRow<TRow> extends PairedArmRow {\n clusterKey: string\n original: TRow\n}\n\nconst DEFAULT_BOOTSTRAP_RESAMPLES = 10_000\nconst DEFAULT_SIGN_FLIP_RESAMPLES = 100_000\nconst MAX_RESAMPLES = 1_000_000\nconst DEFAULT_EXACT_CLUSTER_LIMIT = 20\nconst SIGN_FLIP_SEED_SALT = 0x9e3779b9\n\n/**\n * Compare binary outcomes on matched work items while respecting independent\n * clusters. The confidence interval resamples whole clusters and recomputes the\n * task-weighted risk difference. The sign-flip test flips whole-cluster outcome\n * totals and tests that same task-weighted estimand.\n */\nexport function clusteredPairedBinary<TRow>(\n rows: readonly TRow[],\n options: ClusteredPairedBinaryOptions<TRow>,\n): ClusteredPairedBinaryResult<TRow> {\n const config = validateOptions(options)\n const projected = projectSelectedRows(rows, options)\n const paired = pairArms(projected, {\n baselineArm: options.baselineArm,\n treatmentArm: options.treatmentArm,\n })\n\n const matchedPairs = paired.pairs.map((pair): ClusteredMatchedPair<TRow> => {\n const baseline = pair.baseline as ProjectedRow<TRow>\n const treatment = pair.treatment as ProjectedRow<TRow>\n if (baseline.clusterKey !== treatment.clusterKey) {\n throw new ValidationError(\n `clusteredPairedBinary: pairKey '${pair.pairKey}' rep ${pair.repIndex} crosses clusters ` +\n `('${baseline.clusterKey}' vs '${treatment.clusterKey}')`,\n )\n }\n return {\n pairKey: pair.pairKey,\n repIndex: pair.repIndex,\n clusterKey: baseline.clusterKey,\n baseline: baseline.original,\n treatment: treatment.original,\n baselinePass: baseline.pass!,\n treatmentPass: treatment.pass!,\n }\n })\n\n const unpairedBaseline = paired.unpairedBaseline.map(\n (row) => (row as ProjectedRow<TRow>).original,\n )\n const unpairedTreatment = paired.unpairedTreatment.map(\n (row) => (row as ProjectedRow<TRow>).original,\n )\n\n if (matchedPairs.length === 0) {\n return { matchedPairs, unpairedBaseline, unpairedTreatment, statistics: null }\n }\n\n const clusters = summarizeClusters(matchedPairs)\n const b10 = clusters.reduce((sum, cluster) => sum + cluster.b10, 0)\n const b01 = clusters.reduce((sum, cluster) => sum + cluster.b01, 0)\n const taskWeightedRiskDifference = (b10 - b01) / matchedPairs.length\n const equalClusterMean = mean(clusters.map((cluster) => cluster.meanDifference))\n const bootstrap = clusters.length < 2 ? null : clusterBootstrap(clusters, config)\n const signFlip = clusterSignFlip(clusters, config)\n\n return {\n matchedPairs,\n unpairedBaseline,\n unpairedTreatment,\n statistics: {\n nPairs: matchedPairs.length,\n nClusters: clusters.length,\n b10,\n b01,\n taskWeightedRiskDifference,\n equalClusterMean,\n clusters,\n bootstrap,\n signFlip,\n },\n }\n}\n\ninterface ValidatedConfig {\n seed: number\n confidence: number\n bootstrapResamples: number\n alternative: ClusterSignFlipAlternative\n exactClusterLimit: number\n signFlipResamples: number\n}\n\nfunction validateOptions<TRow>(options: ClusteredPairedBinaryOptions<TRow>): ValidatedConfig {\n assertNonEmptyString('baselineArm', options.baselineArm)\n assertNonEmptyString('treatmentArm', options.treatmentArm)\n if (options.baselineArm === options.treatmentArm) {\n throw new ValidationError(\n `clusteredPairedBinary: baselineArm and treatmentArm are both '${options.baselineArm}'`,\n )\n }\n if (!Number.isInteger(options.seed)) {\n throw new ValidationError(`clusteredPairedBinary: seed must be an integer, got ${options.seed}`)\n }\n const confidence = options.confidence ?? 0.95\n if (!Number.isFinite(confidence) || confidence <= 0 || confidence >= 1) {\n throw new ValidationError(\n `clusteredPairedBinary: confidence must be in (0,1), got ${confidence}`,\n )\n }\n const bootstrapResamples = options.bootstrapResamples ?? DEFAULT_BOOTSTRAP_RESAMPLES\n assertResampleCount('bootstrapResamples', bootstrapResamples)\n const rawMinimumBootstrapResamples = 2 / (1 - confidence)\n const minimumBootstrapResamples = Math.ceil(\n rawMinimumBootstrapResamples - Number.EPSILON * Math.max(1, rawMinimumBootstrapResamples) * 8,\n )\n if (bootstrapResamples < minimumBootstrapResamples) {\n throw new ValidationError(\n `clusteredPairedBinary: bootstrapResamples must be at least ${minimumBootstrapResamples} for confidence ${confidence} so both interval tails are represented, got ${bootstrapResamples}`,\n )\n }\n const signFlipResamples = options.signFlipResamples ?? DEFAULT_SIGN_FLIP_RESAMPLES\n assertResampleCount('signFlipResamples', signFlipResamples)\n const exactClusterLimit = options.exactClusterLimit ?? DEFAULT_EXACT_CLUSTER_LIMIT\n if (\n !Number.isInteger(exactClusterLimit) ||\n exactClusterLimit < 0 ||\n exactClusterLimit > DEFAULT_EXACT_CLUSTER_LIMIT\n ) {\n throw new ValidationError(\n `clusteredPairedBinary: exactClusterLimit must be an integer in [0,${DEFAULT_EXACT_CLUSTER_LIMIT}], got ${exactClusterLimit}`,\n )\n }\n const alternative = options.alternative ?? 'two-sided'\n if (alternative !== 'two-sided' && alternative !== 'greater' && alternative !== 'less') {\n throw new ValidationError(\n `clusteredPairedBinary: alternative must be 'two-sided', 'greater', or 'less', got ${String(alternative)}`,\n )\n }\n return {\n seed: options.seed,\n confidence,\n bootstrapResamples,\n alternative,\n exactClusterLimit,\n signFlipResamples,\n }\n}\n\nfunction assertResampleCount(name: string, value: number): void {\n if (!Number.isInteger(value) || value <= 0) {\n throw new ValidationError(\n `clusteredPairedBinary: ${name} must be a positive integer, got ${value}`,\n )\n }\n if (value > MAX_RESAMPLES) {\n throw new ValidationError(\n `clusteredPairedBinary: ${name} must not exceed ${MAX_RESAMPLES}, got ${value}`,\n )\n }\n}\n\nfunction projectSelectedRows<TRow>(\n rows: readonly TRow[],\n options: ClusteredPairedBinaryOptions<TRow>,\n): ProjectedRow<TRow>[] {\n const projected: ProjectedRow<TRow>[] = []\n for (const original of rows) {\n const arm = options.arm(original)\n assertNonEmptyString('arm', arm)\n if (arm !== options.baselineArm && arm !== options.treatmentArm) continue\n\n const pairKey = options.pairKey(original)\n const clusterKey = options.clusterKey(original)\n const pass = options.pass(original)\n const repKey = options.repKey?.(original)\n assertNonEmptyString('pairKey', pairKey)\n assertNonEmptyString('clusterKey', clusterKey)\n if (typeof pass !== 'boolean') {\n throw new ValidationError(\n `clusteredPairedBinary: pass accessor must return boolean for pairKey '${pairKey}'`,\n )\n }\n if (repKey !== undefined) assertNonEmptyString('repKey', repKey)\n projected.push({ pairKey, clusterKey, arm, pass, repKey, original })\n }\n return projected\n}\n\nfunction assertNonEmptyString(name: string, value: string): void {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new ValidationError(\n `clusteredPairedBinary: ${name} accessor must return a non-empty string`,\n )\n }\n}\n\nfunction summarizeClusters<TRow>(\n pairs: readonly ClusteredMatchedPair<TRow>[],\n): ClusteredBinaryCluster[] {\n const byCluster = new Map<string, { nPairs: number; b10: number; b01: number }>()\n for (const pair of pairs) {\n const summary = byCluster.get(pair.clusterKey) ?? { nPairs: 0, b10: 0, b01: 0 }\n summary.nPairs++\n if (pair.treatmentPass && !pair.baselinePass) summary.b10++\n else if (pair.baselinePass && !pair.treatmentPass) summary.b01++\n byCluster.set(pair.clusterKey, summary)\n }\n return [...byCluster.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([clusterKey, summary]) => ({\n clusterKey,\n ...summary,\n meanDifference: (summary.b10 - summary.b01) / summary.nPairs,\n }))\n}\n\nfunction clusterBootstrap(\n clusters: readonly ClusteredBinaryCluster[],\n config: ValidatedConfig,\n): ClusterBootstrapInterval {\n const rng = mulberry32(config.seed)\n const samples = new Array<number>(config.bootstrapResamples)\n for (let draw = 0; draw < config.bootstrapResamples; draw++) {\n let differenceSum = 0\n let pairCount = 0\n for (let index = 0; index < clusters.length; index++) {\n const cluster = clusters[Math.floor(rng() * clusters.length)]!\n differenceSum += cluster.b10 - cluster.b01\n pairCount += cluster.nPairs\n }\n samples[draw] = differenceSum / pairCount\n }\n samples.sort((a, b) => a - b)\n const alpha = 1 - config.confidence\n const lowerIndex = Math.floor((alpha / 2) * config.bootstrapResamples)\n const upperIndex = Math.min(\n config.bootstrapResamples - 1,\n Math.ceil((1 - alpha / 2) * config.bootstrapResamples) - 1,\n )\n return {\n statistic: 'task-weighted-risk-difference',\n lower: samples[lowerIndex]!,\n upper: samples[Math.max(lowerIndex, upperIndex)]!,\n confidence: config.confidence,\n resamples: config.bootstrapResamples,\n seed: config.seed,\n }\n}\n\nfunction clusterSignFlip(\n clusters: readonly ClusteredBinaryCluster[],\n config: ValidatedConfig,\n): ClusterSignFlipResult {\n const clusterTotals = clusters.map((cluster) => cluster.b10 - cluster.b01)\n const nonZero = clusterTotals.filter((delta) => delta !== 0)\n const totalPairs = clusters.reduce((sum, cluster) => sum + cluster.nPairs, 0)\n const statistic = clusterTotals.reduce((sum, delta) => sum + delta, 0) / totalPairs\n if (nonZero.length <= config.exactClusterLimit) {\n const assignments = 2 ** nonZero.length\n let extreme = 0\n for (let mask = 0; mask < assignments; mask++) {\n let sum = 0\n for (let index = 0; index < nonZero.length; index++) {\n sum += (mask & (2 ** index) ? 1 : -1) * nonZero[index]!\n }\n const permuted = sum / totalPairs\n if (isExtreme(permuted, statistic, config.alternative)) extreme++\n }\n return {\n statistic,\n pValue: extreme / assignments,\n alternative: config.alternative,\n method: 'exact',\n assignments,\n nClusters: clusters.length,\n nNonZeroClusters: nonZero.length,\n seed: null,\n }\n }\n\n const signFlipSeed = (config.seed ^ SIGN_FLIP_SEED_SALT) >>> 0\n const rng = mulberry32(signFlipSeed)\n let extreme = 0\n for (let draw = 0; draw < config.signFlipResamples; draw++) {\n let sum = 0\n for (const delta of nonZero) sum += (rng() < 0.5 ? -1 : 1) * delta\n const permuted = sum / totalPairs\n if (isExtreme(permuted, statistic, config.alternative)) extreme++\n }\n return {\n statistic,\n pValue: (extreme + 1) / (config.signFlipResamples + 1),\n alternative: config.alternative,\n method: 'monte-carlo',\n assignments: config.signFlipResamples,\n nClusters: clusters.length,\n nNonZeroClusters: nonZero.length,\n seed: signFlipSeed,\n }\n}\n\nfunction isExtreme(\n candidate: number,\n observed: number,\n alternative: ClusterSignFlipAlternative,\n): boolean {\n const tolerance = Number.EPSILON * Math.max(1, Math.abs(observed)) * 16\n if (alternative === 'greater') return candidate >= observed - tolerance\n if (alternative === 'less') return candidate <= observed + tolerance\n return Math.abs(candidate) >= Math.abs(observed) - tolerance\n}\n\nfunction mean(values: readonly number[]): number {\n return values.reduce((sum, value) => sum + value, 0) / values.length\n}\n","/**\n * Experiment tracker — git-provenanced experiment log with N-rep stats and a\n * KEEP / REGRESSION / NOISE verdict against a parent.\n *\n * Every loop the fleet runs reduces to the same question: \"I ran the candidate\n * N times — is the median measurably better than the parent, or is the delta\n * inside the noise band?\" The hand-rolled copies bake a fixed score scale\n * (percentage points), a fixed store path (`.evolve/experiments-v2.json`), and\n * `execSync('git …')` straight into the module. This is the canonical version:\n * provenance and persistence are injected, thresholds are configurable, and the\n * stats + verdict are pure functions you can unit-test without a git repo or a\n * filesystem.\n *\n * Stats per experiment: median / mean / min / max / iqr / stddev / passRate /\n * n, plus a `stable` flag (`iqr < iqrUnstableAbove && stddev < stddevUnstableAbove`).\n *\n * Verdict against a parent (both must have `n >= minRepsForVerdict`):\n * - NOISE — the candidate is too unstable to judge (`!stable`)\n * - KEEP — `medianDelta > keepThreshold`\n * - REGRESSION — `medianDelta < -regressionThreshold`\n * - NOISE — otherwise (delta inside the band)\n * With no parent (or insufficient reps) the verdict is the neutral ITERATE.\n */\n\nimport { execSync } from 'node:child_process'\nimport { iqr } from './baseline'\nimport { ValidationError } from './errors'\n\n/** Verdict for one experiment relative to its parent. ITERATE is the neutral\n * \"keep collecting reps / no parent to compare against\" state. */\nexport type ExperimentVerdict = 'KEEP' | 'ITERATE' | 'NOISE' | 'REGRESSION'\n\n/** Git provenance for the working tree an experiment was run from. */\nexport interface ExperimentProvenance {\n /** Commit sha (short or full — the tracker does not interpret it). */\n commit: string\n /** First line of the commit message. */\n message: string\n /** Files changed vs the parent commit, or a marker like 'uncommitted'. */\n changedFiles: string[]\n}\n\n/** A single repetition of an experiment, carrying the score the verdict is\n * computed on plus any free-form per-rep metrics the consumer wants kept. */\nexport interface ExperimentRep {\n /** 0-indexed repetition number within the experiment. */\n rep: number\n /** The score this rep is judged on (same scale as the thresholds). */\n score: number\n /** ISO timestamp the rep completed. */\n timestamp: string\n /** Whether this rep passed the consumer's own gate — folded into `passRate`. */\n passed?: boolean\n /** Free-form numeric metrics retained for later analysis. */\n metrics?: Record<string, number>\n}\n\nexport interface ExperimentStats {\n median: number\n mean: number\n min: number\n max: number\n /** Inter-quartile range of the rep scores. */\n iqr: number\n /** Population standard deviation of the rep scores. */\n stddev: number\n /** Fraction of reps with `passed === true`, over reps that set `passed`.\n * null when no rep declared a pass/fail outcome. */\n passRate: number | null\n /** Number of reps. */\n n: number\n /** True when the sample is tight enough to trust for a verdict. */\n stable: boolean\n}\n\nexport interface Experiment {\n /** Stable id for the experiment. */\n id: string\n /** Free-form label / config descriptor. */\n label: string\n /** Git provenance captured when the experiment was created. */\n provenance: ExperimentProvenance\n /** Parent experiment id this candidate is compared against, if any. */\n parentId?: string\n /** One-line summary of what changed from the parent. */\n changeSummary: string\n reps: ExperimentRep[]\n stats: ExperimentStats\n verdict: ExperimentVerdict\n /** ISO timestamp the experiment was created. */\n createdAt: string\n}\n\nexport interface ImprovementThresholds {\n /** medianDelta strictly above this ⇒ KEEP. Default 5. */\n keepThreshold?: number\n /** medianDelta strictly below the negative of this ⇒ REGRESSION. Default 5. */\n regressionThreshold?: number\n /** iqr at or above this ⇒ unstable. Default 10. */\n iqrUnstableAbove?: number\n /** stddev at or above this ⇒ unstable. Default Infinity (iqr-only stability). */\n stddevUnstableAbove?: number\n /** Reps required on BOTH candidate and parent before a verdict is rendered.\n * Default 3. */\n minRepsForVerdict?: number\n}\n\nexport interface ImprovementVerdictResult {\n verdict: ExperimentVerdict\n /** candidate.median − parent.median; null when no parent or insufficient reps. */\n medianDelta: number | null\n /** Human-readable reason for the verdict — for dashboards and logs. */\n reason: string\n}\n\nconst DEFAULTS: Required<ImprovementThresholds> = {\n keepThreshold: 5,\n regressionThreshold: 5,\n iqrUnstableAbove: 10,\n stddevUnstableAbove: Number.POSITIVE_INFINITY,\n minRepsForVerdict: 3,\n}\n\nfunction resolveThresholds(t: ImprovementThresholds | undefined): Required<ImprovementThresholds> {\n const r = { ...DEFAULTS, ...(t ?? {}) }\n if (r.keepThreshold < 0) {\n throw new ValidationError(\n `experiment-tracker: keepThreshold must be >= 0, got ${r.keepThreshold}`,\n )\n }\n if (r.regressionThreshold < 0) {\n throw new ValidationError(\n `experiment-tracker: regressionThreshold must be >= 0, got ${r.regressionThreshold}`,\n )\n }\n if (r.minRepsForVerdict < 1) {\n throw new ValidationError(\n `experiment-tracker: minRepsForVerdict must be >= 1, got ${r.minRepsForVerdict}`,\n )\n }\n return r\n}\n\nfunction median(sorted: number[]): number {\n const n = sorted.length\n if (n === 0) return 0\n const mid = Math.floor(n / 2)\n return n % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!\n}\n\n/** Population standard deviation (÷n). 0 for fewer than 2 values. */\nfunction stddev(values: number[], mean: number): number {\n if (values.length < 2) return 0\n const variance = values.reduce((acc, v) => acc + (v - mean) ** 2, 0) / values.length\n return Math.sqrt(variance)\n}\n\n/**\n * Compute the N-rep statistics for a set of reps. Pure — no I/O. The `stable`\n * flag is the trust gate the verdict depends on: a sample whose spread exceeds\n * the configured bounds can't distinguish a real delta from run-to-run noise.\n */\nexport function computeExperimentStats(\n reps: ExperimentRep[],\n thresholds?: ImprovementThresholds,\n): ExperimentStats {\n const t = resolveThresholds(thresholds)\n const n = reps.length\n if (n === 0) {\n return {\n median: 0,\n mean: 0,\n min: 0,\n max: 0,\n iqr: 0,\n stddev: 0,\n passRate: null,\n n: 0,\n stable: false,\n }\n }\n const scores = reps.map((r) => {\n if (!Number.isFinite(r.score)) {\n throw new ValidationError(`experiment-tracker: rep ${r.rep} has non-finite score ${r.score}`)\n }\n return r.score\n })\n const sorted = [...scores].sort((a, b) => a - b)\n const mean = scores.reduce((s, v) => s + v, 0) / n\n const sd = stddev(scores, mean)\n const spread = iqr(scores)\n const rated = reps.filter((r) => typeof r.passed === 'boolean')\n const passRate = rated.length === 0 ? null : rated.filter((r) => r.passed).length / rated.length\n const stable = spread < t.iqrUnstableAbove && sd < t.stddevUnstableAbove\n return {\n median: median(sorted),\n mean,\n min: sorted[0]!,\n max: sorted[n - 1]!,\n iqr: spread,\n stddev: sd,\n passRate,\n n,\n stable,\n }\n}\n\n/**\n * Verdict for a candidate against its parent. Pure — operates on already-computed\n * stats. KEEP/REGRESSION require both sides to have `>= minRepsForVerdict` reps\n * AND the candidate to be `stable`; otherwise the result is NOISE (unstable) or\n * ITERATE (not enough reps / no parent).\n */\nexport function improvementVerdict(\n candidate: ExperimentStats,\n parent: ExperimentStats | null,\n thresholds?: ImprovementThresholds,\n): ImprovementVerdictResult {\n const t = resolveThresholds(thresholds)\n if (!parent) {\n return {\n verdict: 'ITERATE',\n medianDelta: null,\n reason: 'no parent experiment to compare against',\n }\n }\n if (candidate.n < t.minRepsForVerdict || parent.n < t.minRepsForVerdict) {\n return {\n verdict: 'ITERATE',\n medianDelta: null,\n reason: `need >= ${t.minRepsForVerdict} reps on both sides (candidate n=${candidate.n}, parent n=${parent.n})`,\n }\n }\n if (!candidate.stable) {\n return {\n verdict: 'NOISE',\n medianDelta: candidate.median - parent.median,\n reason: `candidate unstable (iqr=${candidate.iqr}, stddev=${candidate.stddev.toFixed(2)})`,\n }\n }\n const medianDelta = candidate.median - parent.median\n if (medianDelta > t.keepThreshold) {\n return { verdict: 'KEEP', medianDelta, reason: `median +${medianDelta} > +${t.keepThreshold}` }\n }\n if (medianDelta < -t.regressionThreshold) {\n return {\n verdict: 'REGRESSION',\n medianDelta,\n reason: `median ${medianDelta} < -${t.regressionThreshold}`,\n }\n }\n return {\n verdict: 'NOISE',\n medianDelta,\n reason: `median delta ${medianDelta} inside noise band [-${t.regressionThreshold}, +${t.keepThreshold}]`,\n }\n}\n\n// ── Provenance + persistence seams ───────────────────────────────────\n\n/** Reads git provenance for the working tree. Inject a fake in tests; the\n * default implementation shells out to `git`. */\nexport type ProvenanceReader = () => ExperimentProvenance | Promise<ExperimentProvenance>\n\n/** Persistence seam for the experiment log. Inject in-memory in tests; the\n * filesystem implementation is `fileExperimentStore`. */\nexport interface ExperimentStore {\n load(): Promise<Experiment[]>\n save(experiments: Experiment[]): Promise<void>\n}\n\n/**\n * Default provenance reader: `git rev-parse HEAD`, the subject line, and the\n * files changed vs `HEAD~1`. Fail-loud — a tracker that silently logs\n * `commit: 'unknown'` corrupts the provenance the whole point of the log is to\n * carry. When the working tree genuinely has no parent commit, pass an override.\n */\nexport const gitProvenanceReader: ProvenanceReader = () => {\n const run = (cmd: string): string => execSync(cmd, { encoding: 'utf8' }).trim()\n const commit = run('git rev-parse --short HEAD')\n const message = run('git log -1 --format=%s')\n const changedRaw = run('git diff --name-only HEAD~1')\n const changedFiles = changedRaw.length === 0 ? [] : changedRaw.split('\\n').filter(Boolean)\n return { commit, message, changedFiles }\n}\n\n/** In-memory store — the default when no persistence is wanted (tests, ephemeral\n * runs). State lives on the instance. */\nexport function inMemoryExperimentStore(initial: Experiment[] = []): ExperimentStore {\n let state = initial.map((e) => structuredClone(e))\n return {\n async load() {\n return state.map((e) => structuredClone(e))\n },\n async save(experiments) {\n state = experiments.map((e) => structuredClone(e))\n },\n }\n}\n\n/** Filesystem store — a single JSON array at `path`, created on first save. */\nexport function fileExperimentStore(path: string): ExperimentStore {\n return {\n async load() {\n const fs = await import('node:fs/promises')\n try {\n const raw = await fs.readFile(path, 'utf8')\n const parsed = JSON.parse(raw)\n if (!Array.isArray(parsed)) {\n throw new ValidationError(`experiment-tracker: store at ${path} is not a JSON array`)\n }\n return parsed as Experiment[]\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw err\n }\n },\n async save(experiments) {\n const fs = await import('node:fs/promises')\n const pathMod = await import('node:path')\n await fs.mkdir(pathMod.dirname(path), { recursive: true })\n await fs.writeFile(path, JSON.stringify(experiments, null, 2), 'utf8')\n },\n }\n}\n\nexport interface ExperimentTrackerOptions {\n store?: ExperimentStore\n provenanceReader?: ProvenanceReader\n thresholds?: ImprovementThresholds\n /** Clock seam for deterministic timestamps in tests. Default `Date.now`. */\n now?: () => number\n}\n\nexport interface CreateExperimentInput {\n id: string\n label: string\n changeSummary: string\n parentId?: string\n /** Override provenance instead of reading from git (e.g. CI metadata). */\n provenance?: ExperimentProvenance\n}\n\n/**\n * Stateful tracker over an `ExperimentStore`. Create an experiment (provenance\n * is captured once), append reps as they complete (stats + verdict recompute on\n * every append), and read the log back for a dashboard. All persistence and git\n * access flow through the injected seams, so the tracker is fully testable\n * without a repo or disk.\n */\nexport class ExperimentTracker {\n private readonly store: ExperimentStore\n private readonly provenanceReader: ProvenanceReader\n private readonly thresholds: Required<ImprovementThresholds>\n private readonly now: () => number\n\n constructor(options: ExperimentTrackerOptions = {}) {\n this.store = options.store ?? inMemoryExperimentStore()\n this.provenanceReader = options.provenanceReader ?? gitProvenanceReader\n this.thresholds = resolveThresholds(options.thresholds)\n this.now = options.now ?? Date.now\n }\n\n async create(input: CreateExperimentInput): Promise<Experiment> {\n const experiments = await this.store.load()\n if (experiments.some((e) => e.id === input.id)) {\n throw new ValidationError(`experiment-tracker: experiment id \"${input.id}\" already exists`)\n }\n if (input.parentId && !experiments.some((e) => e.id === input.parentId)) {\n throw new ValidationError(\n `experiment-tracker: parent experiment \"${input.parentId}\" not found`,\n )\n }\n const provenance = input.provenance ?? (await this.provenanceReader())\n const experiment: Experiment = {\n id: input.id,\n label: input.label,\n provenance,\n parentId: input.parentId,\n changeSummary: input.changeSummary,\n reps: [],\n stats: computeExperimentStats([], this.thresholds),\n verdict: 'ITERATE',\n createdAt: new Date(this.now()).toISOString(),\n }\n experiments.push(experiment)\n await this.store.save(experiments)\n return structuredClone(experiment)\n }\n\n /** Append a rep (its `rep` index defaults to the current rep count) and\n * recompute stats + verdict. Returns the updated experiment. */\n async addRep(\n experimentId: string,\n rep: Omit<ExperimentRep, 'rep' | 'timestamp'> & { rep?: number; timestamp?: string },\n ): Promise<Experiment> {\n const experiments = await this.store.load()\n const exp = experiments.find((e) => e.id === experimentId)\n if (!exp)\n throw new ValidationError(`experiment-tracker: experiment \"${experimentId}\" not found`)\n const fullRep: ExperimentRep = {\n rep: rep.rep ?? exp.reps.length,\n score: rep.score,\n passed: rep.passed,\n metrics: rep.metrics,\n timestamp: rep.timestamp ?? new Date(this.now()).toISOString(),\n }\n exp.reps.push(fullRep)\n exp.stats = computeExperimentStats(exp.reps, this.thresholds)\n const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : undefined\n exp.verdict = improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds).verdict\n await this.store.save(experiments)\n return structuredClone(exp)\n }\n\n async get(experimentId: string): Promise<Experiment | undefined> {\n const experiments = await this.store.load()\n const found = experiments.find((e) => e.id === experimentId)\n return found ? structuredClone(found) : undefined\n }\n\n async list(): Promise<Experiment[]> {\n return this.store.load()\n }\n\n /** Full verdict (not just the enum) for an experiment vs its parent. */\n async verdictFor(experimentId: string): Promise<ImprovementVerdictResult> {\n const experiments = await this.store.load()\n const exp = experiments.find((e) => e.id === experimentId)\n if (!exp)\n throw new ValidationError(`experiment-tracker: experiment \"${experimentId}\" not found`)\n const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : undefined\n return improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"experiment-tracker-IMntXr6J.d.ts","names":[],"sources":["../src/clustered-paired-binary.ts","../src/experiment-tracker.ts"],"mappings":";;;;;;;;;KAaY;UAEK,6BAA6B;;EAE5C;;EAEA;;EAEA,UAAU,KAAK;;EAEf,aAAa,KAAK;;EAElB,MAAM,KAAK;;EAEX,OAAO,KAAK;;EAEZ,UAAU,KAAK;;EAEf;;EAEA;;EAEA;;EAEA,cAAc;;;;;EAKd;;EAEA;;UAGe,qBAAqB;EACpC;EACA;EACA;EACA,UAAU;EACV,WAAW;EACX;EACA;;UAGe;EACf;EACA;;EAEA;;EAEA;;EAEA;;UAGe;;EAEf;EACA;EACA;EACA;EACA;EACA;;UAGe;;EAEf;;;;;;EAMA;EACA,aAAa;EACb;;EAEA;EACA;EACA;;EAEA;;UAGe;EACf;EACA;;EAEA;;EAEA;;EAEA;;EAEA;EACA,UAAU;;EAEV,WAAW;EACX,UAAU;;UAGK,4BAA4B;EAC3C,cAAc,qBAAqB;EACnC,kBAAkB;EAClB,mBAAmB;;EAEnB,YAAY;;;;;;;;iBAoBE,sBAAsB,MACpC,eAAe,QACf,SAAS,6BAA6B,QACrC,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;KChHnB;;UAGK;;EAEf;;EAEA;;EAEA;;;;UAKe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA,UAAU;;UAGK;EACf;EACA;EACA;EACA;;EAEA;;EAEA;;;EAGA;;EAEA;;EAEA;;UAGe;;EAEf;;EAEA;;EAEA,YAAY;;EAEZ;;EAEA;EACA,MAAM;EACN,OAAO;EACP,SAAS;;EAET;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA;;;EAGA;;UAGe;EACf,SAAS;;EAET;;EAEA;;;;;;;iBAkDc,uBACd,MAAM,iBACN,aAAa,wBACZ;;;;;;;iBAgDa,mBACd,WAAW,iBACX,QAAQ,wBACR,aAAa,wBACZ;;;KA6CS,yBAAyB,uBAAuB,QAAQ;;;UAInD;EACf,QAAQ,QAAQ;EAChB,KAAK,aAAa,eAAe;;;;;;;;cAStB,qBAAqB;;;iBAWlB,wBAAwB,UAAS,eAAoB;;iBAarD,oBAAoB,eAAe;UAyBlC;EACf,QAAQ;EACR,mBAAmB;EACnB,aAAa;;EAEb;;UAGe;EACf;EACA;EACA;EACA;;EAEA,aAAa;;;;;;;;;cAUF;mBACM;mBACA;mBACA;mBACA;EAEjB,YAAY,UAAS;EAOf,OAAO,OAAO,wBAAwB,QAAQ;;;EA6B9C,OACJ,sBACA,KAAK,KAAK;IAAwC;IAAc;MAC/D,QAAQ;EAoBL,IAAI,uBAAuB,QAAQ;EAMnC,QAAQ,QAAQ;;EAKhB,WAAW,uBAAuB,QAAQ"}
|