@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
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { s as ValidationError } from "./errors-Dngq5h35.js";
|
|
2
|
+
import { n as iqr } from "./baseline-BhPRQBVn.js";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
//#region src/experiment-tracker.ts
|
|
5
|
+
/**
|
|
6
|
+
* Experiment tracker — git-provenanced experiment log with N-rep stats and a
|
|
7
|
+
* KEEP / REGRESSION / NOISE verdict against a parent.
|
|
8
|
+
*
|
|
9
|
+
* Every loop the fleet runs reduces to the same question: "I ran the candidate
|
|
10
|
+
* N times — is the median measurably better than the parent, or is the delta
|
|
11
|
+
* inside the noise band?" The hand-rolled copies bake a fixed score scale
|
|
12
|
+
* (percentage points), a fixed store path (`.evolve/experiments-v2.json`), and
|
|
13
|
+
* `execSync('git …')` straight into the module. This is the canonical version:
|
|
14
|
+
* provenance and persistence are injected, thresholds are configurable, and the
|
|
15
|
+
* stats + verdict are pure functions you can unit-test without a git repo or a
|
|
16
|
+
* filesystem.
|
|
17
|
+
*
|
|
18
|
+
* Stats per experiment: median / mean / min / max / iqr / stddev / passRate /
|
|
19
|
+
* n, plus a `stable` flag (`iqr < iqrUnstableAbove && stddev < stddevUnstableAbove`).
|
|
20
|
+
*
|
|
21
|
+
* Verdict against a parent (both must have `n >= minRepsForVerdict`):
|
|
22
|
+
* - NOISE — the candidate is too unstable to judge (`!stable`)
|
|
23
|
+
* - KEEP — `medianDelta > keepThreshold`
|
|
24
|
+
* - REGRESSION — `medianDelta < -regressionThreshold`
|
|
25
|
+
* - NOISE — otherwise (delta inside the band)
|
|
26
|
+
* With no parent (or insufficient reps) the verdict is the neutral ITERATE.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULTS = {
|
|
29
|
+
keepThreshold: 5,
|
|
30
|
+
regressionThreshold: 5,
|
|
31
|
+
iqrUnstableAbove: 10,
|
|
32
|
+
stddevUnstableAbove: Number.POSITIVE_INFINITY,
|
|
33
|
+
minRepsForVerdict: 3
|
|
34
|
+
};
|
|
35
|
+
function resolveThresholds(t) {
|
|
36
|
+
const r = {
|
|
37
|
+
...DEFAULTS,
|
|
38
|
+
...t ?? {}
|
|
39
|
+
};
|
|
40
|
+
if (r.keepThreshold < 0) throw new ValidationError(`experiment-tracker: keepThreshold must be >= 0, got ${r.keepThreshold}`);
|
|
41
|
+
if (r.regressionThreshold < 0) throw new ValidationError(`experiment-tracker: regressionThreshold must be >= 0, got ${r.regressionThreshold}`);
|
|
42
|
+
if (r.minRepsForVerdict < 1) throw new ValidationError(`experiment-tracker: minRepsForVerdict must be >= 1, got ${r.minRepsForVerdict}`);
|
|
43
|
+
return r;
|
|
44
|
+
}
|
|
45
|
+
function median(sorted) {
|
|
46
|
+
const n = sorted.length;
|
|
47
|
+
if (n === 0) return 0;
|
|
48
|
+
const mid = Math.floor(n / 2);
|
|
49
|
+
return n % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
50
|
+
}
|
|
51
|
+
/** Population standard deviation (÷n). 0 for fewer than 2 values. */
|
|
52
|
+
function stddev(values, mean) {
|
|
53
|
+
if (values.length < 2) return 0;
|
|
54
|
+
const variance = values.reduce((acc, v) => acc + (v - mean) ** 2, 0) / values.length;
|
|
55
|
+
return Math.sqrt(variance);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Compute the N-rep statistics for a set of reps. Pure — no I/O. The `stable`
|
|
59
|
+
* flag is the trust gate the verdict depends on: a sample whose spread exceeds
|
|
60
|
+
* the configured bounds can't distinguish a real delta from run-to-run noise.
|
|
61
|
+
*/
|
|
62
|
+
function computeExperimentStats(reps, thresholds) {
|
|
63
|
+
const t = resolveThresholds(thresholds);
|
|
64
|
+
const n = reps.length;
|
|
65
|
+
if (n === 0) return {
|
|
66
|
+
median: 0,
|
|
67
|
+
mean: 0,
|
|
68
|
+
min: 0,
|
|
69
|
+
max: 0,
|
|
70
|
+
iqr: 0,
|
|
71
|
+
stddev: 0,
|
|
72
|
+
passRate: null,
|
|
73
|
+
n: 0,
|
|
74
|
+
stable: false
|
|
75
|
+
};
|
|
76
|
+
const scores = reps.map((r) => {
|
|
77
|
+
if (!Number.isFinite(r.score)) throw new ValidationError(`experiment-tracker: rep ${r.rep} has non-finite score ${r.score}`);
|
|
78
|
+
return r.score;
|
|
79
|
+
});
|
|
80
|
+
const sorted = [...scores].sort((a, b) => a - b);
|
|
81
|
+
const mean = scores.reduce((s, v) => s + v, 0) / n;
|
|
82
|
+
const sd = stddev(scores, mean);
|
|
83
|
+
const spread = iqr(scores);
|
|
84
|
+
const rated = reps.filter((r) => typeof r.passed === "boolean");
|
|
85
|
+
const passRate = rated.length === 0 ? null : rated.filter((r) => r.passed).length / rated.length;
|
|
86
|
+
const stable = spread < t.iqrUnstableAbove && sd < t.stddevUnstableAbove;
|
|
87
|
+
return {
|
|
88
|
+
median: median(sorted),
|
|
89
|
+
mean,
|
|
90
|
+
min: sorted[0],
|
|
91
|
+
max: sorted[n - 1],
|
|
92
|
+
iqr: spread,
|
|
93
|
+
stddev: sd,
|
|
94
|
+
passRate,
|
|
95
|
+
n,
|
|
96
|
+
stable
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Verdict for a candidate against its parent. Pure — operates on already-computed
|
|
101
|
+
* stats. KEEP/REGRESSION require both sides to have `>= minRepsForVerdict` reps
|
|
102
|
+
* AND the candidate to be `stable`; otherwise the result is NOISE (unstable) or
|
|
103
|
+
* ITERATE (not enough reps / no parent).
|
|
104
|
+
*/
|
|
105
|
+
function improvementVerdict(candidate, parent, thresholds) {
|
|
106
|
+
const t = resolveThresholds(thresholds);
|
|
107
|
+
if (!parent) return {
|
|
108
|
+
verdict: "ITERATE",
|
|
109
|
+
medianDelta: null,
|
|
110
|
+
reason: "no parent experiment to compare against"
|
|
111
|
+
};
|
|
112
|
+
if (candidate.n < t.minRepsForVerdict || parent.n < t.minRepsForVerdict) return {
|
|
113
|
+
verdict: "ITERATE",
|
|
114
|
+
medianDelta: null,
|
|
115
|
+
reason: `need >= ${t.minRepsForVerdict} reps on both sides (candidate n=${candidate.n}, parent n=${parent.n})`
|
|
116
|
+
};
|
|
117
|
+
if (!candidate.stable) return {
|
|
118
|
+
verdict: "NOISE",
|
|
119
|
+
medianDelta: candidate.median - parent.median,
|
|
120
|
+
reason: `candidate unstable (iqr=${candidate.iqr}, stddev=${candidate.stddev.toFixed(2)})`
|
|
121
|
+
};
|
|
122
|
+
const medianDelta = candidate.median - parent.median;
|
|
123
|
+
if (medianDelta > t.keepThreshold) return {
|
|
124
|
+
verdict: "KEEP",
|
|
125
|
+
medianDelta,
|
|
126
|
+
reason: `median +${medianDelta} > +${t.keepThreshold}`
|
|
127
|
+
};
|
|
128
|
+
if (medianDelta < -t.regressionThreshold) return {
|
|
129
|
+
verdict: "REGRESSION",
|
|
130
|
+
medianDelta,
|
|
131
|
+
reason: `median ${medianDelta} < -${t.regressionThreshold}`
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
verdict: "NOISE",
|
|
135
|
+
medianDelta,
|
|
136
|
+
reason: `median delta ${medianDelta} inside noise band [-${t.regressionThreshold}, +${t.keepThreshold}]`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Default provenance reader: `git rev-parse HEAD`, the subject line, and the
|
|
141
|
+
* files changed vs `HEAD~1`. Fail-loud — a tracker that silently logs
|
|
142
|
+
* `commit: 'unknown'` corrupts the provenance the whole point of the log is to
|
|
143
|
+
* carry. When the working tree genuinely has no parent commit, pass an override.
|
|
144
|
+
*/
|
|
145
|
+
const gitProvenanceReader = () => {
|
|
146
|
+
const run = (cmd) => execSync(cmd, { encoding: "utf8" }).trim();
|
|
147
|
+
const commit = run("git rev-parse --short HEAD");
|
|
148
|
+
const message = run("git log -1 --format=%s");
|
|
149
|
+
const changedRaw = run("git diff --name-only HEAD~1");
|
|
150
|
+
return {
|
|
151
|
+
commit,
|
|
152
|
+
message,
|
|
153
|
+
changedFiles: changedRaw.length === 0 ? [] : changedRaw.split("\n").filter(Boolean)
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
/** In-memory store — the default when no persistence is wanted (tests, ephemeral
|
|
157
|
+
* runs). State lives on the instance. */
|
|
158
|
+
function inMemoryExperimentStore(initial = []) {
|
|
159
|
+
let state = initial.map((e) => structuredClone(e));
|
|
160
|
+
return {
|
|
161
|
+
async load() {
|
|
162
|
+
return state.map((e) => structuredClone(e));
|
|
163
|
+
},
|
|
164
|
+
async save(experiments) {
|
|
165
|
+
state = experiments.map((e) => structuredClone(e));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/** Filesystem store — a single JSON array at `path`, created on first save. */
|
|
170
|
+
function fileExperimentStore(path) {
|
|
171
|
+
return {
|
|
172
|
+
async load() {
|
|
173
|
+
const fs = await import("node:fs/promises");
|
|
174
|
+
try {
|
|
175
|
+
const raw = await fs.readFile(path, "utf8");
|
|
176
|
+
const parsed = JSON.parse(raw);
|
|
177
|
+
if (!Array.isArray(parsed)) throw new ValidationError(`experiment-tracker: store at ${path} is not a JSON array`);
|
|
178
|
+
return parsed;
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if (err.code === "ENOENT") return [];
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
async save(experiments) {
|
|
185
|
+
const fs = await import("node:fs/promises");
|
|
186
|
+
const pathMod = await import("node:path");
|
|
187
|
+
await fs.mkdir(pathMod.dirname(path), { recursive: true });
|
|
188
|
+
await fs.writeFile(path, JSON.stringify(experiments, null, 2), "utf8");
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Stateful tracker over an `ExperimentStore`. Create an experiment (provenance
|
|
194
|
+
* is captured once), append reps as they complete (stats + verdict recompute on
|
|
195
|
+
* every append), and read the log back for a dashboard. All persistence and git
|
|
196
|
+
* access flow through the injected seams, so the tracker is fully testable
|
|
197
|
+
* without a repo or disk.
|
|
198
|
+
*/
|
|
199
|
+
var ExperimentTracker = class {
|
|
200
|
+
store;
|
|
201
|
+
provenanceReader;
|
|
202
|
+
thresholds;
|
|
203
|
+
now;
|
|
204
|
+
constructor(options = {}) {
|
|
205
|
+
this.store = options.store ?? inMemoryExperimentStore();
|
|
206
|
+
this.provenanceReader = options.provenanceReader ?? gitProvenanceReader;
|
|
207
|
+
this.thresholds = resolveThresholds(options.thresholds);
|
|
208
|
+
this.now = options.now ?? Date.now;
|
|
209
|
+
}
|
|
210
|
+
async create(input) {
|
|
211
|
+
const experiments = await this.store.load();
|
|
212
|
+
if (experiments.some((e) => e.id === input.id)) throw new ValidationError(`experiment-tracker: experiment id "${input.id}" already exists`);
|
|
213
|
+
if (input.parentId && !experiments.some((e) => e.id === input.parentId)) throw new ValidationError(`experiment-tracker: parent experiment "${input.parentId}" not found`);
|
|
214
|
+
const provenance = input.provenance ?? await this.provenanceReader();
|
|
215
|
+
const experiment = {
|
|
216
|
+
id: input.id,
|
|
217
|
+
label: input.label,
|
|
218
|
+
provenance,
|
|
219
|
+
parentId: input.parentId,
|
|
220
|
+
changeSummary: input.changeSummary,
|
|
221
|
+
reps: [],
|
|
222
|
+
stats: computeExperimentStats([], this.thresholds),
|
|
223
|
+
verdict: "ITERATE",
|
|
224
|
+
createdAt: new Date(this.now()).toISOString()
|
|
225
|
+
};
|
|
226
|
+
experiments.push(experiment);
|
|
227
|
+
await this.store.save(experiments);
|
|
228
|
+
return structuredClone(experiment);
|
|
229
|
+
}
|
|
230
|
+
/** Append a rep (its `rep` index defaults to the current rep count) and
|
|
231
|
+
* recompute stats + verdict. Returns the updated experiment. */
|
|
232
|
+
async addRep(experimentId, rep) {
|
|
233
|
+
const experiments = await this.store.load();
|
|
234
|
+
const exp = experiments.find((e) => e.id === experimentId);
|
|
235
|
+
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
236
|
+
const fullRep = {
|
|
237
|
+
rep: rep.rep ?? exp.reps.length,
|
|
238
|
+
score: rep.score,
|
|
239
|
+
passed: rep.passed,
|
|
240
|
+
metrics: rep.metrics,
|
|
241
|
+
timestamp: rep.timestamp ?? new Date(this.now()).toISOString()
|
|
242
|
+
};
|
|
243
|
+
exp.reps.push(fullRep);
|
|
244
|
+
exp.stats = computeExperimentStats(exp.reps, this.thresholds);
|
|
245
|
+
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
246
|
+
exp.verdict = improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds).verdict;
|
|
247
|
+
await this.store.save(experiments);
|
|
248
|
+
return structuredClone(exp);
|
|
249
|
+
}
|
|
250
|
+
async get(experimentId) {
|
|
251
|
+
const found = (await this.store.load()).find((e) => e.id === experimentId);
|
|
252
|
+
return found ? structuredClone(found) : void 0;
|
|
253
|
+
}
|
|
254
|
+
async list() {
|
|
255
|
+
return this.store.load();
|
|
256
|
+
}
|
|
257
|
+
/** Full verdict (not just the enum) for an experiment vs its parent. */
|
|
258
|
+
async verdictFor(experimentId) {
|
|
259
|
+
const experiments = await this.store.load();
|
|
260
|
+
const exp = experiments.find((e) => e.id === experimentId);
|
|
261
|
+
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
262
|
+
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
263
|
+
return improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
//#endregion
|
|
267
|
+
export { inMemoryExperimentStore as a, improvementVerdict as i, computeExperimentStats as n, fileExperimentStore as r, ExperimentTracker as t };
|
|
268
|
+
|
|
269
|
+
//# sourceMappingURL=experiment-tracker-C29gXM4B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiment-tracker-C29gXM4B.js","names":[],"sources":["../src/experiment-tracker.ts"],"sourcesContent":["/**\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,120 +1,83 @@
|
|
|
1
|
-
//#region src/
|
|
1
|
+
//#region src/statistics/power-and-mde.d.ts
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Required N per arm for a two-sample comparison at target effect size,
|
|
4
|
+
* alpha, and power. Normal-approximation formula:
|
|
5
|
+
* n = 2 * ( (z_{1-α/2} + z_{1-β}) / d )^2
|
|
6
|
+
* where d is Cohen's d. Returns Infinity for effect ≤ 0.
|
|
7
|
+
*/
|
|
8
|
+
declare function requiredSampleSize(opts: {
|
|
9
|
+
effect: number;
|
|
10
|
+
alpha?: number;
|
|
11
|
+
power?: number;
|
|
12
|
+
twoSided?: boolean;
|
|
13
|
+
}): number;
|
|
14
|
+
/**
|
|
15
|
+
* Required number of paired observations for a target Cohen's dz.
|
|
16
|
+
* Unlike the independent-groups formula, this has no two-arm factor of two.
|
|
4
17
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
18
|
+
* Normal quantiles with no t correction, so treat the result as a LOWER bound:
|
|
19
|
+
* it returns 32 where the exact t-based answer is 34 at dz = 0.5, and 13 where
|
|
20
|
+
* it is 15 at dz = 0.8 — a 6–13 % shortfall precisely in the range a caller
|
|
21
|
+
* consults to decide whether 3–10 repetitions suffice.
|
|
9
22
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
treatmentPass: boolean;
|
|
50
|
-
}
|
|
51
|
-
interface ClusteredBinaryCluster {
|
|
52
|
-
clusterKey: string;
|
|
53
|
-
nPairs: number;
|
|
54
|
-
/** Treatment passes and baseline fails. */
|
|
55
|
-
b10: number;
|
|
56
|
-
/** Baseline passes and treatment fails. */
|
|
57
|
-
b01: number;
|
|
58
|
-
/** Mean (treatment - baseline) binary outcome within this cluster. */
|
|
59
|
-
meanDifference: number;
|
|
60
|
-
}
|
|
61
|
-
interface ClusterBootstrapInterval {
|
|
62
|
-
/** The interval resamples clusters and recomputes this task-weighted statistic. */
|
|
63
|
-
statistic: 'task-weighted-risk-difference';
|
|
64
|
-
lower: number;
|
|
65
|
-
upper: number;
|
|
66
|
-
confidence: number;
|
|
67
|
-
resamples: number;
|
|
68
|
-
seed: number;
|
|
69
|
-
}
|
|
70
|
-
interface ClusterSignFlipResult {
|
|
71
|
-
/** Task-weighted paired risk difference, matching the reported bootstrap estimand. */
|
|
72
|
-
statistic: number;
|
|
73
|
-
/**
|
|
74
|
-
* Randomization p-value under whole-cluster arm-label exchangeability.
|
|
75
|
-
* `method: 'exact'` means every cluster-level sign assignment was enumerated;
|
|
76
|
-
* it does not make the exchangeability assumption unnecessary.
|
|
77
|
-
*/
|
|
78
|
-
pValue: number;
|
|
79
|
-
alternative: ClusterSignFlipAlternative;
|
|
80
|
-
method: 'exact' | 'monte-carlo';
|
|
81
|
-
/** Exact assignments enumerated or Monte Carlo assignments drawn. */
|
|
82
|
-
assignments: number;
|
|
83
|
-
nClusters: number;
|
|
84
|
-
nNonZeroClusters: number;
|
|
85
|
-
/** Null for exact enumeration, which has no random draws. */
|
|
86
|
-
seed: number | null;
|
|
87
|
-
}
|
|
88
|
-
interface ClusteredPairedBinaryStatistics {
|
|
89
|
-
nPairs: number;
|
|
90
|
-
nClusters: number;
|
|
91
|
-
/** Treatment passes and baseline fails, across all matched pairs. */
|
|
92
|
-
b10: number;
|
|
93
|
-
/** Baseline passes and treatment fails, across all matched pairs. */
|
|
94
|
-
b01: number;
|
|
95
|
-
/** Mean paired difference across tasks, so every task has equal weight. */
|
|
96
|
-
taskWeightedRiskDifference: number;
|
|
97
|
-
/** Mean of cluster-level paired differences, so every cluster has equal weight. */
|
|
98
|
-
equalClusterMean: number;
|
|
99
|
-
clusters: ClusteredBinaryCluster[];
|
|
100
|
-
/** Null below two independent clusters; one cluster cannot estimate cluster uncertainty. */
|
|
101
|
-
bootstrap: ClusterBootstrapInterval | null;
|
|
102
|
-
signFlip: ClusterSignFlipResult;
|
|
103
|
-
}
|
|
104
|
-
interface ClusteredPairedBinaryResult<TRow> {
|
|
105
|
-
matchedPairs: ClusteredMatchedPair<TRow>[];
|
|
106
|
-
unpairedBaseline: TRow[];
|
|
107
|
-
unpairedTreatment: TRow[];
|
|
108
|
-
/** Null when there are no matched rows; absence is never reported as a zero effect. */
|
|
109
|
-
statistics: ClusteredPairedBinaryStatistics | null;
|
|
110
|
-
}
|
|
23
|
+
declare function requiredPairedSampleSize(opts: {
|
|
24
|
+
effect: number;
|
|
25
|
+
alpha?: number;
|
|
26
|
+
power?: number;
|
|
27
|
+
twoSided?: boolean;
|
|
28
|
+
}): number;
|
|
29
|
+
/**
|
|
30
|
+
* Minimum detectable paired effect (standardised units) for a target paired
|
|
31
|
+
* sample size: d_min = (z_{1-α/2} + z_β) / sqrt(n_paired). Multiply by
|
|
32
|
+
* sd(deltas) for score units; treat as a lower bound — Wilcoxon and bootstrap
|
|
33
|
+
* have asymptotic relative efficiency below 1 vs the t-test on heavy tails.
|
|
34
|
+
*/
|
|
35
|
+
declare function pairedMde(opts: {
|
|
36
|
+
nPaired: number;
|
|
37
|
+
alpha?: number;
|
|
38
|
+
power?: number;
|
|
39
|
+
twoSided?: boolean;
|
|
40
|
+
}): number;
|
|
41
|
+
/**
|
|
42
|
+
* Number of paired observations needed for a McNemar test to reach a target
|
|
43
|
+
* power — the pre-registration companion to {@link mcnemar}. Parametrised by the
|
|
44
|
+
* expected discordant-cell probabilities `p10` (P[treatment wins on a pair]) and
|
|
45
|
+
* `p01` (P[control wins]); concordant pairs carry no information, so the count
|
|
46
|
+
* is driven entirely by the discordant rate. Lachin's (1992) asymptotic normal
|
|
47
|
+
* approximation: with discordant rate `pDisc = p10 + p01` and marginal effect
|
|
48
|
+
* `δ = p10 − p01`,
|
|
49
|
+
* n = ( z_{1-α/2}·√pDisc + z_{1-β}·√(pDisc − δ²) )² / δ².
|
|
50
|
+
* Returns Infinity when there is no effect (p10 === p01). Asymptotic — at the
|
|
51
|
+
* tiny discordant counts where the exact {@link mcnemar} differs from the normal
|
|
52
|
+
* approximation, treat the result as a lower bound and prefer the discordant-pair
|
|
53
|
+
* floor.
|
|
54
|
+
*/
|
|
55
|
+
declare function mcnemarRequiredN(opts: {
|
|
56
|
+
p10: number;
|
|
57
|
+
p01: number;
|
|
58
|
+
alpha?: number;
|
|
59
|
+
power?: number;
|
|
60
|
+
twoSided?: boolean;
|
|
61
|
+
}): number;
|
|
111
62
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* totals and tests that same task-weighted estimand.
|
|
63
|
+
* Power of a McNemar test at a given number of paired observations, the inverse
|
|
64
|
+
* of {@link mcnemarRequiredN} (same Lachin asymptotic model, same parameters).
|
|
65
|
+
* Returns a value in [0, 1]; equals `alpha` when there is no effect.
|
|
116
66
|
*/
|
|
117
|
-
declare function
|
|
67
|
+
declare function mcnemarPower(opts: {
|
|
68
|
+
p10: number;
|
|
69
|
+
p01: number;
|
|
70
|
+
nPairs: number;
|
|
71
|
+
alpha?: number;
|
|
72
|
+
twoSided?: boolean;
|
|
73
|
+
}): number;
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/statistics/random.d.ts
|
|
76
|
+
/** Tiny seedable PRNG (mulberry32) — deterministic resampling/shuffling, not
|
|
77
|
+
* cryptographic. Exported so e-process shuffles and bootstrap resampling
|
|
78
|
+
* share ONE PRNG implementation. Every distinct 32-bit seed gives a distinct
|
|
79
|
+
* stream, including 0. */
|
|
80
|
+
declare function mulberry32(seed: number): () => number;
|
|
118
81
|
//#endregion
|
|
119
82
|
//#region src/experiment-tracker.d.ts
|
|
120
83
|
/**
|
|
@@ -242,13 +205,6 @@ interface ExperimentStore {
|
|
|
242
205
|
load(): Promise<Experiment[]>;
|
|
243
206
|
save(experiments: Experiment[]): Promise<void>;
|
|
244
207
|
}
|
|
245
|
-
/**
|
|
246
|
-
* Default provenance reader: `git rev-parse HEAD`, the subject line, and the
|
|
247
|
-
* files changed vs `HEAD~1`. Fail-loud — a tracker that silently logs
|
|
248
|
-
* `commit: 'unknown'` corrupts the provenance the whole point of the log is to
|
|
249
|
-
* carry. When the working tree genuinely has no parent commit, pass an override.
|
|
250
|
-
*/
|
|
251
|
-
declare const gitProvenanceReader: ProvenanceReader;
|
|
252
208
|
/** In-memory store — the default when no persistence is wanted (tests, ephemeral
|
|
253
209
|
* runs). State lives on the instance. */
|
|
254
210
|
declare function inMemoryExperimentStore(initial?: Experiment[]): ExperimentStore;
|
|
@@ -295,5 +251,5 @@ declare class ExperimentTracker {
|
|
|
295
251
|
verdictFor(experimentId: string): Promise<ImprovementVerdictResult>;
|
|
296
252
|
}
|
|
297
253
|
//#endregion
|
|
298
|
-
export {
|
|
299
|
-
//# sourceMappingURL=experiment-tracker-
|
|
254
|
+
export { requiredSampleSize as _, ExperimentVerdict as a, computeExperimentStats as c, inMemoryExperimentStore as d, mulberry32 as f, requiredPairedSampleSize as g, pairedMde as h, ExperimentTracker as i, fileExperimentStore as l, mcnemarRequiredN as m, ExperimentRep as n, ImprovementThresholds as o, mcnemarPower as p, ExperimentStats as r, ImprovementVerdictResult as s, Experiment as t, improvementVerdict as u };
|
|
255
|
+
//# sourceMappingURL=experiment-tracker-DWHZBAYL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiment-tracker-DWHZBAYL.d.ts","names":[],"sources":["../src/statistics/power-and-mde.ts","../src/statistics/random.ts","../src/experiment-tracker.ts"],"mappings":";;;;;;;iBAWgB,mBAAmB;EACjC;EACA;EACA;EACA;;;;;;;;;;;iBAsBc,yBAAyB;EACvC;EACA;EACA;EACA;;;;;;;;iBAkBc,UAAU;EACxB;EACA;EACA;EACA;;;;;;;;;;;;;;;;iBAyBc,iBAAiB;EAC/B;EACA;EACA;EACA;EACA;;;;;;;iBAyBc,aAAa;EAC3B;EACA;EACA;EACA;EACA;;;;;;;;iBCrHc,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCwBf;;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;;;;iBAoBnB,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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as CustomTokenPricing, g as CostReceiptInput } from "./cost-ledger-
|
|
2
|
-
import {
|
|
1
|
+
import { b as CustomTokenPricing, g as CostReceiptInput } from "./cost-ledger-DbQdN3nO.js";
|
|
2
|
+
import { h as ChatResponse, m as ChatRequest } from "./types-Cx3YUh2r.js";
|
|
3
3
|
//#region src/campaign/external-optimizer-contracts.d.ts
|
|
4
4
|
interface ExternalOptimizerProcessLimits {
|
|
5
5
|
/** Maximum serialized input written for the child process. */
|
|
@@ -162,4 +162,4 @@ interface ExternalOptimizerModelBudget {
|
|
|
162
162
|
}
|
|
163
163
|
//#endregion
|
|
164
164
|
export { ExternalTextEvaluationRequest as _, ExternalOptimizerEndpointFormat as a, ExternalOptimizerModelBudget as c, ExternalOptimizerModelCallResult as d, ExternalOptimizerModelExecutionObservation as f, ExternalTextCandidate as g, ExternalOptimizerRunnerCommand as h, ExternalOptimizerChatRequest as i, ExternalOptimizerModelCall as l, ExternalOptimizerResumeMode as m, DEFAULT_EXTERNAL_OPTIMIZER_PROCESS_LIMITS as n, ExternalOptimizerEvaluationObservation as o, ExternalOptimizerProcessLimits as p, ExternalOptimizerCallbackLimits as r, ExternalOptimizerEvaluationRefusalReason as s, DEFAULT_EXTERNAL_OPTIMIZER_CALLBACK_LIMITS as t, ExternalOptimizerModelCallRequest as u, resolveExternalOptimizerCallbackLimits as v, resolveExternalOptimizerProcessLimits as y };
|
|
165
|
-
//# sourceMappingURL=external-optimizer-contracts-
|
|
165
|
+
//# sourceMappingURL=external-optimizer-contracts-lixrOZdX.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-optimizer-contracts-
|
|
1
|
+
{"version":3,"file":"external-optimizer-contracts-lixrOZdX.d.ts","names":[],"sources":["../src/campaign/external-optimizer-contracts.ts"],"mappings":";;;UAWiB;;EAEf;;EAEA;;EAEA;;cAGW,2CAA2C,SAAS;UAOhD;;EAEf;;EAEA;;cAGW,4CAA4C,SAAS;UAMjD;EACf;EACA;EACA,MAAM,OAAO;;EAEb,SAAS,QAAQ;;KAGP;KAEA,iCAAiC;UAE5B;EACf,WAAW;EACX;;iBAUc,sCACd,OAAO,QAAQ,6CACf,iBACC;iBAmBa,uCACd,OAAO,QAAQ,8CACf,iBACC;KAkBE,aAAa,KAAK,eAAc,6BACjC,IACA,0BAA0B,gBACf,aAAa,OACtB,+BACc,WAAW,IAAI,aAAa,EAAE,SAC1C;;KAGI,+BAA+B,aACzC,KAAK;EAA0B;;KAGrB;;UAGK;;WAEN;;WAEA,SAAS;;WAET,iBAAiB;WACjB,QAAQ;;;KAIP;WAEG;;WAEA,UAAU;;;;;;;WAOV,SAPU;;WASV;;WAGA;;WAEA;;WAEA,SATkC;;WAWlC;;;;;;;;;;;;KAaH,8BACV,SAAS,sCACN,QAAQ;;KAGD;WAEG;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGH;;;;;;KAUA;WAEG;WACA;WACA,WAAW;WACX;;WAGA;WACA;WACA,WAAW;WACX;WACA;;WAEA;WACA;;WAGA;WACA;WACA,QAAQ;WACR,YAAY;WACZ;WACA;;UAGE;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;;;;EAUA;;;;;;EAMA,UAAU;;EAEV"}
|