@tangle-network/agent-eval 0.187.2 → 0.189.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +95 -0
- package/dist/adapters/http.d.ts +2 -2
- package/dist/{agent-profile-uAIQK3Nr.d.ts → agent-profile-DNV_U6QR.d.ts} +4 -4
- package/dist/{agent-profile-uAIQK3Nr.d.ts.map → agent-profile-DNV_U6QR.d.ts.map} +1 -1
- package/dist/analyst/index.d.ts +12 -12
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +7 -7
- package/dist/{analyze-runs-DapYZz02.d.ts → analyze-runs-BvK4-wSs.d.ts} +5 -5
- package/dist/{analyze-runs-DapYZz02.d.ts.map → analyze-runs-BvK4-wSs.d.ts.map} +1 -1
- package/dist/{analyze-runs-DCY7LMt4.js → analyze-runs-SCSWYpy0.js} +17 -9
- package/dist/analyze-runs-SCSWYpy0.js.map +1 -0
- package/dist/{benchmark-command-DGokT8zd.js → benchmark-command-BhhAYstU.js} +14 -14
- package/dist/benchmark-command-BhhAYstU.js.map +1 -0
- package/dist/benchmarks/index.d.ts +4 -4
- package/dist/benchmarks/index.js +3 -3
- package/dist/builder-eval/index.d.ts +3 -3
- package/dist/builder-eval/index.js +1 -1
- package/dist/campaign/index.d.ts +5 -5
- package/dist/campaign/index.js +7 -7
- package/dist/{campaign-DlxdTOvw.js → campaign-BWoSQPSU.js} +10 -10
- package/dist/{campaign-DlxdTOvw.js.map → campaign-BWoSQPSU.js.map} +1 -1
- package/dist/{campaign-evidence-IF1p0oDa.js → campaign-evidence-CBlGJ3kC.js} +5 -5
- package/dist/campaign-evidence-CBlGJ3kC.js.map +1 -0
- package/dist/{chat-client-DqPqWzVV.js → chat-client-C4dg7Ng_.js} +2 -2
- package/dist/{chat-client-DqPqWzVV.js.map → chat-client-C4dg7Ng_.js.map} +1 -1
- package/dist/{chat-json-call-C-DnDxEy.js → chat-json-call-JVGbfx95.js} +2 -2
- package/dist/{chat-json-call-C-DnDxEy.js.map → chat-json-call-JVGbfx95.js.map} +1 -1
- package/dist/cli.js +4 -4
- package/dist/{client-DCc7a8ZC.d.ts → client-BhEyAdfe.d.ts} +4 -4
- package/dist/{client-DCc7a8ZC.d.ts.map → client-BhEyAdfe.d.ts.map} +1 -1
- package/dist/{client-CXE-U1SA.js → client-QwJpsNYU.js} +5 -1
- package/dist/client-QwJpsNYU.js.map +1 -0
- package/dist/contract/index.d.ts +11 -11
- package/dist/contract/index.js +22 -13
- package/dist/contract/index.js.map +1 -1
- package/dist/{counterfactual-CLgrwhkY.d.ts → counterfactual-CPaWN99-.d.ts} +4 -4
- package/dist/{counterfactual-CLgrwhkY.d.ts.map → counterfactual-CPaWN99-.d.ts.map} +1 -1
- package/dist/{counterfactual-Bjq1mlUu.js → counterfactual-DtMWvn7D.js} +2 -2
- package/dist/{counterfactual-Bjq1mlUu.js.map → counterfactual-DtMWvn7D.js.map} +1 -1
- package/dist/deep-freeze-CurcOQg3.js +16 -0
- package/dist/deep-freeze-CurcOQg3.js.map +1 -0
- package/dist/{default-registry-DMxeb4GD.d.ts → default-registry-B5HrwrPM.d.ts} +6 -6
- package/dist/{default-registry-DMxeb4GD.d.ts.map → default-registry-B5HrwrPM.d.ts.map} +1 -1
- package/dist/{default-registry-Ca2IWH1X.js → default-registry-m2jhbG6Q.js} +4 -3
- package/dist/default-registry-m2jhbG6Q.js.map +1 -0
- package/dist/{define-agent-eval-C0EqJ9Gz.js → define-agent-eval-98sgUaC1.js} +8 -8
- package/dist/{define-agent-eval-C0EqJ9Gz.js.map → define-agent-eval-98sgUaC1.js.map} +1 -1
- package/dist/{define-agent-eval-CGBwPPaq.d.ts → define-agent-eval-q6890HU4.d.ts} +7 -7
- package/dist/{define-agent-eval-CGBwPPaq.d.ts.map → define-agent-eval-q6890HU4.d.ts.map} +1 -1
- package/dist/diagnosis/index.d.ts +38 -96
- package/dist/diagnosis/index.d.ts.map +1 -1
- package/dist/diagnosis/index.js +84 -135
- package/dist/diagnosis/index.js.map +1 -1
- package/dist/{dspy-rlm-engine-BE9lCzzL.js → dspy-rlm-engine-DLYttKBm.js} +3 -3
- package/dist/{dspy-rlm-engine-BE9lCzzL.js.map → dspy-rlm-engine-DLYttKBm.js.map} +1 -1
- package/dist/emitter-DbMXUIVP.js +334 -0
- package/dist/emitter-DbMXUIVP.js.map +1 -0
- package/dist/{emitter-Cs0egaFd.d.ts → emitter-HcCmFQl_.d.ts} +37 -6
- package/dist/emitter-HcCmFQl_.d.ts.map +1 -0
- package/dist/{engine-DNlKhIm0.d.ts → engine-BkLCnZQX.d.ts} +15 -5
- package/dist/engine-BkLCnZQX.d.ts.map +1 -0
- package/dist/{eval-campaign-XFHEpN86.js → eval-campaign-C0Q1Eeo_.js} +8 -5
- package/dist/{eval-campaign-XFHEpN86.js.map → eval-campaign-C0Q1Eeo_.js.map} +1 -1
- package/dist/evaluation.d.ts +2 -2
- package/dist/{exact-types-BEHN7tnq.d.ts → exact-types-CfpP2A4Z.d.ts} +2 -2
- package/dist/{exact-types-BEHN7tnq.d.ts.map → exact-types-CfpP2A4Z.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +3 -3
- package/dist/experiment/index.js +2 -3
- package/dist/experiment/index.js.map +1 -1
- package/dist/{external-optimizer-process-BbhvXTFx.js → external-optimizer-process-C3quNeKV.js} +3 -3
- package/dist/{external-optimizer-process-BbhvXTFx.js.map → external-optimizer-process-C3quNeKV.js.map} +1 -1
- package/dist/{external-optimizer-subprocess-DMgmqTB6.js → external-optimizer-subprocess-BDwgKLO1.js} +3 -3
- package/dist/{external-optimizer-subprocess-DMgmqTB6.js.map → external-optimizer-subprocess-BDwgKLO1.js.map} +1 -1
- package/dist/{failure-cluster-OldNRoAt.d.ts → failure-cluster-CbgEDcFJ.d.ts} +3 -3
- package/dist/{failure-cluster-OldNRoAt.d.ts.map → failure-cluster-CbgEDcFJ.d.ts.map} +1 -1
- package/dist/failure-taxonomy-CjabTATj.js +538 -0
- package/dist/failure-taxonomy-CjabTATj.js.map +1 -0
- package/dist/{feedback-trajectory-CytTR7u4.d.ts → feedback-trajectory-B3ZSkfAq.d.ts} +6 -6
- package/dist/{feedback-trajectory-CytTR7u4.d.ts.map → feedback-trajectory-B3ZSkfAq.d.ts.map} +1 -1
- package/dist/hosted/index.d.ts +2 -2
- package/dist/hosted/index.d.ts.map +1 -1
- package/dist/hosted/index.js +1 -1
- package/dist/{index-vYNHCV2G.d.ts → index-2e_MTznj.d.ts} +8 -8
- package/dist/{index-vYNHCV2G.d.ts.map → index-2e_MTznj.d.ts.map} +1 -1
- package/dist/{index-CKZa_rnt.d.ts → index-Bcc9PkOz.d.ts} +3 -3
- package/dist/{index-CKZa_rnt.d.ts.map → index-Bcc9PkOz.d.ts.map} +1 -1
- package/dist/{index-u0d1Jp4F.d.ts → index-BqDJ6fUK.d.ts} +45 -24
- package/dist/index-BqDJ6fUK.d.ts.map +1 -0
- package/dist/{index-BRsrfSHT.d.ts → index-CnJOPR_E.d.ts} +10 -10
- package/dist/{index-BRsrfSHT.d.ts.map → index-CnJOPR_E.d.ts.map} +1 -1
- package/dist/{index-YZrbnBSV.d.ts → index-Dk1dOUfm.d.ts} +11 -11
- package/dist/{index-YZrbnBSV.d.ts.map → index-Dk1dOUfm.d.ts.map} +1 -1
- package/dist/index.d.ts +384 -69
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1492 -217
- package/dist/index.js.map +1 -1
- package/dist/{insight-report-DpOo-3iL.d.ts → insight-report-CvPkEIcC.d.ts} +14 -7
- package/dist/insight-report-CvPkEIcC.d.ts.map +1 -0
- package/dist/{integrity-Cy9WHAtb.js → integrity-BFP4kjGj.js} +6 -1
- package/dist/integrity-BFP4kjGj.js.map +1 -0
- package/dist/{integrity-rGOfSUle.d.ts → integrity-CaeNeusS.d.ts} +4 -4
- package/dist/integrity-CaeNeusS.d.ts.map +1 -0
- package/dist/jev.d.ts +2 -2
- package/dist/jev.js +2 -1
- package/dist/jev.js.map +1 -1
- package/dist/{journal-BuRLm6ho.js → journal-CDP0Vhx_.js} +262 -115
- package/dist/journal-CDP0Vhx_.js.map +1 -0
- package/dist/{kind-factory-V79Hw0AU.js → kind-factory-BGwN0nE6.js} +17 -5
- package/dist/{kind-factory-V79Hw0AU.js.map → kind-factory-BGwN0nE6.js.map} +1 -1
- package/dist/ledger-core/index.d.ts +2 -2
- package/dist/ledger-core/index.js +1 -1
- package/dist/{llm-client-DDhZ29Vm.js → llm-client-DF9bPNYA.js} +2 -2
- package/dist/{llm-client-DDhZ29Vm.js.map → llm-client-DF9bPNYA.js.map} +1 -1
- package/dist/{llm-judge-BVso5x-u.js → llm-judge-M_l_WXw2.js} +26 -24
- package/dist/llm-judge-M_l_WXw2.js.map +1 -0
- package/dist/{matrix-CPKsRY8Y.d.ts → matrix-CNypzP-v.d.ts} +2 -2
- package/dist/{matrix-CPKsRY8Y.d.ts.map → matrix-CNypzP-v.d.ts.map} +1 -1
- package/dist/meta-eval/index.d.ts +4 -4
- package/dist/{mint-BI14xehJ.d.ts → mint-DsS38v5c.d.ts} +25 -5
- package/dist/{mint-BI14xehJ.d.ts.map → mint-DsS38v5c.d.ts.map} +1 -1
- package/dist/{mint-B4zgSAJW.js → mint-iCD-W43s.js} +30 -12
- package/dist/mint-iCD-W43s.js.map +1 -0
- package/dist/multishot/golden/index.d.ts +1 -1
- package/dist/multishot/index.d.ts +2 -2
- package/dist/openapi.json +1 -1
- package/dist/pipelines/index.d.ts +67 -12
- package/dist/pipelines/index.d.ts.map +1 -1
- package/dist/pipelines/index.js +178 -41
- package/dist/pipelines/index.js.map +1 -1
- package/dist/{prime-protocol-CDBcL9NM.d.ts → prime-protocol-Fwvctmhm.d.ts} +2 -2
- package/dist/{prime-protocol-CDBcL9NM.d.ts.map → prime-protocol-Fwvctmhm.d.ts.map} +1 -1
- package/dist/{produced-state-Cn9ECr4v.js → produced-state-BOY98IJO.js} +4 -4
- package/dist/{produced-state-Cn9ECr4v.js.map → produced-state-BOY98IJO.js.map} +1 -1
- package/dist/{query-D6W6MaGx.d.ts → query-DBUQhehH.d.ts} +3 -3
- package/dist/{query-D6W6MaGx.d.ts.map → query-DBUQhehH.d.ts.map} +1 -1
- package/dist/random-DGEyr3zG.d.ts +83 -0
- package/dist/random-DGEyr3zG.d.ts.map +1 -0
- package/dist/{raw-provider-sink-BQd7mzyT.js → raw-provider-sink-C96CcqeG.js} +19 -56
- package/dist/raw-provider-sink-C96CcqeG.js.map +1 -0
- package/dist/redact-DPoH1-OW.d.ts +158 -0
- package/dist/redact-DPoH1-OW.d.ts.map +1 -0
- package/dist/redact-DxwlUAvh.js +824 -0
- package/dist/redact-DxwlUAvh.js.map +1 -0
- package/dist/{registry-D5Ly3GRV.d.ts → registry-mAQVtuLx.d.ts} +4 -4
- package/dist/{registry-D5Ly3GRV.d.ts.map → registry-mAQVtuLx.d.ts.map} +1 -1
- package/dist/{release-confidence-CSp3MsU4.d.ts → release-confidence-CkoXFx9I.d.ts} +4 -4
- package/dist/{release-confidence-CSp3MsU4.d.ts.map → release-confidence-CkoXFx9I.d.ts.map} +1 -1
- package/dist/{release-confidence-RanRUXRW.js → release-confidence-XQm_xjhR.js} +3 -3
- package/dist/release-confidence-XQm_xjhR.js.map +1 -0
- package/dist/{report-command-CSTjzFGY.js → report-command-DKJ_yAIj.js} +21 -12
- package/dist/{report-command-CSTjzFGY.js.map → report-command-DKJ_yAIj.js.map} +1 -1
- package/dist/reporting.d.ts +3 -3
- package/dist/reporting.js +1 -1
- package/dist/{researcher-D7E92STT.d.ts → researcher-DojEMb7E.d.ts} +7 -7
- package/dist/{researcher-D7E92STT.d.ts.map → researcher-DojEMb7E.d.ts.map} +1 -1
- package/dist/{reward-hacking-BIQ2BWLG.d.ts → reward-hacking-Cyk-QHk9.d.ts} +2 -2
- package/dist/{reward-hacking-BIQ2BWLG.d.ts.map → reward-hacking-Cyk-QHk9.d.ts.map} +1 -1
- package/dist/rl.d.ts +11 -10
- package/dist/rl.d.ts.map +1 -1
- package/dist/rl.js +7 -6
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +4 -4
- package/dist/rollout/index.js +2 -2
- package/dist/{rollout-C0Ifk3vK.js → rollout-B-XBReTC.js} +2 -2
- package/dist/{rollout-C0Ifk3vK.js.map → rollout-B-XBReTC.js.map} +1 -1
- package/dist/{rubric-predictive-validity-CTU8y8Cv.d.ts → rubric-predictive-validity-DIUwJJ9Y.d.ts} +2 -2
- package/dist/{rubric-predictive-validity-CTU8y8Cv.d.ts.map → rubric-predictive-validity-DIUwJJ9Y.d.ts.map} +1 -1
- package/dist/{run-record-tg_5H2IK.js → run-record-BRlM99rX.js} +41 -3
- package/dist/run-record-BRlM99rX.js.map +1 -0
- package/dist/{run-record-D9wS35fK.d.ts → run-record-DF-fuu31.d.ts} +59 -7
- package/dist/run-record-DF-fuu31.d.ts.map +1 -0
- package/dist/{run-record-CNNzWGpB.js → run-record-DnMFyg_g.js} +26 -13
- package/dist/run-record-DnMFyg_g.js.map +1 -0
- package/dist/{schema-CR5cpjQ3.d.ts → schema-2g7trUwH.d.ts} +17 -2
- package/dist/schema-2g7trUwH.d.ts.map +1 -0
- package/dist/{schema-BzWDXhOR.d.ts → schema-B5LtYvn9.d.ts} +7 -5
- package/dist/{schema-BzWDXhOR.d.ts.map → schema-B5LtYvn9.d.ts.map} +1 -1
- package/dist/schema-C1aaAxTf.js.map +1 -1
- package/dist/schema-CSf6qWgZ.js.map +1 -1
- package/dist/{semantic-concept-judge-Cnt0TWp0.js → semantic-concept-judge-Cm2K2wAo.js} +6 -6
- package/dist/{semantic-concept-judge-Cnt0TWp0.js.map → semantic-concept-judge-Cm2K2wAo.js.map} +1 -1
- package/dist/{series-convergence-BnMs_uAr.d.ts → series-convergence-DY7ha0kx.d.ts} +2 -2
- package/dist/{series-convergence-BnMs_uAr.d.ts.map → series-convergence-DY7ha0kx.d.ts.map} +1 -1
- package/dist/{server-DmpcFiVK.js → server-C8XvqCg8.js} +2 -2
- package/dist/{server-DmpcFiVK.js.map → server-C8XvqCg8.js.map} +1 -1
- package/dist/{skillopt-optimization-method-Cc9SVLqi.js → skillopt-optimization-method-BVSB676o.js} +7 -7
- package/dist/{skillopt-optimization-method-Cc9SVLqi.js.map → skillopt-optimization-method-BVSB676o.js.map} +1 -1
- package/dist/spans-W0o8pbEg.d.ts +60 -0
- package/dist/spans-W0o8pbEg.d.ts.map +1 -0
- package/dist/{statistical-heldout-DTmhTW8P.d.ts → statistical-heldout-plAHG82H.d.ts} +3 -3
- package/dist/{statistical-heldout-DTmhTW8P.d.ts.map → statistical-heldout-plAHG82H.d.ts.map} +1 -1
- package/dist/{store-BErPvYBr.d.ts → store-C4avFjIi.d.ts} +2 -2
- package/dist/{store-BErPvYBr.d.ts.map → store-C4avFjIi.d.ts.map} +1 -1
- package/dist/{store-otlp-2gYCy-v0.js → store-otlp-D0AV4cvB.js} +2 -2
- package/dist/{store-otlp-2gYCy-v0.js.map → store-otlp-D0AV4cvB.js.map} +1 -1
- package/dist/{store-tool-spans-B3bX9yqn.d.ts → store-tool-spans-8PAyhRqb.d.ts} +9 -54
- package/dist/store-tool-spans-8PAyhRqb.d.ts.map +1 -0
- package/dist/{store-tool-spans-B1e6Auc2.js → store-tool-spans-B_0mXvYl.js} +4 -4
- package/dist/{store-tool-spans-B1e6Auc2.js.map → store-tool-spans-B_0mXvYl.js.map} +1 -1
- package/dist/storyboard/index.d.ts +1 -1
- package/dist/{summary-report-Iy6kXo8x.d.ts → summary-report-DvvesgR_.d.ts} +6 -5
- package/dist/summary-report-DvvesgR_.d.ts.map +1 -0
- package/dist/supervisor-run/index.d.ts +2 -2
- package/dist/supervisor-run/index.d.ts.map +1 -1
- package/dist/supervisor-run/index.js +1 -1
- package/dist/{tool-groups-veQYPiTy.d.ts → tool-groups-W7MJobX_.d.ts} +3 -3
- package/dist/tool-groups-W7MJobX_.d.ts.map +1 -0
- package/dist/{tool-waste-nbHPAxei.js → tool-waste-CJDfxH45.js} +3 -537
- package/dist/tool-waste-CJDfxH45.js.map +1 -0
- package/dist/{tool-waste-D23I0zWm.d.ts → tool-waste-CP5DO383.d.ts} +4 -4
- package/dist/{tool-waste-D23I0zWm.d.ts.map → tool-waste-CP5DO383.d.ts.map} +1 -1
- package/dist/trace-repair/index.d.ts +2 -2
- package/dist/traces.d.ts +12 -11
- package/dist/traces.d.ts.map +1 -1
- package/dist/traces.js +9 -9
- package/dist/{trajectory-D7qrNvaN.d.ts → trajectory-Y1fmdlw7.d.ts} +3 -3
- package/dist/{trajectory-D7qrNvaN.d.ts.map → trajectory-Y1fmdlw7.d.ts.map} +1 -1
- package/dist/trajectory-replay/index.d.ts +3 -3
- package/dist/trajectory-replay/index.js +2 -2
- package/dist/{types-BjB2wZM9.d.ts → types-Bay1dh2o.d.ts} +6 -6
- package/dist/{types-BjB2wZM9.d.ts.map → types-Bay1dh2o.d.ts.map} +1 -1
- package/dist/{types-BTRcIqFr.d.ts → types-BvmWNjjs.d.ts} +4 -4
- package/dist/{types-BTRcIqFr.d.ts.map → types-BvmWNjjs.d.ts.map} +1 -1
- package/dist/{types-CBbLtr2J.d.ts → types-C0bWoSKC.d.ts} +10 -11
- package/dist/types-C0bWoSKC.d.ts.map +1 -0
- package/dist/{types-C8VBbiw6.js → types-CW5b90JH.js} +2 -15
- package/dist/types-CW5b90JH.js.map +1 -0
- package/dist/{types--18oHwVF.d.ts → types-Cvqy7asY.d.ts} +3 -3
- package/dist/{types--18oHwVF.d.ts.map → types-Cvqy7asY.d.ts.map} +1 -1
- package/dist/{types-Tp5WhYL9.d.ts → types-DRNlLbBR.d.ts} +2 -2
- package/dist/{types-Tp5WhYL9.d.ts.map → types-DRNlLbBR.d.ts.map} +1 -1
- package/dist/wire/index.d.ts +3 -3
- package/dist/wire/index.js +1 -1
- package/docs/code-agent-intake.md +1 -1
- package/docs/diagnosis.md +2 -3
- package/docs/eval-surface-map.md +1 -1
- package/docs/experiment.md +0 -1
- package/docs/insight-report.md +3 -2
- package/docs/public-api.md +2 -2
- package/docs/redaction.md +59 -0
- package/docs/rollout.md +5 -5
- package/docs/search-history-receipts.md +1 -0
- package/docs/trace-contracts.md +102 -0
- package/docs/verdicts.md +1 -1
- package/package.json +3 -2
- package/dist/analyze-runs-DCY7LMt4.js.map +0 -1
- package/dist/benchmark-command-DGokT8zd.js.map +0 -1
- package/dist/campaign-evidence-IF1p0oDa.js.map +0 -1
- package/dist/client-CXE-U1SA.js.map +0 -1
- package/dist/default-registry-Ca2IWH1X.js.map +0 -1
- package/dist/emitter-Cs0egaFd.d.ts.map +0 -1
- package/dist/emitter-DeQHiDMm.js +0 -257
- package/dist/emitter-DeQHiDMm.js.map +0 -1
- package/dist/engine-DNlKhIm0.d.ts.map +0 -1
- package/dist/experiment-tracker-BKEumQug.js +0 -280
- package/dist/experiment-tracker-BKEumQug.js.map +0 -1
- package/dist/experiment-tracker-URRGP9ek.d.ts +0 -237
- package/dist/experiment-tracker-URRGP9ek.d.ts.map +0 -1
- package/dist/index-u0d1Jp4F.d.ts.map +0 -1
- package/dist/insight-report-DpOo-3iL.d.ts.map +0 -1
- package/dist/integrity-Cy9WHAtb.js.map +0 -1
- package/dist/integrity-rGOfSUle.d.ts.map +0 -1
- package/dist/journal-BuRLm6ho.js.map +0 -1
- package/dist/llm-judge-BVso5x-u.js.map +0 -1
- package/dist/mint-B4zgSAJW.js.map +0 -1
- package/dist/raw-provider-sink-BQd7mzyT.js.map +0 -1
- package/dist/redact-7Aq1ukl-.js +0 -107
- package/dist/redact-7Aq1ukl-.js.map +0 -1
- package/dist/release-confidence-RanRUXRW.js.map +0 -1
- package/dist/run-record-CNNzWGpB.js.map +0 -1
- package/dist/run-record-D9wS35fK.d.ts.map +0 -1
- package/dist/run-record-tg_5H2IK.js.map +0 -1
- package/dist/schema-CR5cpjQ3.d.ts.map +0 -1
- package/dist/store-tool-spans-B3bX9yqn.d.ts.map +0 -1
- package/dist/summary-report-Iy6kXo8x.d.ts.map +0 -1
- package/dist/tool-groups-veQYPiTy.d.ts.map +0 -1
- package/dist/tool-waste-nbHPAxei.js.map +0 -1
- package/dist/types-C8VBbiw6.js.map +0 -1
- package/dist/types-CBbLtr2J.d.ts.map +0 -1
package/dist/emitter-DeQHiDMm.js
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import { t as newRecordId } from "./record-id-DUgsK5qp.js";
|
|
2
|
-
//#region src/trace/emitter.ts
|
|
3
|
-
/**
|
|
4
|
-
* TraceEmitter — hierarchical span builder that auto-parents using an
|
|
5
|
-
* internal stack. One emitter per Run; emitters do NOT share state.
|
|
6
|
-
*
|
|
7
|
-
* Convenience methods (`llm`, `tool`, `retrieval`, `judge`, `sandbox`)
|
|
8
|
-
* return a `SpanHandle` with `.end()` / `.fail()` so callers don't
|
|
9
|
-
* have to thread spanIds manually. For async workflows that can't use
|
|
10
|
-
* the stack (e.g. fan-out parallel calls), pass `parentSpanId`
|
|
11
|
-
* explicitly.
|
|
12
|
-
*/
|
|
13
|
-
var TraceEmitter = class {
|
|
14
|
-
store;
|
|
15
|
-
stack = [];
|
|
16
|
-
_runId;
|
|
17
|
-
now;
|
|
18
|
-
id;
|
|
19
|
-
hooks;
|
|
20
|
-
hookErrors;
|
|
21
|
-
constructor(store, options = {}) {
|
|
22
|
-
this.store = store;
|
|
23
|
-
this.now = options.now ?? (() => Date.now());
|
|
24
|
-
this.id = options.id ?? (() => newRecordId());
|
|
25
|
-
this._runId = options.runId ?? this.id();
|
|
26
|
-
this.hooks = options.onRunComplete ?? [];
|
|
27
|
-
this.hookErrors = options.hookErrors ?? "swallow";
|
|
28
|
-
}
|
|
29
|
-
get runId() {
|
|
30
|
-
return this._runId;
|
|
31
|
-
}
|
|
32
|
-
get traceStore() {
|
|
33
|
-
return this.store;
|
|
34
|
-
}
|
|
35
|
-
/** Append a hook after construction (e.g. attach the trace analyst). */
|
|
36
|
-
addRunCompleteHook(hook) {
|
|
37
|
-
this.hooks.push(hook);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Begin a Run.
|
|
41
|
-
*
|
|
42
|
-
* `scenarioId` is required on the persisted Run shape — every Run downstream
|
|
43
|
-
* gets a non-empty scenarioId so filters and aggregations stay simple — but
|
|
44
|
-
* the INPUT here accepts it as optional. When omitted, startRun substitutes
|
|
45
|
-
* a sensible default (`run.layer ?? run.tags?.['kind'] ?? 'runtime'`) so
|
|
46
|
-
* runtime / operator / meta-eval runs that have no curated-scenario corpus
|
|
47
|
-
* to anchor to don't have to invent placeholder strings at the call site.
|
|
48
|
-
*/
|
|
49
|
-
async startRun(run) {
|
|
50
|
-
const scenarioId = run.scenarioId ?? run.layer ?? run.tags?.kind ?? "runtime";
|
|
51
|
-
const full = {
|
|
52
|
-
...run,
|
|
53
|
-
scenarioId,
|
|
54
|
-
runId: this._runId,
|
|
55
|
-
startedAt: this.now(),
|
|
56
|
-
status: "running"
|
|
57
|
-
};
|
|
58
|
-
await this.store.appendRun(full);
|
|
59
|
-
return full;
|
|
60
|
-
}
|
|
61
|
-
async endRun(outcome) {
|
|
62
|
-
const status = outcome?.pass === false ? "failed" : "completed";
|
|
63
|
-
await this.store.updateRun(this._runId, {
|
|
64
|
-
endedAt: this.now(),
|
|
65
|
-
status,
|
|
66
|
-
outcome
|
|
67
|
-
});
|
|
68
|
-
await this.runHooks({
|
|
69
|
-
runId: this._runId,
|
|
70
|
-
emitter: this,
|
|
71
|
-
store: this.store,
|
|
72
|
-
outcome,
|
|
73
|
-
status
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
async abortRun(reason) {
|
|
77
|
-
const outcome = {
|
|
78
|
-
pass: false,
|
|
79
|
-
notes: reason
|
|
80
|
-
};
|
|
81
|
-
await this.store.updateRun(this._runId, {
|
|
82
|
-
endedAt: this.now(),
|
|
83
|
-
status: "aborted",
|
|
84
|
-
outcome
|
|
85
|
-
});
|
|
86
|
-
await this.runHooks({
|
|
87
|
-
runId: this._runId,
|
|
88
|
-
emitter: this,
|
|
89
|
-
store: this.store,
|
|
90
|
-
outcome,
|
|
91
|
-
status: "aborted"
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
async runHooks(ctx) {
|
|
95
|
-
for (const hook of this.hooks) try {
|
|
96
|
-
await hook(ctx);
|
|
97
|
-
} catch (err) {
|
|
98
|
-
if (this.hookErrors === "throw") throw err;
|
|
99
|
-
try {
|
|
100
|
-
await this.store.appendEvent({
|
|
101
|
-
eventId: this.id(),
|
|
102
|
-
runId: this._runId,
|
|
103
|
-
kind: "log",
|
|
104
|
-
timestamp: this.now(),
|
|
105
|
-
payload: {
|
|
106
|
-
source: "run_complete_hook",
|
|
107
|
-
error: err instanceof Error ? err.message : String(err)
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
} catch {}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
async span(init) {
|
|
114
|
-
const spanId = this.id();
|
|
115
|
-
const span = {
|
|
116
|
-
spanId,
|
|
117
|
-
parentSpanId: init.parentSpanId ?? this.stack[this.stack.length - 1],
|
|
118
|
-
runId: this._runId,
|
|
119
|
-
startedAt: this.now(),
|
|
120
|
-
...init
|
|
121
|
-
};
|
|
122
|
-
await this.store.appendSpan(span);
|
|
123
|
-
this.stack.push(spanId);
|
|
124
|
-
return this.handle(span);
|
|
125
|
-
}
|
|
126
|
-
handle(span) {
|
|
127
|
-
return {
|
|
128
|
-
span,
|
|
129
|
-
end: async (patch) => {
|
|
130
|
-
const endedAt = this.now();
|
|
131
|
-
await this.store.updateSpan(span.spanId, {
|
|
132
|
-
endedAt,
|
|
133
|
-
status: "ok",
|
|
134
|
-
...patch
|
|
135
|
-
});
|
|
136
|
-
this.pop(span.spanId);
|
|
137
|
-
},
|
|
138
|
-
fail: async (error, patch) => {
|
|
139
|
-
const endedAt = this.now();
|
|
140
|
-
const errStr = error instanceof Error ? error.message : error;
|
|
141
|
-
await this.store.updateSpan(span.spanId, {
|
|
142
|
-
endedAt,
|
|
143
|
-
status: "error",
|
|
144
|
-
error: errStr,
|
|
145
|
-
...patch
|
|
146
|
-
});
|
|
147
|
-
this.pop(span.spanId);
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
pop(spanId) {
|
|
152
|
-
const idx = this.stack.lastIndexOf(spanId);
|
|
153
|
-
if (idx >= 0) this.stack.splice(idx, 1);
|
|
154
|
-
}
|
|
155
|
-
llm(init) {
|
|
156
|
-
return this.span({
|
|
157
|
-
kind: "llm",
|
|
158
|
-
...init
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
tool(init) {
|
|
162
|
-
return this.span({
|
|
163
|
-
kind: "tool",
|
|
164
|
-
...init
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
retrieval(init) {
|
|
168
|
-
return this.span({
|
|
169
|
-
kind: "retrieval",
|
|
170
|
-
...init
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
async recordJudge(verdict) {
|
|
174
|
-
const spanId = this.id();
|
|
175
|
-
const now = this.now();
|
|
176
|
-
const full = {
|
|
177
|
-
spanId,
|
|
178
|
-
runId: this._runId,
|
|
179
|
-
kind: "judge",
|
|
180
|
-
startedAt: now,
|
|
181
|
-
endedAt: now,
|
|
182
|
-
status: "ok",
|
|
183
|
-
...verdict
|
|
184
|
-
};
|
|
185
|
-
await this.store.appendSpan(full);
|
|
186
|
-
return full;
|
|
187
|
-
}
|
|
188
|
-
sandbox(init) {
|
|
189
|
-
return this.span({
|
|
190
|
-
kind: "sandbox",
|
|
191
|
-
...init
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
async emit(event) {
|
|
195
|
-
const full = {
|
|
196
|
-
eventId: this.id(),
|
|
197
|
-
runId: this._runId,
|
|
198
|
-
spanId: event.spanId ?? this.stack[this.stack.length - 1],
|
|
199
|
-
kind: event.kind,
|
|
200
|
-
timestamp: this.now(),
|
|
201
|
-
payload: event.payload ?? {}
|
|
202
|
-
};
|
|
203
|
-
await this.store.appendEvent(full);
|
|
204
|
-
return full;
|
|
205
|
-
}
|
|
206
|
-
async recordBudget(entry) {
|
|
207
|
-
const full = {
|
|
208
|
-
runId: this._runId,
|
|
209
|
-
timestamp: entry.timestamp ?? this.now(),
|
|
210
|
-
dimension: entry.dimension,
|
|
211
|
-
limit: entry.limit,
|
|
212
|
-
consumed: entry.consumed,
|
|
213
|
-
remaining: entry.remaining,
|
|
214
|
-
breached: entry.breached,
|
|
215
|
-
spanId: entry.spanId ?? this.stack[this.stack.length - 1]
|
|
216
|
-
};
|
|
217
|
-
await this.store.appendBudgetEntry(full);
|
|
218
|
-
if (full.breached) await this.emit({
|
|
219
|
-
kind: "budget_breach",
|
|
220
|
-
spanId: full.spanId,
|
|
221
|
-
payload: {
|
|
222
|
-
dimension: full.dimension,
|
|
223
|
-
limit: full.limit,
|
|
224
|
-
consumed: full.consumed
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
return full;
|
|
228
|
-
}
|
|
229
|
-
async recordArtifact(artifact) {
|
|
230
|
-
const full = {
|
|
231
|
-
artifactId: this.id(),
|
|
232
|
-
runId: this._runId,
|
|
233
|
-
...artifact
|
|
234
|
-
};
|
|
235
|
-
await this.store.appendArtifact(full);
|
|
236
|
-
return full;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Runs `fn` inside a span; auto-ends on success, auto-fails on throw.
|
|
240
|
-
* Returns the fn's return value. Use this for the 95% case.
|
|
241
|
-
*/
|
|
242
|
-
async within(init, fn) {
|
|
243
|
-
const handle = await this.span(init);
|
|
244
|
-
try {
|
|
245
|
-
const result = await fn(handle);
|
|
246
|
-
await handle.end();
|
|
247
|
-
return result;
|
|
248
|
-
} catch (err) {
|
|
249
|
-
await handle.fail(err instanceof Error ? err : String(err));
|
|
250
|
-
throw err;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
//#endregion
|
|
255
|
-
export { TraceEmitter as t };
|
|
256
|
-
|
|
257
|
-
//# sourceMappingURL=emitter-DeQHiDMm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"emitter-DeQHiDMm.js","names":[],"sources":["../src/trace/emitter.ts"],"sourcesContent":["/**\n * TraceEmitter — hierarchical span builder that auto-parents using an\n * internal stack. One emitter per Run; emitters do NOT share state.\n *\n * Convenience methods (`llm`, `tool`, `retrieval`, `judge`, `sandbox`)\n * return a `SpanHandle` with `.end()` / `.fail()` so callers don't\n * have to thread spanIds manually. For async workflows that can't use\n * the stack (e.g. fan-out parallel calls), pass `parentSpanId`\n * explicitly.\n */\n\nimport { newRecordId } from '../record-id'\nimport type {\n Artifact,\n BudgetLedgerEntry,\n EventKind,\n JudgeSpan,\n LlmSpan,\n RetrievalSpan,\n Run,\n RunOutcome,\n SandboxSpan,\n Span,\n SpanKind,\n ToolSpan,\n TraceEvent,\n} from './schema'\nimport type { TraceStore } from './store'\n\nexport interface SpanHandle<S extends Span = Span> {\n span: S\n end(patch?: Partial<S>): Promise<void>\n fail(error: string | Error, patch?: Partial<S>): Promise<void>\n}\n\nexport interface RunCompleteHookContext {\n runId: string\n emitter: TraceEmitter\n store: TraceStore\n /** Outcome the caller passed to `endRun` (undefined for `abortRun`). */\n outcome?: RunOutcome\n /** Final run status. */\n status: 'completed' | 'failed' | 'aborted'\n}\n\nexport type RunCompleteHook = (ctx: RunCompleteHookContext) => Promise<void> | void\n\nexport interface TraceEmitterOptions {\n runId?: string\n /** Inject a clock for deterministic tests. */\n now?: () => number\n /** Inject an id generator for deterministic tests. */\n id?: () => string\n /**\n * Hooks fired after `endRun` / `abortRun` writes the final run state.\n * Designed for trace-analyst auto-execution, integrity assertions, and\n * outbound notifications. Hooks run sequentially in the order supplied.\n *\n * By default a hook that throws is swallowed and logged as a `note` event\n * on the run — auto-orchestration must not crash the underlying flow.\n * Set `hookErrors: 'throw'` to propagate.\n */\n onRunComplete?: RunCompleteHook[]\n /** `'swallow'` (default) | `'throw'`. */\n hookErrors?: 'swallow' | 'throw'\n}\n\nexport class TraceEmitter {\n private store: TraceStore\n private stack: string[] = []\n private _runId: string\n private now: () => number\n private id: () => string\n private hooks: RunCompleteHook[]\n private hookErrors: 'swallow' | 'throw'\n\n constructor(store: TraceStore, options: TraceEmitterOptions = {}) {\n this.store = store\n this.now = options.now ?? (() => Date.now())\n this.id = options.id ?? (() => newRecordId())\n this._runId = options.runId ?? this.id()\n this.hooks = options.onRunComplete ?? []\n this.hookErrors = options.hookErrors ?? 'swallow'\n }\n\n get runId(): string {\n return this._runId\n }\n\n get traceStore(): TraceStore {\n return this.store\n }\n\n /** Append a hook after construction (e.g. attach the trace analyst). */\n addRunCompleteHook(hook: RunCompleteHook): void {\n this.hooks.push(hook)\n }\n\n // ── Run lifecycle ──────────────────────────────────────────────────\n\n /**\n * Begin a Run.\n *\n * `scenarioId` is required on the persisted Run shape — every Run downstream\n * gets a non-empty scenarioId so filters and aggregations stay simple — but\n * the INPUT here accepts it as optional. When omitted, startRun substitutes\n * a sensible default (`run.layer ?? run.tags?.['kind'] ?? 'runtime'`) so\n * runtime / operator / meta-eval runs that have no curated-scenario corpus\n * to anchor to don't have to invent placeholder strings at the call site.\n */\n async startRun(\n run: Omit<Run, 'runId' | 'scenarioId' | 'startedAt' | 'status'> & { scenarioId?: string },\n ): Promise<Run> {\n const scenarioId = run.scenarioId ?? run.layer ?? run.tags?.kind ?? 'runtime'\n const full: Run = {\n ...run,\n scenarioId,\n runId: this._runId,\n startedAt: this.now(),\n status: 'running',\n }\n await this.store.appendRun(full)\n return full\n }\n\n async endRun(outcome?: RunOutcome): Promise<void> {\n const status: 'completed' | 'failed' = outcome?.pass === false ? 'failed' : 'completed'\n await this.store.updateRun(this._runId, { endedAt: this.now(), status, outcome })\n await this.runHooks({ runId: this._runId, emitter: this, store: this.store, outcome, status })\n }\n\n async abortRun(reason: string): Promise<void> {\n const outcome = { pass: false, notes: reason }\n await this.store.updateRun(this._runId, {\n endedAt: this.now(),\n status: 'aborted',\n outcome,\n })\n await this.runHooks({\n runId: this._runId,\n emitter: this,\n store: this.store,\n outcome,\n status: 'aborted',\n })\n }\n\n private async runHooks(ctx: RunCompleteHookContext): Promise<void> {\n for (const hook of this.hooks) {\n try {\n await hook(ctx)\n } catch (err) {\n if (this.hookErrors === 'throw') throw err\n try {\n await this.store.appendEvent({\n eventId: this.id(),\n runId: this._runId,\n kind: 'log',\n timestamp: this.now(),\n payload: {\n source: 'run_complete_hook',\n error: err instanceof Error ? err.message : String(err),\n },\n })\n } catch {\n // best-effort\n }\n }\n }\n }\n\n // ── Generic span ───────────────────────────────────────────────────\n\n async span<S extends Span = Span>(\n init: {\n kind: SpanKind\n name: string\n parentSpanId?: string\n attributes?: Record<string, unknown>\n } & Partial<Omit<S, 'spanId' | 'runId' | 'startedAt' | 'kind' | 'name'>>,\n ): Promise<SpanHandle<S>> {\n const spanId = this.id()\n const parent = init.parentSpanId ?? this.stack[this.stack.length - 1]\n const span = {\n spanId,\n parentSpanId: parent,\n runId: this._runId,\n startedAt: this.now(),\n ...init,\n } as unknown as S\n await this.store.appendSpan(span)\n this.stack.push(spanId)\n return this.handle<S>(span)\n }\n\n private handle<S extends Span>(span: S): SpanHandle<S> {\n return {\n span,\n end: async (patch?: Partial<S>) => {\n const endedAt = this.now()\n await this.store.updateSpan(span.spanId, {\n endedAt,\n status: 'ok',\n ...patch,\n } as Partial<Span>)\n this.pop(span.spanId)\n },\n fail: async (error: string | Error, patch?: Partial<S>) => {\n const endedAt = this.now()\n const errStr = error instanceof Error ? error.message : error\n await this.store.updateSpan(span.spanId, {\n endedAt,\n status: 'error',\n error: errStr,\n ...patch,\n } as Partial<Span>)\n this.pop(span.spanId)\n },\n }\n }\n\n private pop(spanId: string): void {\n const idx = this.stack.lastIndexOf(spanId)\n if (idx >= 0) this.stack.splice(idx, 1)\n }\n\n // ── Typed span conveniences ────────────────────────────────────────\n\n llm(\n init: Omit<LlmSpan, 'spanId' | 'runId' | 'kind' | 'startedAt'>,\n ): Promise<SpanHandle<LlmSpan>> {\n return this.span<LlmSpan>({ kind: 'llm', ...init })\n }\n\n tool(\n init: Omit<ToolSpan, 'spanId' | 'runId' | 'kind' | 'startedAt'>,\n ): Promise<SpanHandle<ToolSpan>> {\n return this.span<ToolSpan>({ kind: 'tool', ...init })\n }\n\n retrieval(\n init: Omit<RetrievalSpan, 'spanId' | 'runId' | 'kind' | 'startedAt'>,\n ): Promise<SpanHandle<RetrievalSpan>> {\n return this.span<RetrievalSpan>({ kind: 'retrieval', ...init })\n }\n\n async recordJudge(\n verdict: Omit<JudgeSpan, 'spanId' | 'runId' | 'kind' | 'startedAt' | 'endedAt'>,\n ): Promise<JudgeSpan> {\n const spanId = this.id()\n const now = this.now()\n const full: JudgeSpan = {\n spanId,\n runId: this._runId,\n kind: 'judge',\n startedAt: now,\n endedAt: now,\n status: 'ok',\n ...verdict,\n }\n await this.store.appendSpan(full)\n return full\n }\n\n sandbox(\n init: Omit<SandboxSpan, 'spanId' | 'runId' | 'kind' | 'startedAt'>,\n ): Promise<SpanHandle<SandboxSpan>> {\n return this.span<SandboxSpan>({ kind: 'sandbox', ...init })\n }\n\n // ── Events ─────────────────────────────────────────────────────────\n\n async emit(event: {\n kind: EventKind\n spanId?: string\n payload?: Record<string, unknown>\n }): Promise<TraceEvent> {\n const full: TraceEvent = {\n eventId: this.id(),\n runId: this._runId,\n spanId: event.spanId ?? this.stack[this.stack.length - 1],\n kind: event.kind,\n timestamp: this.now(),\n payload: event.payload ?? {},\n }\n await this.store.appendEvent(full)\n return full\n }\n\n // ── Budget ledger ──────────────────────────────────────────────────\n\n async recordBudget(\n entry: Omit<BudgetLedgerEntry, 'runId' | 'timestamp'> & { timestamp?: number },\n ): Promise<BudgetLedgerEntry> {\n const full: BudgetLedgerEntry = {\n runId: this._runId,\n timestamp: entry.timestamp ?? this.now(),\n dimension: entry.dimension,\n limit: entry.limit,\n consumed: entry.consumed,\n remaining: entry.remaining,\n breached: entry.breached,\n spanId: entry.spanId ?? this.stack[this.stack.length - 1],\n }\n await this.store.appendBudgetEntry(full)\n if (full.breached) {\n await this.emit({\n kind: 'budget_breach',\n spanId: full.spanId,\n payload: { dimension: full.dimension, limit: full.limit, consumed: full.consumed },\n })\n }\n return full\n }\n\n // ── Artifacts ──────────────────────────────────────────────────────\n\n async recordArtifact(artifact: Omit<Artifact, 'artifactId' | 'runId'>): Promise<Artifact> {\n const full: Artifact = { artifactId: this.id(), runId: this._runId, ...artifact }\n await this.store.appendArtifact(full)\n return full\n }\n\n // ── Nested composition ─────────────────────────────────────────────\n\n /**\n * Runs `fn` inside a span; auto-ends on success, auto-fails on throw.\n * Returns the fn's return value. Use this for the 95% case.\n */\n async within<T>(\n init: Parameters<TraceEmitter['span']>[0],\n fn: (handle: SpanHandle) => Promise<T>,\n ): Promise<T> {\n const handle = await this.span(init)\n try {\n const result = await fn(handle)\n await handle.end()\n return result\n } catch (err) {\n await handle.fail(err instanceof Error ? err : String(err))\n throw err\n }\n }\n}\n\n// Helpers -------------------------------------------------------------\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine-DNlKhIm0.d.ts","names":[],"sources":["../src/eval-tools.ts","../src/trace-analyst/tools.ts","../src/analyst/finding-signature.ts","../src/analyst/engine.ts"],"mappings":";;;;;;;UA4BiB;EACf;EACA;EACA,YAAY;EACZ,UAAU,eAAe;IAAQ,SAAS;QAAkB;;;;cClBjD;UAEI,uCAAuC;EACtD,OAAO;;UAGQ,oCAAoC;EACnD,kBAAkB;;;iBAIJ,kCACd,SAAS,iCACR;iBAoIa,0BAA0B,SAAS;EACjD;EACA;EACA;EACA;EACA,WAAW;;;;cCxJP,0BAAwB,EAAA;;;GAKnB,EAAA,KAAA;KAEC,qBAAqB,EAAE,aAAa;cAiBnC,yBAAuB,EAAA;;;;;;;;;;;;;;;;;GAKzB,EAAA,KAAA;KAEC,oBAAoB,EAAE,aAAa;;;;;;cAOlC;;iBAYG,2BAA2B,SAAS,oBAAoB;iBAQxD,gBACd,cACA,OAAO,aAAa,SAAS,mCAC5B;;;;UCpEc;;EAEf;;EAEA;;EAEA;;EAEA;;;;;;;;;;;;;;;;cAwBW;UAEI;EACf;EACA;EACA;EACA,gBAAgB;;;;;;;;;;;EAWhB,aAAa,SAAS;EACtB,QAAQ;EACR,YAAY;EACZ;EACA,WAAW;EACX,SAAS;EACT,OAAO,iBAAiB,SAAS;;;UAIlB;EACf;EACA,UAAU;;EAEV;;;;;EAKA;;EAEA;EACA,SAAS;;;;;;;;;UAUM;WACN;WACA;WACA;;WAEA;;;;;;;;WAQA,iBAAiB,SAAS;EACnC,QAAQ,SAAS,6BAA6B,QAAQ;;iBAGxC,0BACd,QAAQ,QAAQ,kCACf"}
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
import { s as ValidationError } from "./errors-Dngq5h35.js";
|
|
2
|
-
import { n as iqr } from "./baseline-BC-eBZ7U.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
|
-
if (rep.runId !== void 0 && rep.runId.trim().length === 0) throw new ValidationError("experiment-tracker: rep runId must be non-empty when present");
|
|
237
|
-
const evidence = rep.evidence?.map((reference, index) => {
|
|
238
|
-
if (reference.uri.trim().length === 0) throw new ValidationError(`experiment-tracker: rep evidence[${index}].uri must be non-empty`);
|
|
239
|
-
return {
|
|
240
|
-
kind: reference.kind,
|
|
241
|
-
uri: reference.uri,
|
|
242
|
-
...reference.excerpt === void 0 ? {} : { excerpt: reference.excerpt }
|
|
243
|
-
};
|
|
244
|
-
});
|
|
245
|
-
const fullRep = {
|
|
246
|
-
rep: rep.rep ?? exp.reps.length,
|
|
247
|
-
score: rep.score,
|
|
248
|
-
timestamp: rep.timestamp ?? new Date(this.now()).toISOString(),
|
|
249
|
-
...rep.runId === void 0 ? {} : { runId: rep.runId },
|
|
250
|
-
...evidence === void 0 ? {} : { evidence },
|
|
251
|
-
...rep.passed === void 0 ? {} : { passed: rep.passed },
|
|
252
|
-
...rep.metrics === void 0 ? {} : { metrics: { ...rep.metrics } }
|
|
253
|
-
};
|
|
254
|
-
exp.reps.push(fullRep);
|
|
255
|
-
exp.stats = computeExperimentStats(exp.reps, this.thresholds);
|
|
256
|
-
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
257
|
-
exp.verdict = improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds).verdict;
|
|
258
|
-
await this.store.save(experiments);
|
|
259
|
-
return structuredClone(exp);
|
|
260
|
-
}
|
|
261
|
-
async get(experimentId) {
|
|
262
|
-
const found = (await this.store.load()).find((e) => e.id === experimentId);
|
|
263
|
-
return found ? structuredClone(found) : void 0;
|
|
264
|
-
}
|
|
265
|
-
async list() {
|
|
266
|
-
return this.store.load();
|
|
267
|
-
}
|
|
268
|
-
/** Full verdict (not just the enum) for an experiment vs its parent. */
|
|
269
|
-
async verdictFor(experimentId) {
|
|
270
|
-
const experiments = await this.store.load();
|
|
271
|
-
const exp = experiments.find((e) => e.id === experimentId);
|
|
272
|
-
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
273
|
-
const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : void 0;
|
|
274
|
-
return improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds);
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
//#endregion
|
|
278
|
-
export { inMemoryExperimentStore as a, improvementVerdict as i, computeExperimentStats as n, fileExperimentStore as r, ExperimentTracker as t };
|
|
279
|
-
|
|
280
|
-
//# sourceMappingURL=experiment-tracker-BKEumQug.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"experiment-tracker-BKEumQug.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 type { EvidenceRef } from './analyst/types'\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 /** Stable execution/run identity that produced this score. */\n runId?: string\n /** Mechanically resolvable trace, artifact, metric, or finding evidence. */\n evidence?: EvidenceRef[]\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 if (rep.runId !== undefined && rep.runId.trim().length === 0) {\n throw new ValidationError('experiment-tracker: rep runId must be non-empty when present')\n }\n const evidence = rep.evidence?.map((reference, index) => {\n if (reference.uri.trim().length === 0) {\n throw new ValidationError(\n `experiment-tracker: rep evidence[${index}].uri must be non-empty`,\n )\n }\n return {\n kind: reference.kind,\n uri: reference.uri,\n ...(reference.excerpt === undefined ? {} : { excerpt: reference.excerpt }),\n }\n })\n const fullRep: ExperimentRep = {\n rep: rep.rep ?? exp.reps.length,\n score: rep.score,\n timestamp: rep.timestamp ?? new Date(this.now()).toISOString(),\n ...(rep.runId === undefined ? {} : { runId: rep.runId }),\n ...(evidence === undefined ? {} : { evidence }),\n ...(rep.passed === undefined ? {} : { passed: rep.passed }),\n ...(rep.metrics === undefined ? {} : { metrics: { ...rep.metrics } }),\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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"}
|