@tangle-network/agent-eval 0.216.0 → 0.216.1
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 +39 -0
- package/dist/adapters/http.d.ts +3 -3
- package/dist/{agent-profile-CIA2Atnt.d.ts → agent-profile-VFcQncbW.d.ts} +5 -5
- package/dist/{agent-profile-CIA2Atnt.d.ts.map → agent-profile-VFcQncbW.d.ts.map} +1 -1
- package/dist/{agent-profile-cell-BYc0bxsL.js → agent-profile-cell-BK8mlqlq.js} +3 -3
- package/dist/{agent-profile-cell-BYc0bxsL.js.map → agent-profile-cell-BK8mlqlq.js.map} +1 -1
- package/dist/{agreement-irr-DsTURxdr.js → agreement-irr-BEWLIF3_.js} +3 -3
- package/dist/{agreement-irr-DsTURxdr.js.map → agreement-irr-BEWLIF3_.js.map} +1 -1
- package/dist/analyst/index.d.ts +14 -14
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +15 -15
- package/dist/{analyze-runs-3xpby3p2.js → analyze-runs-C84irm4i.js} +608 -604
- package/dist/analyze-runs-C84irm4i.js.map +1 -0
- package/dist/{analyze-runs-CSDAh8A7.d.ts → analyze-runs-D68fd-su.d.ts} +17 -15
- package/dist/analyze-runs-D68fd-su.d.ts.map +1 -0
- package/dist/{baseline-Dm8966du.js → baseline-Udi_PLuT.js} +5 -5
- package/dist/{baseline-Dm8966du.js.map → baseline-Udi_PLuT.js.map} +1 -1
- package/dist/{benchmark-BywPeAUo.js → benchmark-CXmVVHH2.js} +2 -2
- package/dist/{benchmark-BywPeAUo.js.map → benchmark-CXmVVHH2.js.map} +1 -1
- package/dist/{benchmark-command-CByl9dxG.js → benchmark-command-By0vh8q7.js} +62 -45
- package/dist/benchmark-command-By0vh8q7.js.map +1 -0
- package/dist/benchmarks/index.d.ts +5 -5
- package/dist/benchmarks/index.js +3 -3
- package/dist/builder-eval/index.js +2 -2
- package/dist/campaign/index.d.ts +7 -7
- package/dist/campaign/index.js +13 -13
- package/dist/{campaign-BQ-Jujuj.js → campaign-BudZ70zo.js} +245 -247
- package/dist/campaign-BudZ70zo.js.map +1 -0
- package/dist/{campaign-evidence-OcUciD-N.js → campaign-evidence-Clrn4hBV.js} +8 -8
- package/dist/campaign-evidence-Clrn4hBV.js.map +1 -0
- package/dist/{canonical-BsZVgBhW.js → canonical-B2RqLofv.js} +2 -2
- package/dist/{canonical-BsZVgBhW.js.map → canonical-B2RqLofv.js.map} +1 -1
- package/dist/{chat-client-DthPOYGd.js → chat-client-l-MVDlDk.js} +2 -2
- package/dist/{chat-client-DthPOYGd.js.map → chat-client-l-MVDlDk.js.map} +1 -1
- package/dist/{chat-json-call-BrKsyspg.js → chat-json-call-puMArmtW.js} +2 -2
- package/dist/{chat-json-call-BrKsyspg.js.map → chat-json-call-puMArmtW.js.map} +1 -1
- package/dist/{claim-BXcZw-jo.js → claim-q4HQhK1G.js} +4 -4
- package/dist/claim-q4HQhK1G.js.map +1 -0
- package/dist/cli.js +9 -9
- package/dist/cli.js.map +1 -1
- package/dist/{cluster-bootstrap-B3JywQQn.js → cluster-bootstrap-qcUWYFl-.js} +3 -3
- package/dist/{cluster-bootstrap-B3JywQQn.js.map → cluster-bootstrap-qcUWYFl-.js.map} +1 -1
- package/dist/contract/index.d.ts +11 -11
- package/dist/contract/index.js +1022 -1078
- package/dist/contract/index.js.map +1 -1
- package/dist/{cost-ledger-D2FnJPBF.js → cost-ledger-BP8V4kUQ.js} +835 -816
- package/dist/cost-ledger-BP8V4kUQ.js.map +1 -0
- package/dist/{cost-ledger-CO7UyEcQ.d.ts → cost-ledger-Jk62OBfF.d.ts} +12 -47
- package/dist/cost-ledger-Jk62OBfF.d.ts.map +1 -0
- package/dist/{counterfactual-DtMWvn7D.js → counterfactual-Dn3veueY.js} +2 -2
- package/dist/{counterfactual-DtMWvn7D.js.map → counterfactual-Dn3veueY.js.map} +1 -1
- package/dist/{default-registry-Cn1LQ2Ve.js → default-registry-COhk9g36.js} +5 -5
- package/dist/{default-registry-Cn1LQ2Ve.js.map → default-registry-COhk9g36.js.map} +1 -1
- package/dist/{default-registry-BrWh62zf.d.ts → default-registry-DzHiGruW.d.ts} +6 -6
- package/dist/{default-registry-BrWh62zf.d.ts.map → default-registry-DzHiGruW.d.ts.map} +1 -1
- package/dist/{define-agent-eval-Ch3MWX6k.js → define-agent-eval-CNTPzIkp.js} +10 -10
- package/dist/define-agent-eval-CNTPzIkp.js.map +1 -0
- package/dist/{define-agent-eval-CEWkX5wZ.d.ts → define-agent-eval-WSck0CZJ.d.ts} +8 -8
- package/dist/{define-agent-eval-CEWkX5wZ.d.ts.map → define-agent-eval-WSck0CZJ.d.ts.map} +1 -1
- package/dist/{descriptive-CnU8Yq29.js → descriptive-DboxPZrG.js} +2 -2
- package/dist/{descriptive-CnU8Yq29.js.map → descriptive-DboxPZrG.js.map} +1 -1
- package/dist/diagnosis/index.d.ts +3 -3
- package/dist/diagnosis/index.js +4 -4
- package/dist/{dspy-rlm-engine-D-KX_e64.js → dspy-rlm-engine-LRCu61m5.js} +3 -3
- package/dist/{dspy-rlm-engine-D-KX_e64.js.map → dspy-rlm-engine-LRCu61m5.js.map} +1 -1
- package/dist/{effect-sizes-DiH8MGOH.js → effect-sizes-BhzEpXMc.js} +2 -2
- package/dist/{effect-sizes-DiH8MGOH.js.map → effect-sizes-BhzEpXMc.js.map} +1 -1
- package/dist/{engine-C_zNWfM8.d.ts → engine-3A_4jOlI.d.ts} +5 -5
- package/dist/{engine-C_zNWfM8.d.ts.map → engine-3A_4jOlI.d.ts.map} +1 -1
- package/dist/{equal-terms-Blx9Zk5I.js → equal-terms-BtdXayCJ.js} +2 -2
- package/dist/{equal-terms-Blx9Zk5I.js.map → equal-terms-BtdXayCJ.js.map} +1 -1
- package/dist/{errors-Dngq5h35.js → errors-DVZiqS7K.js} +6 -2
- package/dist/{errors-Dngq5h35.js.map → errors-DVZiqS7K.js.map} +1 -1
- package/dist/{eval-campaign-4byTtqrf.js → eval-campaign-90jeaCAI.js} +6 -6
- package/dist/{eval-campaign-4byTtqrf.js.map → eval-campaign-90jeaCAI.js.map} +1 -1
- package/dist/{evaluation-Cn2dRZIz.d.ts → evaluation-6Yoi74gM.d.ts} +4 -4
- package/dist/{evaluation-Cn2dRZIz.d.ts.map → evaluation-6Yoi74gM.d.ts.map} +1 -1
- package/dist/evaluation.d.ts +1 -1
- package/dist/evaluation.js +1 -1
- package/dist/{exact-types-CD0lf5Qd.d.ts → exact-types-ClugMJfI.d.ts} +2 -2
- package/dist/{exact-types-CD0lf5Qd.d.ts.map → exact-types-ClugMJfI.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +404 -3
- package/dist/experiment/index.d.ts.map +1 -1
- package/dist/experiment/index.js +313 -19
- package/dist/experiment/index.js.map +1 -1
- package/dist/{external-optimizer-process-nnsY5D_4.js → external-optimizer-process-BjMGUuds.js} +3 -3
- package/dist/{external-optimizer-process-nnsY5D_4.js.map → external-optimizer-process-BjMGUuds.js.map} +1 -1
- package/dist/{external-optimizer-subprocess-DcerlZSG.js → external-optimizer-subprocess-BqW0hHcI.js} +548 -548
- package/dist/external-optimizer-subprocess-BqW0hHcI.js.map +1 -0
- package/dist/{feedback-trajectory-DkaDj0dj.d.ts → feedback-trajectory-C4EG0nNH.d.ts} +5 -8
- package/dist/feedback-trajectory-C4EG0nNH.d.ts.map +1 -0
- package/dist/fuzz.d.ts +1 -1
- package/dist/fuzz.js +3 -3
- package/dist/hosted/index.js +1 -1
- package/dist/{index-CPJJr98o.d.ts → index-BFRO6chs.d.ts} +3 -2
- package/dist/index-BFRO6chs.d.ts.map +1 -0
- package/dist/{index-Ch9VxCpK.d.ts → index-BO41eGj5.d.ts} +2 -2
- package/dist/{index-Ch9VxCpK.d.ts.map → index-BO41eGj5.d.ts.map} +1 -1
- package/dist/{index-NvGBiO8H.d.ts → index-CyszSg4O.d.ts} +165 -162
- package/dist/index-CyszSg4O.d.ts.map +1 -0
- package/dist/{index-DlH0Y9gI.d.ts → index-DPcngtwt.d.ts} +30 -17
- package/dist/index-DPcngtwt.d.ts.map +1 -0
- package/dist/{index-oQ4aHziK.d.ts → index-DV-jSzxF.d.ts} +8 -8
- package/dist/{index-oQ4aHziK.d.ts.map → index-DV-jSzxF.d.ts.map} +1 -1
- package/dist/index.d.ts +1969 -1871
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +161 -201
- package/dist/index.js.map +1 -1
- package/dist/{integrity-BvnVARVl.js → integrity-BXOsAb3i.js} +2 -2
- package/dist/{integrity-BvnVARVl.js.map → integrity-BXOsAb3i.js.map} +1 -1
- package/dist/{integrity-CCAxGVK6.d.ts → integrity-DAMEDFaC.d.ts} +2 -2
- package/dist/{integrity-CCAxGVK6.d.ts.map → integrity-DAMEDFaC.d.ts.map} +1 -1
- package/dist/{integrity-BV1ZDf42.js → integrity-dLiDe2kD.js} +2 -5
- package/dist/integrity-dLiDe2kD.js.map +1 -0
- package/dist/{internal-CRHwS9iz.js → internal-Epl-YBZW.js} +3 -3
- package/dist/{internal-CRHwS9iz.js.map → internal-Epl-YBZW.js.map} +1 -1
- package/dist/interval-CELpye1n.js +219 -0
- package/dist/interval-CELpye1n.js.map +1 -0
- package/dist/interval-ohuOJurX.d.ts +47 -0
- package/dist/interval-ohuOJurX.d.ts.map +1 -0
- package/dist/{journal-DvKCvjty.js → journal-DfRz9kps.js} +2 -2
- package/dist/{journal-DvKCvjty.js.map → journal-DfRz9kps.js.map} +1 -1
- package/dist/{judge-calibration-N44V04Se.js → judge-calibration-BpCy5XQl.js} +3 -3
- package/dist/{judge-calibration-N44V04Se.js.map → judge-calibration-BpCy5XQl.js.map} +1 -1
- package/dist/{judge-gate-DNcUrRFA.d.ts → judge-gate-CE7CQAgt.d.ts} +3 -3
- package/dist/{judge-gate-DNcUrRFA.d.ts.map → judge-gate-CE7CQAgt.d.ts.map} +1 -1
- package/dist/{judge-gate-B1qYnkpi.js → judge-gate-iY9s4L44.js} +3 -3
- package/dist/judge-gate-iY9s4L44.js.map +1 -0
- package/dist/{kind-factory-CbZ-6tvu.js → kind-factory-BobI5Jy3.js} +4 -4
- package/dist/{kind-factory-CbZ-6tvu.js.map → kind-factory-BobI5Jy3.js.map} +1 -1
- package/dist/ledger-core/index.js +3 -3
- package/dist/{ledger-core-B2hahzrt.js → ledger-core-Gq7yp8lP.js} +4 -4
- package/dist/{ledger-core-B2hahzrt.js.map → ledger-core-Gq7yp8lP.js.map} +1 -1
- package/dist/{llm-client-DQveoxSM.js → llm-client-CyBAoYiX.js} +192 -219
- package/dist/llm-client-CyBAoYiX.js.map +1 -0
- package/dist/{llm-judge-PXV7Xljl.js → llm-judge-CG12SQJq.js} +499 -921
- package/dist/llm-judge-CG12SQJq.js.map +1 -0
- package/dist/matrix/index.d.ts +2 -2
- package/dist/matrix/index.js +1 -1
- package/dist/{matrix-CHMiebFx.d.ts → matrix-DSrSxjjy.d.ts} +4 -4
- package/dist/{matrix-CHMiebFx.d.ts.map → matrix-DSrSxjjy.d.ts.map} +1 -1
- package/dist/{matrix-_BV9-Lk5.js → matrix-Dm0BQW7U.js} +7 -11
- package/dist/matrix-Dm0BQW7U.js.map +1 -0
- package/dist/{paired-tests-jbwPdSz5.js → mean-DHoMiudD.js} +11 -5
- package/dist/mean-DHoMiudD.js.map +1 -0
- package/dist/meta-eval/index.d.ts +3 -3
- package/dist/meta-eval/index.js +9 -9
- package/dist/meta-eval/index.js.map +1 -1
- package/dist/mint-DNU8QPG4.d.ts +81 -0
- package/dist/mint-DNU8QPG4.d.ts.map +1 -0
- package/dist/{mint-Csor1BLJ.js → mint-QaD5cA0u.js} +3 -3
- package/dist/{mint-Csor1BLJ.js.map → mint-QaD5cA0u.js.map} +1 -1
- package/dist/{multiplicity-D9cjmStq.js → multiplicity-DQUFcbW4.js} +2 -2
- package/dist/{multiplicity-D9cjmStq.js.map → multiplicity-DQUFcbW4.js.map} +1 -1
- package/dist/multishot/golden/index.d.ts +1 -1
- package/dist/multishot/golden/index.d.ts.map +1 -1
- package/dist/multishot/golden/index.js +3 -6
- package/dist/multishot/golden/index.js.map +1 -1
- package/dist/multishot/index.d.ts +2 -2
- package/dist/multishot/index.js +1 -1
- package/dist/nonnegative-number-DvdMxg_f.js +9 -0
- package/dist/nonnegative-number-DvdMxg_f.js.map +1 -0
- package/dist/openapi.json +1 -1
- package/dist/{otel-spans-C8YIJWy1.js → otel-spans-B9tUXRHF.js} +3 -3
- package/dist/{otel-spans-C8YIJWy1.js.map → otel-spans-B9tUXRHF.js.map} +1 -1
- package/dist/{paired-arms-DzKn0TfY.js → paired-arms-CwMGJsrS.js} +5 -5
- package/dist/{paired-arms-DzKn0TfY.js.map → paired-arms-CwMGJsrS.js.map} +1 -1
- package/dist/{paired-binary-Q36bhn2R.js → paired-binary-CvpFHfKZ.js} +2 -2
- package/dist/{paired-binary-Q36bhn2R.js.map → paired-binary-CvpFHfKZ.js.map} +1 -1
- package/dist/{paired-promotion-decision-BN6IQTiu.js → paired-promotion-decision-DsAPYGCm.js} +3 -3
- package/dist/{paired-promotion-decision-BN6IQTiu.js.map → paired-promotion-decision-DsAPYGCm.js.map} +1 -1
- package/dist/{search-kernel-BztlERLv.js → pareto-Cm6ndrWN.js} +883 -861
- package/dist/pareto-Cm6ndrWN.js.map +1 -0
- package/dist/pipelines/index.d.ts +2 -2
- package/dist/pipelines/index.js +3 -3
- package/dist/{power-and-mde-fK5Qocwo.js → power-and-mde-Hj2ubb4B.js} +2 -2
- package/dist/{power-and-mde-fK5Qocwo.js.map → power-and-mde-Hj2ubb4B.js.map} +1 -1
- package/dist/predicate-FdKmElA_.js +38 -0
- package/dist/predicate-FdKmElA_.js.map +1 -0
- package/dist/{prime-protocol-DcAK9pC8.js → prime-protocol-CHKgA3a6.js} +2 -2
- package/dist/{prime-protocol-DcAK9pC8.js.map → prime-protocol-CHKgA3a6.js.map} +1 -1
- package/dist/{prime-protocol-CEE4BR9N.d.ts → prime-protocol-HiB9HX7E.d.ts} +3 -3
- package/dist/{prime-protocol-CEE4BR9N.d.ts.map → prime-protocol-HiB9HX7E.d.ts.map} +1 -1
- package/dist/{produced-state-ZCtDBxAE.js → produced-state-BsDmnwxc.js} +8 -8
- package/dist/{produced-state-ZCtDBxAE.js.map → produced-state-BsDmnwxc.js.map} +1 -1
- package/dist/profile-cell.js +1 -1
- package/dist/{release-confidence-BK2QCB5M.d.ts → promotion-gate-BawrdPYr.d.ts} +102 -102
- package/dist/promotion-gate-BawrdPYr.d.ts.map +1 -0
- package/dist/{promotion-policy-CWW35UWq.js → promotion-policy-KO57gbyV.js} +4 -4
- package/dist/{promotion-policy-CWW35UWq.js.map → promotion-policy-KO57gbyV.js.map} +1 -1
- package/dist/{proposal-findings-BZiMTzAF.js → proposal-findings-CY1xKn_a.js} +2 -2
- package/dist/{proposal-findings-BZiMTzAF.js.map → proposal-findings-CY1xKn_a.js.map} +1 -1
- package/dist/{query-B1D1qp2Z.js → query-BUCZCK7F.js} +3 -3
- package/dist/{query-B1D1qp2Z.js.map → query-BUCZCK7F.js.map} +1 -1
- package/dist/{random-Dn5fPWkt.js → random-ByUSnV9w.js} +2 -2
- package/dist/{random-Dn5fPWkt.js.map → random-ByUSnV9w.js.map} +1 -1
- package/dist/{raw-provider-sink-rB2DYxr6.js → raw-provider-sink-DoHz4JNG.js} +2 -2
- package/dist/{raw-provider-sink-rB2DYxr6.js.map → raw-provider-sink-DoHz4JNG.js.map} +1 -1
- package/dist/{redact-Dk1ZdJEm.js → redact-B5xXKqQ3.js} +97 -98
- package/dist/redact-B5xXKqQ3.js.map +1 -0
- package/dist/{redact-Cveoq6fJ.d.ts → redact-mtCCcT8z.d.ts} +4 -20
- package/dist/redact-mtCCcT8z.d.ts.map +1 -0
- package/dist/{registry-JYfPxcVz.d.ts → registry-D7_hm2fK.d.ts} +5 -5
- package/dist/{registry-JYfPxcVz.d.ts.map → registry-D7_hm2fK.d.ts.map} +1 -1
- package/dist/{release-confidence-Dbe9AS_X.js → release-confidence-CpuP65S5.js} +5 -5
- package/dist/{release-confidence-Dbe9AS_X.js.map → release-confidence-CpuP65S5.js.map} +1 -1
- package/dist/{report-command-y8H6RSX8.js → report-command-SC9nqb4M.js} +106 -171
- package/dist/report-command-SC9nqb4M.js.map +1 -0
- package/dist/reporting-html-Kvlc8oMt.js +100 -0
- package/dist/reporting-html-Kvlc8oMt.js.map +1 -0
- package/dist/reporting.d.ts +3 -3
- package/dist/reporting.js +6 -6
- package/dist/{researcher-f6mZhh58.d.ts → researcher-CEcfku-T.d.ts} +5 -5
- package/dist/{researcher-f6mZhh58.d.ts.map → researcher-CEcfku-T.d.ts.map} +1 -1
- package/dist/reward-CpCmAM8L.d.ts +78 -0
- package/dist/reward-CpCmAM8L.d.ts.map +1 -0
- package/dist/{reward-hacking-BFcQgkux.js → reward-hacking-E0d-WVcP.js} +2 -2
- package/dist/{reward-hacking-BFcQgkux.js.map → reward-hacking-E0d-WVcP.js.map} +1 -1
- package/dist/{reward-hacking-DHA7c1l8.d.ts → reward-hacking-RVdZ6Kkt.d.ts} +2 -2
- package/dist/{reward-hacking-DHA7c1l8.d.ts.map → reward-hacking-RVdZ6Kkt.d.ts.map} +1 -1
- package/dist/rl.d.ts +8 -8
- package/dist/rl.js +14 -14
- package/dist/rollout/index.d.ts +3 -2
- package/dist/rollout/index.js +2 -2
- package/dist/{rollout-D9bKKBnZ.js → rollout-DZV1t2Wg.js} +2 -2
- package/dist/{rollout-D9bKKBnZ.js.map → rollout-DZV1t2Wg.js.map} +1 -1
- package/dist/round-decimal-COrKglMh.js +10 -0
- package/dist/round-decimal-COrKglMh.js.map +1 -0
- package/dist/{rubric-predictive-validity-2SgHxoa5.d.ts → rubric-predictive-validity-C03EC7ZE.d.ts} +2 -2
- package/dist/{rubric-predictive-validity-2SgHxoa5.d.ts.map → rubric-predictive-validity-C03EC7ZE.d.ts.map} +1 -1
- package/dist/{rubric-predictive-validity-BsgkBfT0.js → rubric-predictive-validity-DaFW70y9.js} +3 -3
- package/dist/{rubric-predictive-validity-BsgkBfT0.js.map → rubric-predictive-validity-DaFW70y9.js.map} +1 -1
- package/dist/{run-record-DlTZ_lqe.js → run-record-Boc5IUTp.js} +4 -4
- package/dist/{run-record-DlTZ_lqe.js.map → run-record-Boc5IUTp.js.map} +1 -1
- package/dist/{run-record-D1Hw-Jml.d.ts → run-record-C1E24G2A.d.ts} +2 -2
- package/dist/{run-record-D1Hw-Jml.d.ts.map → run-record-C1E24G2A.d.ts.map} +1 -1
- package/dist/{run-record-ES07wfz9.js → run-record-C5e7FjhJ.js} +3 -5
- package/dist/run-record-C5e7FjhJ.js.map +1 -0
- package/dist/search/index.d.ts +46 -32
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +3 -3
- package/dist/{search-kernel-CpcKH5Ih.d.ts → search-kernel-DyNEa6IU.d.ts} +14 -10
- package/dist/search-kernel-DyNEa6IU.d.ts.map +1 -0
- package/dist/{search-ledger-d7V8o9Lk.js → search-ledger-CVUGLDZp.js} +189 -199
- package/dist/search-ledger-CVUGLDZp.js.map +1 -0
- package/dist/{search-ledger-file-BqOo-bVo.js → search-ledger-file-DDQUgvCg.js} +4 -4
- package/dist/{search-ledger-file-BqOo-bVo.js.map → search-ledger-file-DDQUgvCg.js.map} +1 -1
- package/dist/search-ledger-types-p2xKfiDJ.d.ts.map +1 -1
- package/dist/{search-shipper-er4pK5_Y.js → search-shipper-BOSD46qv.js} +3 -3
- package/dist/{search-shipper-er4pK5_Y.js.map → search-shipper-BOSD46qv.js.map} +1 -1
- package/dist/{search-summary-CBvz3u_S.js → search-summary-BQCSWf1g.js} +5 -5
- package/dist/{search-summary-CBvz3u_S.js.map → search-summary-BQCSWf1g.js.map} +1 -1
- package/dist/{semantic-concept-judge-zQBG9hHU.js → semantic-concept-judge-BQF8te0T.js} +12 -14
- package/dist/semantic-concept-judge-BQF8te0T.js.map +1 -0
- package/dist/{sequential-D-1PPCmM.js → sequential-Bf_pbE50.js} +5 -5
- package/dist/{sequential-D-1PPCmM.js.map → sequential-Bf_pbE50.js.map} +1 -1
- package/dist/{sequential-eprocess-D1jKoihe.js → sequential-eprocess-DM_qENCl.js} +2 -2
- package/dist/{sequential-eprocess-D1jKoihe.js.map → sequential-eprocess-DM_qENCl.js.map} +1 -1
- package/dist/{server-DbcC7xMl.js → server-e9oWO_bN.js} +4 -4
- package/dist/{server-DbcC7xMl.js.map → server-e9oWO_bN.js.map} +1 -1
- package/dist/{single-run-lock-fVu3MZWH.js → single-run-lock-CV9Eyd_q.js} +2 -2
- package/dist/{single-run-lock-fVu3MZWH.js.map → single-run-lock-CV9Eyd_q.js.map} +1 -1
- package/dist/{skillopt-optimization-method-CCtzralq.js → skillopt-optimization-method-BiwA8nfX.js} +427 -12
- package/dist/skillopt-optimization-method-BiwA8nfX.js.map +1 -0
- package/dist/{spans-D9_ehFuk.d.ts → spans-BHAUXMGN.d.ts} +2 -2
- package/dist/{spans-D9_ehFuk.d.ts.map → spans-BHAUXMGN.d.ts.map} +1 -1
- package/dist/{statistical-heldout-1Gbmex7v.js → statistical-heldout-42NlCNDe.js} +3 -3
- package/dist/{statistical-heldout-1Gbmex7v.js.map → statistical-heldout-42NlCNDe.js.map} +1 -1
- package/dist/{statistical-heldout-BeR4bOdg.d.ts → statistical-heldout-CYpGaoDH.d.ts} +3 -3
- package/dist/{statistical-heldout-BeR4bOdg.d.ts.map → statistical-heldout-CYpGaoDH.d.ts.map} +1 -1
- package/dist/{store-otlp-DtB4Slsr.js → store-otlp-DJ9dtA5x.js} +135 -132
- package/dist/store-otlp-DJ9dtA5x.js.map +1 -0
- package/dist/{store-tool-spans-fZIigrpP.js → store-tool-spans-CIX5arAG.js} +7 -7
- package/dist/{store-tool-spans-fZIigrpP.js.map → store-tool-spans-CIX5arAG.js.map} +1 -1
- package/dist/{store-tool-spans-DR1SrCLK.d.ts → store-tool-spans-DdCSPa7C.d.ts} +162 -161
- package/dist/store-tool-spans-DdCSPa7C.d.ts.map +1 -0
- package/dist/storyboard/index.d.ts.map +1 -1
- package/dist/storyboard/index.js +20 -3
- package/dist/storyboard/index.js.map +1 -1
- package/dist/{student-t-BQeKJx2N.js → student-t-DVPW7CdL.js} +2 -2
- package/dist/{student-t-BQeKJx2N.js.map → student-t-DVPW7CdL.js.map} +1 -1
- package/dist/{summary-report-DtdRucM0.js → summary-report-V_JACR4Y.js} +526 -614
- package/dist/summary-report-V_JACR4Y.js.map +1 -0
- package/dist/{summary-report-C-CtItCN.d.ts → summary-report-bdFDXq0b.d.ts} +10 -5
- package/dist/summary-report-bdFDXq0b.d.ts.map +1 -0
- package/dist/supervisor-run/index.d.ts +153 -149
- package/dist/supervisor-run/index.d.ts.map +1 -1
- package/dist/supervisor-run/index.js +65 -3
- package/dist/supervisor-run/index.js.map +1 -1
- package/dist/{systemone-CpTLAlqb.d.ts → systemone-BomhHr2c.d.ts} +6 -6
- package/dist/{systemone-CpTLAlqb.d.ts.map → systemone-BomhHr2c.d.ts.map} +1 -1
- package/dist/systemone-protocol.js +1 -1
- package/dist/{systemone-review-B_yo1xsd.d.ts → systemone-review-CUVcQJu6.d.ts} +2 -2
- package/dist/{systemone-review-B_yo1xsd.d.ts.map → systemone-review-CUVcQJu6.d.ts.map} +1 -1
- package/dist/{systemone-review-BZWfrtq1.js → systemone-review-D7sXwsqq.js} +2 -2
- package/dist/{systemone-review-BZWfrtq1.js.map → systemone-review-D7sXwsqq.js.map} +1 -1
- package/dist/systemone.d.ts +3 -3
- package/dist/systemone.js +4 -4
- package/dist/{task-failure-attributes-DngaLdE4.js → task-failure-attributes-hEmASjix.js} +2 -2
- package/dist/{task-failure-attributes-DngaLdE4.js.map → task-failure-attributes-hEmASjix.js.map} +1 -1
- package/dist/{terminal-record-BHocwFw1.js → terminal-record-DZyQZ3pz.js} +14 -10
- package/dist/terminal-record-DZyQZ3pz.js.map +1 -0
- package/dist/{tool-groups-mcxOXVlb.d.ts → tool-groups-C3NEcdCM.d.ts} +3 -3
- package/dist/tool-groups-C3NEcdCM.d.ts.map +1 -0
- package/dist/{tool-waste-Wi4g6Ekb.d.ts → tool-waste-BKgvd-TP.d.ts} +30 -30
- package/dist/tool-waste-BKgvd-TP.d.ts.map +1 -0
- package/dist/{tool-waste-D52PqU9Q.js → tool-waste-BlesqTqW.js} +4 -4
- package/dist/{tool-waste-D52PqU9Q.js.map → tool-waste-BlesqTqW.js.map} +1 -1
- package/dist/{trace-questions-DG7nqLQ7.d.ts → trace-questions-CM2CAocU.d.ts} +4 -4
- package/dist/{trace-questions-DG7nqLQ7.d.ts.map → trace-questions-CM2CAocU.d.ts.map} +1 -1
- package/dist/trace-repair/index.d.ts +3 -3
- package/dist/trace-repair/index.d.ts.map +1 -1
- package/dist/trace-repair/index.js +7 -13
- package/dist/trace-repair/index.js.map +1 -1
- package/dist/traces.d.ts +76 -58
- package/dist/traces.d.ts.map +1 -1
- package/dist/traces.js +9 -9
- package/dist/trajectory-replay/index.js +3 -3
- package/dist/{tree-rXLW3M_4.js → tree-C1XYeXvy.js} +2277 -2339
- package/dist/tree-C1XYeXvy.js.map +1 -0
- package/dist/{types-DBZ7keha.d.ts → types-C02qtnG8.d.ts} +4 -46
- package/dist/types-C02qtnG8.d.ts.map +1 -0
- package/dist/{types-oKRhQAde.d.ts → types-C1tnkEgM.d.ts} +4 -4
- package/dist/{types-oKRhQAde.d.ts.map → types-C1tnkEgM.d.ts.map} +1 -1
- package/dist/{types-CfZMIzB_.d.ts → types-Cbe2fWBa.d.ts} +3 -3
- package/dist/{types-CfZMIzB_.d.ts.map → types-Cbe2fWBa.d.ts.map} +1 -1
- package/dist/{types-B4C5nFw6.d.ts → types-Cq8mSbq8.d.ts} +78 -72
- package/dist/types-Cq8mSbq8.d.ts.map +1 -0
- package/dist/{verdict-DhPoXApk.js → verdict-Dl0tiT1X.js} +2 -2
- package/dist/{verdict-DhPoXApk.js.map → verdict-Dl0tiT1X.js.map} +1 -1
- package/dist/{verdict-cache-BQEsVy9n.js → verdict-cache-Bm8EKL2s.js} +2 -2
- package/dist/{verdict-cache-BQEsVy9n.js.map → verdict-cache-Bm8EKL2s.js.map} +1 -1
- package/dist/wire/index.d.ts +3 -3
- package/dist/wire/index.js +1 -1
- package/docs/design/mlbenchmarks-book-review.md +1 -1
- package/docs/design/mlbenchmarks-review/probes.mts +23 -31
- package/docs/experiment.md +1 -1
- package/package.json +1 -1
- package/dist/analyze-runs-3xpby3p2.js.map +0 -1
- package/dist/analyze-runs-CSDAh8A7.d.ts.map +0 -1
- package/dist/ast-DJ6Bc7ab.js +0 -558
- package/dist/ast-DJ6Bc7ab.js.map +0 -1
- package/dist/ast-hI-vjW6J.d.ts +0 -457
- package/dist/ast-hI-vjW6J.d.ts.map +0 -1
- package/dist/benchmark-command-CByl9dxG.js.map +0 -1
- package/dist/campaign-BQ-Jujuj.js.map +0 -1
- package/dist/campaign-evidence-OcUciD-N.js.map +0 -1
- package/dist/claim-BXcZw-jo.js.map +0 -1
- package/dist/cost-ledger-CO7UyEcQ.d.ts.map +0 -1
- package/dist/cost-ledger-D2FnJPBF.js.map +0 -1
- package/dist/define-agent-eval-Ch3MWX6k.js.map +0 -1
- package/dist/external-optimizer-subprocess-DcerlZSG.js.map +0 -1
- package/dist/feedback-trajectory-DkaDj0dj.d.ts.map +0 -1
- package/dist/index-CPJJr98o.d.ts.map +0 -1
- package/dist/index-DlH0Y9gI.d.ts.map +0 -1
- package/dist/index-NvGBiO8H.d.ts.map +0 -1
- package/dist/integrity-BV1ZDf42.js.map +0 -1
- package/dist/judge-gate-B1qYnkpi.js.map +0 -1
- package/dist/llm-client-DQveoxSM.js.map +0 -1
- package/dist/llm-judge-PXV7Xljl.js.map +0 -1
- package/dist/matrix-_BV9-Lk5.js.map +0 -1
- package/dist/mint-DCGoBYhB.d.ts +0 -155
- package/dist/mint-DCGoBYhB.d.ts.map +0 -1
- package/dist/paired-tests-jbwPdSz5.js.map +0 -1
- package/dist/redact-Cveoq6fJ.d.ts.map +0 -1
- package/dist/redact-Dk1ZdJEm.js.map +0 -1
- package/dist/release-confidence-BK2QCB5M.d.ts.map +0 -1
- package/dist/report-command-y8H6RSX8.js.map +0 -1
- package/dist/run-record-ES07wfz9.js.map +0 -1
- package/dist/search-kernel-BztlERLv.js.map +0 -1
- package/dist/search-kernel-CpcKH5Ih.d.ts.map +0 -1
- package/dist/search-ledger-d7V8o9Lk.js.map +0 -1
- package/dist/semantic-concept-judge-zQBG9hHU.js.map +0 -1
- package/dist/skillopt-optimization-method-CCtzralq.js.map +0 -1
- package/dist/store-otlp-DtB4Slsr.js.map +0 -1
- package/dist/store-tool-spans-DR1SrCLK.d.ts.map +0 -1
- package/dist/summary-report-C-CtItCN.d.ts.map +0 -1
- package/dist/summary-report-DtdRucM0.js.map +0 -1
- package/dist/terminal-record-BHocwFw1.js.map +0 -1
- package/dist/tool-groups-mcxOXVlb.d.ts.map +0 -1
- package/dist/tool-waste-Wi4g6Ekb.d.ts.map +0 -1
- package/dist/tree-rXLW3M_4.js.map +0 -1
- package/dist/types-B4C5nFw6.d.ts.map +0 -1
- package/dist/types-DBZ7keha.d.ts.map +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/experiment/ast/predicate.ts
|
|
2
|
+
/** Read a dot-separated field path. Missing segments yield `undefined`. */
|
|
3
|
+
function readField(record, path) {
|
|
4
|
+
let current = record;
|
|
5
|
+
for (const key of path.split(".")) {
|
|
6
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
7
|
+
current = current[key];
|
|
8
|
+
}
|
|
9
|
+
return current;
|
|
10
|
+
}
|
|
11
|
+
/** Evaluate a predicate against one evidence record. */
|
|
12
|
+
function evaluatePredicate(predicate, record) {
|
|
13
|
+
switch (predicate.kind) {
|
|
14
|
+
case "compare": return compareValues(readField(record, predicate.field), predicate.op, predicate.value);
|
|
15
|
+
case "in": return predicate.values.includes(readField(record, predicate.field));
|
|
16
|
+
case "all": return predicate.of.every((p) => evaluatePredicate(p, record));
|
|
17
|
+
case "any": return predicate.of.some((p) => evaluatePredicate(p, record));
|
|
18
|
+
case "not": return !evaluatePredicate(predicate.of, record);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Numbers compare numerically; everything else compares as strings. */
|
|
22
|
+
function compareValues(value, op, target) {
|
|
23
|
+
if (op === "eq") return value === target;
|
|
24
|
+
if (op === "ne") return value !== target;
|
|
25
|
+
const numeric = typeof value === "number" && typeof target === "number";
|
|
26
|
+
const left = numeric ? value : String(value);
|
|
27
|
+
const right = numeric ? target : String(target);
|
|
28
|
+
switch (op) {
|
|
29
|
+
case "lt": return left < right;
|
|
30
|
+
case "lte": return left <= right;
|
|
31
|
+
case "gt": return left > right;
|
|
32
|
+
case "gte": return left >= right;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { evaluatePredicate as n, readField as r, compareValues as t };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=predicate-FdKmElA_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate-FdKmElA_.js","names":[],"sources":["../src/experiment/ast/predicate.ts"],"sourcesContent":["import type { EvidenceRecord, JsonValue } from './evidence'\n\n// ── Predicate ────────────────────────────────────────────────────────\n\n/**\n * Closed-key comparison over a declared record schema. The only leaf node.\n * `field` is a dot-separated path into an evidence record.\n */\nexport type Predicate =\n | {\n kind: 'compare'\n field: string\n op: 'eq' | 'ne' | 'lt' | 'lte' | 'gt' | 'gte'\n value: JsonValue\n }\n | { kind: 'in'; field: string; values: JsonValue[] }\n | { kind: 'all'; of: Predicate[] }\n | { kind: 'any'; of: Predicate[] }\n | { kind: 'not'; of: Predicate }\n\n/** Read a dot-separated field path. Missing segments yield `undefined`. */\nexport function readField(record: EvidenceRecord, path: string): unknown {\n let current: unknown = record\n for (const key of path.split('.')) {\n if (current === null || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n}\n\n/** Evaluate a predicate against one evidence record. */\nexport function evaluatePredicate(predicate: Predicate, record: EvidenceRecord): boolean {\n switch (predicate.kind) {\n case 'compare':\n return compareValues(readField(record, predicate.field), predicate.op, predicate.value)\n case 'in':\n return predicate.values.includes(readField(record, predicate.field) as JsonValue)\n case 'all':\n return predicate.of.every((p) => evaluatePredicate(p, record))\n case 'any':\n return predicate.of.some((p) => evaluatePredicate(p, record))\n case 'not':\n return !evaluatePredicate(predicate.of, record)\n }\n}\n\n/** Numbers compare numerically; everything else compares as strings. */\nexport function compareValues(\n value: unknown,\n op: 'eq' | 'ne' | 'lt' | 'lte' | 'gt' | 'gte',\n target: JsonValue,\n): boolean {\n if (op === 'eq') return value === target\n if (op === 'ne') return value !== target\n const numeric = typeof value === 'number' && typeof target === 'number'\n const left = numeric ? (value as number) : String(value)\n const right = numeric ? (target as number) : String(target)\n switch (op) {\n case 'lt':\n return left < right\n case 'lte':\n return left <= right\n case 'gt':\n return left > right\n case 'gte':\n return left >= right\n }\n}\n"],"mappings":";;AAqBA,SAAgB,UAAU,QAAwB,MAAuB;CACvE,IAAI,UAAmB;CACvB,KAAK,MAAM,OAAO,KAAK,MAAM,GAAG,GAAG;EACjC,IAAI,YAAY,QAAQ,OAAO,YAAY,UAAU,OAAO,KAAA;EAC5D,UAAW,QAAoC;CACjD;CACA,OAAO;AACT;;AAGA,SAAgB,kBAAkB,WAAsB,QAAiC;CACvF,QAAQ,UAAU,MAAlB;EACE,KAAK,WACH,OAAO,cAAc,UAAU,QAAQ,UAAU,KAAK,GAAG,UAAU,IAAI,UAAU,KAAK;EACxF,KAAK,MACH,OAAO,UAAU,OAAO,SAAS,UAAU,QAAQ,UAAU,KAAK,CAAc;EAClF,KAAK,OACH,OAAO,UAAU,GAAG,OAAO,MAAM,kBAAkB,GAAG,MAAM,CAAC;EAC/D,KAAK,OACH,OAAO,UAAU,GAAG,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;EAC9D,KAAK,OACH,OAAO,CAAC,kBAAkB,UAAU,IAAI,MAAM;CAClD;AACF;;AAGA,SAAgB,cACd,OACA,IACA,QACS;CACT,IAAI,OAAO,MAAM,OAAO,UAAU;CAClC,IAAI,OAAO,MAAM,OAAO,UAAU;CAClC,MAAM,UAAU,OAAO,UAAU,YAAY,OAAO,WAAW;CAC/D,MAAM,OAAO,UAAW,QAAmB,OAAO,KAAK;CACvD,MAAM,QAAQ,UAAW,SAAoB,OAAO,MAAM;CAC1D,QAAQ,IAAR;EACE,KAAK,MACH,OAAO,OAAO;EAChB,KAAK,OACH,OAAO,QAAQ;EACjB,KAAK,MACH,OAAO,OAAO;EAChB,KAAK,OACH,OAAO,QAAQ;CACnB;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as ValidationError } from "./errors-
|
|
1
|
+
import { s as ValidationError } from "./errors-DVZiqS7K.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
//#region src/analyst/reply-contract.ts
|
|
4
4
|
/**
|
|
@@ -480,4 +480,4 @@ function primeProtocolSha256(identity) {
|
|
|
480
480
|
//#endregion
|
|
481
481
|
export { extractPrimeJsonObject as a, primeProtocolSha256 as c, runPrimeExchange as d, decodeReplyRows as f, emptyPrimeRawUsage as i, primeReplyDefect as l, buildPrimePrompt as n, mergePrimeRawUsage as o, buildPrimeRepairPrompt as r, normalizePrimeUsage as s, analystUsageReceiptFromPrimeUsage as t, projectPrimeTrajectory as u };
|
|
482
482
|
|
|
483
|
-
//# sourceMappingURL=prime-protocol-
|
|
483
|
+
//# sourceMappingURL=prime-protocol-CHKgA3a6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prime-protocol-DcAK9pC8.js","names":[],"sources":["../src/analyst/reply-contract.ts","../src/analyst/prime-protocol.ts"],"sourcesContent":["/**\n * The reply grammar an analyst arm holds a model to, independent of transport.\n *\n * One contract serves every arm shape: the inline bridge protocol\n * (`runPrimeExchange`) reads the base fields, and one-shot JSON arms\n * additionally use the strict-envelope and all-rejected knobs. `PrimeReplyContract`\n * in ./prime-protocol is a type alias of this contract, so a consumer written\n * against the prime protocol names the same grammar object.\n */\n\nimport { ValidationError } from '../errors'\n\n/** Verdict of decoding one raw reply row. */\nexport type ReplyRowDecoded<TRow> = { ok: true; row: TRow } | { ok: false; reason: string }\n\n/** A strictly parsed reply envelope: the row array plus retained extras. */\nexport interface ReplyEnvelope {\n rows: readonly unknown[]\n /** Envelope fields beside the rows the arm retains (e.g. a `report` string). */\n extras: Record<string, unknown>\n}\n\nexport interface ReplyContract<TRow> {\n /** Name of the reply's row array, e.g. `blocks` or `findings`. */\n rowsField: string\n /** Row-grammar lines spliced into the first-turn prompt. */\n contractLines: readonly string[]\n /**\n * The same grammar restated for the repair turn, which never carries the\n * evidence. Empty when the arm declares zero repair turns.\n */\n repairContractLines: readonly string[]\n /**\n * Validate and convert one raw row in a single pass. One function rather than\n * a separate validator and constructor, so the two can never disagree about\n * what a valid row is.\n */\n decodeRow(row: unknown, index: number): ReplyRowDecoded<TRow>\n /**\n * Cap on ACCEPTED rows. The cap is applied after decoding, so malformed rows\n * never consume an accepted slot; the surplus is reported as `overflow`.\n * Omit when the consumer's own expansion owns the cap and records the drop.\n */\n maxRows?: number\n /**\n * Strict envelope parse for one-shot JSON arms. Throws on an envelope defect\n * (missing report, unknown key, over-cap row count). When absent, rows are\n * read from `rowsField` on the parsed reply object.\n */\n parseEnvelope?(value: unknown): ReplyEnvelope\n /**\n * What a reply whose EVERY reported row was rejected means. `fail` throws a\n * validation error carrying each rejection; `accept-empty` (the default)\n * keeps the honest empty result beside the recorded rejections.\n */\n whenAllRowsRejected?: 'fail' | 'accept-empty'\n /**\n * Message prefix for the `fail` case, in the contract's own row vocabulary\n * (e.g. \"every reported failure block was malformed\").\n */\n allRejectedMessage?: string\n}\n\n/** One rejected row, indexed as the model reported it. */\nexport interface ReplyRowRejection {\n index: number\n reason: string\n}\n\nexport interface DecodedReply<TRow> {\n rows: TRow[]\n /** Envelope fields beside the rows (empty when the contract has no envelope). */\n extras: Record<string, unknown>\n rejected: ReplyRowRejection[]\n /** Rows the model reported, before decoding or the count cap. */\n reportedRows: number\n /** Valid rows dropped by `maxRows`. */\n overflow: number\n}\n\n/**\n * The per-row half of a decode: validate each raw row under the contract's\n * grammar and cap ACCEPTED rows. Shape before count — a malformed row never\n * consumes an accepted slot. Shared by every consumer of a `ReplyContract`\n * row array, whatever envelope handling surrounds it.\n */\nexport function decodeContractRows<TRow>(\n contract: Pick<ReplyContract<TRow>, 'decodeRow' | 'maxRows'>,\n rawRows: readonly unknown[],\n): { rows: TRow[]; rejected: ReplyRowRejection[]; overflow: number } {\n const rows: TRow[] = []\n const rejected: ReplyRowRejection[] = []\n let overflow = 0\n rawRows.forEach((row, index) => {\n const decoded = contract.decodeRow(row, index)\n if (!decoded.ok) {\n rejected.push({ index, reason: decoded.reason })\n return\n }\n if (contract.maxRows !== undefined && rows.length >= contract.maxRows) {\n overflow += 1\n return\n }\n rows.push(decoded.row)\n })\n return { rows, rejected, overflow }\n}\n\n/**\n * Decode a parsed reply value under a contract: strict envelope when declared,\n * then per-row decoding, then the all-rejected policy.\n */\nexport function decodeReplyRows<TRow>(\n contract: ReplyContract<TRow>,\n value: unknown,\n): DecodedReply<TRow> {\n let rawRows: readonly unknown[]\n let extras: Record<string, unknown> = {}\n if (contract.parseEnvelope) {\n const envelope = contract.parseEnvelope(value)\n rawRows = envelope.rows\n extras = envelope.extras\n } else {\n const record =\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n const field = record?.[contract.rowsField]\n if (!Array.isArray(field)) {\n throw new ValidationError(`reply has no \"${contract.rowsField}\" array`)\n }\n rawRows = field\n }\n const { rows, rejected, overflow } = decodeContractRows(contract, rawRows)\n if (rows.length === 0 && rawRows.length > 0 && contract.whenAllRowsRejected === 'fail') {\n throw new ValidationError(\n `${contract.allRejectedMessage ?? 'every reported row was malformed'}: ${rejected\n .map((entry) => entry.reason)\n .join(' | ')}`,\n )\n }\n return { rows, extras, rejected, reportedRows: rawRows.length, overflow }\n}\n","import { createHash } from 'node:crypto'\nimport type { CustomTokenPricing } from '../cost-ledger'\nimport type { PrimeBridgeTransport, PrimeBridgeTransportResult } from './prime-bridge-transport'\nimport { decodeContractRows, type ReplyContract, type ReplyRowDecoded } from './reply-contract'\nimport type { AnalystUsageReceipt } from './types'\n\n/**\n * The prime analyst protocol: a one-shot RLM reached through an\n * OpenAI-compatible bridge, given the whole trajectory inline because it has no\n * REPL and no trace tools, answering in one fenced JSON block of short strings.\n *\n * This module owns every part of that protocol that does not depend on what the\n * rows MEAN: prompt and contract composition, the bounded repair turn, reply\n * extraction, row decoding order, the render-measure-fall-back-fail-loud\n * projection ladder, usage normalization, and the protocol identity digest.\n *\n * The cut: the core speaks RAW ROWS and never names a finding type. It knows a\n * prime reply carries an `answer` string plus an array of rows under a named\n * field, and that each row is decoded by a caller-supplied function. Consumers\n * — the CodeTraceBench benchmark runner here, a span-grounded trace analyzer\n * elsewhere — map decoded rows into their own finding shape on the way out. So\n * nothing in this file may import a block type, a finding type, or a trace\n * store, and no consumer needs another copy of the protocol.\n */\n\n// ── Reply contract ───────────────────────────────────────────────────\n\n/**\n * The prime reply grammar is the general analyst reply contract: these aliases\n * keep every prime-protocol consumer compiling against the shared type in\n * ./reply-contract. The exchange below reads the base fields (`rowsField`,\n * contract lines, `decodeRow`, `maxRows`); the strict-envelope knobs serve\n * one-shot JSON arms and are inert here.\n */\nexport type PrimeRowDecoded<TRow> = ReplyRowDecoded<TRow>\n\nexport type PrimeReplyContract<TRow> = ReplyContract<TRow>\n\n// ── Prompt composition ───────────────────────────────────────────────\n\nexport interface PrimePromptSpec {\n question: string\n /** Task definition spliced under a `TASK DEFINITION:` heading. Omit when the question is the whole task. */\n taskDefinition?: string\n contractLines: readonly string[]\n /** Line introducing the trajectory, e.g. `TRAJECTORY (trace_id X; 12 assistant step spans; ...):`. */\n trajectoryHeader: string\n renderedTrajectory: string\n /** Material appended after the trajectory, e.g. the final-verification spans. */\n trailer?: string\n}\n\nexport function buildPrimePrompt(spec: PrimePromptSpec): string {\n return [\n `QUESTION: ${spec.question}`,\n '',\n ...(spec.taskDefinition === undefined ? [] : ['TASK DEFINITION:', spec.taskDefinition, '']),\n ...spec.contractLines,\n '',\n spec.trajectoryHeader,\n spec.renderedTrajectory,\n ...(spec.trailer === undefined ? [] : ['', spec.trailer]),\n ].join('\\n')\n}\n\nexport interface PrimeRepairPromptSpec {\n defect: string\n previousReply: string\n repairContractLines: readonly string[]\n}\n\n/** Carries the malformed reply and the contract — never the trajectory. */\nexport function buildPrimeRepairPrompt(spec: PrimeRepairPromptSpec): string {\n return [\n 'Your previous reply to a trace-analysis task was structurally malformed and could not be parsed',\n `(${spec.defect}). Below is your previous reply verbatim. Re-emit ONLY the corrected JSON — one`,\n 'fenced ```json block, no other text, no tools. The JSON object has exactly two fields:',\n ...spec.repairContractLines,\n '',\n 'PREVIOUS REPLY:',\n spec.previousReply,\n ].join('\\n')\n}\n\n// ── Reply extraction ─────────────────────────────────────────────────\n\n/**\n * Recover the reply's JSON object.\n *\n * Distinct from `extractJsonPayload` in ../llm-client, which serves a response\n * that DECLARES a JSON root and therefore must not scan onward. A prime reply\n * is prose plus a fenced block, and when the model emits several fences the\n * last one is its answer — so fences are scanned in reverse, and only then is a\n * brace-to-brace slice tried.\n */\nexport function extractPrimeJsonObject(text: string): Record<string, unknown> | null {\n const direct = parsePrimeJsonObject(text)\n if (direct) return direct\n const fenced = [...text.matchAll(/```(?:json)?\\s*\\n?([\\s\\S]*?)```/g)]\n for (let index = fenced.length - 1; index >= 0; index -= 1) {\n const candidate = parsePrimeJsonObject(fenced[index]![1]!)\n if (candidate) return candidate\n }\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start >= 0 && end > start) {\n const candidate = parsePrimeJsonObject(text.slice(start, end + 1))\n if (candidate) return candidate\n }\n return null\n}\n\n/** Why the reply cannot be read as a prime answer, or null when it can. */\nexport function primeReplyDefect(\n parsed: Record<string, unknown> | null,\n rowsField: string,\n): string | null {\n if (parsed === null) return 'no parseable JSON object'\n if (!Array.isArray(parsed[rowsField])) return `JSON has no \"${rowsField}\" array`\n return null\n}\n\nfunction parsePrimeJsonObject(text: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(text.trim())\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null\n } catch {\n return null\n }\n}\n\n// ── Usage ────────────────────────────────────────────────────────────\n\n/**\n * Token accounting exactly as the bridge reported it. Lossless on purpose: a\n * side the bridge did not report stays null rather than becoming a zero, and a\n * side it DID report survives even when its partner is missing.\n */\nexport interface PrimeRawUsage {\n /**\n * Model-usage records the bridge observed. NOT a count of bridge round trips:\n * one prime turn routes several internal model calls, so a single turn\n * typically reports 3-5.\n */\n calls: number | null\n /** Prompt tokens the bridge reported; null when it reported none. */\n inputTokens: number | null\n /** Completion tokens the bridge reported; null when it reported none. */\n outputTokens: number | null\n /**\n * True when the bridge DERIVED the counts (from character lengths) because\n * the backend reported no usage of its own. Pricing derived counts produces a\n * guess about a guess, which a reader must be able to tell apart from a\n * rate-estimated cost over exact tokens.\n */\n bridgeEstimated: boolean\n}\n\nexport function emptyPrimeRawUsage(): PrimeRawUsage {\n return { calls: null, inputTokens: null, outputTokens: null, bridgeEstimated: false }\n}\n\n/** Read the bridge's OpenAI-shaped `usage` object. */\nexport function normalizePrimeUsage(raw: unknown): PrimeRawUsage {\n if (typeof raw !== 'object' || raw === null) return emptyPrimeRawUsage()\n const record = raw as Record<string, unknown>\n return {\n calls: tokenCountOrNull(record.model_requests),\n inputTokens: tokenCountOrNull(record.prompt_tokens),\n outputTokens: tokenCountOrNull(record.completion_tokens),\n bridgeEstimated: record.estimated === true,\n }\n}\n\n/**\n * Sum two turns. Each side poisons independently: two turns that both report\n * input and neither report output yield a real input total beside a null\n * output, because discarding a measured count is as wrong as inventing one.\n */\nexport function mergePrimeRawUsage(a: PrimeRawUsage, b: PrimeRawUsage): PrimeRawUsage {\n return {\n calls: sumOrNull(a.calls, b.calls),\n inputTokens: sumOrNull(a.inputTokens, b.inputTokens),\n outputTokens: sumOrNull(a.outputTokens, b.outputTokens),\n bridgeEstimated: a.bridgeEstimated || b.bridgeEstimated,\n }\n}\n\nfunction sumOrNull(a: number | null, b: number | null): number | null {\n return a !== null && b !== null ? a + b : null\n}\n\nfunction tokenCountOrNull(value: unknown): number | null {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null\n}\n\n/**\n * Bind raw prime usage to agent-eval's typed receipt.\n *\n * `RunTokenUsage.input` and `.output` are non-nullable, so a one-sided count\n * cannot round-trip through `tokens` without writing a zero nobody measured.\n * The complete-accounting field therefore stays null, the reported side is\n * carried verbatim in `partialTokens`, and its price becomes the receipt's\n * `knownCostUsd` lower bound.\n *\n * Only agent-eval calls this; consumers with no pricing table read\n * `PrimeRawUsage` directly.\n */\nexport function analystUsageReceiptFromPrimeUsage(\n usage: PrimeRawUsage,\n pricing: CustomTokenPricing,\n): AnalystUsageReceipt {\n const { calls, inputTokens, outputTokens, bridgeEstimated } = usage\n const estimatedTokens = bridgeEstimated ? { tokensEstimated: true } : {}\n if (inputTokens !== null && outputTokens !== null) {\n return {\n calls,\n tokens: { input: inputTokens, output: outputTokens },\n cost: { kind: 'estimated', usd: priceTokens(inputTokens, outputTokens, pricing) },\n ...estimatedTokens,\n }\n }\n if (inputTokens === null && outputTokens === null) {\n return { calls, tokens: null, cost: { kind: 'uncaptured', usd: null }, ...estimatedTokens }\n }\n return {\n calls,\n tokens: null,\n partialTokens: { input: inputTokens, output: outputTokens },\n cost: { kind: 'uncaptured', usd: null },\n knownCostUsd: priceTokens(inputTokens ?? 0, outputTokens ?? 0, pricing),\n ...estimatedTokens,\n }\n}\n\nfunction priceTokens(input: number, output: number, pricing: CustomTokenPricing): number {\n return (input * pricing.inputUsdPerMillion + output * pricing.outputUsdPerMillion) / 1_000_000\n}\n\n// ── Two-turn exchange ────────────────────────────────────────────────\n\n/**\n * Why an exchange ended without a readable reply. `deadline` and `aborted` are\n * separate members from `transport` on purpose: a model that ran past its\n * deadline, a caller who cancelled, and a bridge that refused the connection\n * demand three different responses, and a record that conflates them cannot be\n * acted on.\n */\nexport type PrimeFailure =\n | {\n kind: 'transport' | 'unparseable-json' | 'no-content' | 'deadline' | 'malformed-reply'\n message: string\n }\n | { kind: 'http-status'; message: string; status: number; bodySnippet: string }\n | { kind: 'aborted'; message: string; cause: unknown }\n\nexport interface PrimeRepairState {\n attempted: boolean\n /** Null when no repair turn ran, or when the repair turn never returned a reply. */\n succeeded: boolean | null\n}\n\n/** One completed bridge turn. A turn that failed produces no record. */\nexport interface PrimeTurnRecord {\n turn: 'first' | 'repair'\n usage: PrimeRawUsage\n /** The reply's `usage` object verbatim; null when the bridge sent none. */\n rawUsage: unknown\n}\n\nexport interface PrimeRejectedRow {\n index: number\n reason: string\n}\n\nexport type PrimeExchangeOutcome<TRow> =\n | {\n ok: true\n /** The reply's `answer` field; null when absent or not a string. */\n answer: string | null\n rows: TRow[]\n rejected: PrimeRejectedRow[]\n /** Rows the model reported, before decoding or the count cap. */\n reportedRows: number\n /** Valid rows dropped by `contract.maxRows`. */\n overflow: number\n usage: PrimeRawUsage\n turns: PrimeTurnRecord[]\n repair: PrimeRepairState\n reply: string\n }\n | {\n ok: false\n failure: PrimeFailure\n usage: PrimeRawUsage\n turns: PrimeTurnRecord[]\n repair: PrimeRepairState\n /** The last reply received, when one arrived — the diagnostic artifact for a malformed case. */\n reply?: string\n }\n\nexport interface PrimeExchangeOptions<TRow> {\n contract: PrimeReplyContract<TRow>\n prompt: string\n transport: PrimeBridgeTransport\n /** Full endpoint, e.g. `http://localhost:4181/v1/chat/completions`. */\n url: string\n model: string\n /** Deadline for ONE turn. Prime analyses routinely exceed five minutes. */\n timeoutMs: number\n /** Whether a structurally malformed reply gets one bounded repair turn. */\n repair: boolean\n signal?: AbortSignal\n}\n\n/**\n * Run the protocol: one call, one bounded repair turn on a structurally\n * malformed reply, then decode. Zero valid rows from a well-formed reply is an\n * honest null, not a failure.\n */\nexport async function runPrimeExchange<TRow>(\n options: PrimeExchangeOptions<TRow>,\n): Promise<PrimeExchangeOutcome<TRow>> {\n const { contract } = options\n const turns: PrimeTurnRecord[] = []\n const repair: PrimeRepairState = { attempted: false, succeeded: null }\n\n const first = await callPrimeTurn(options, options.prompt)\n if (!first.ok) {\n return { ok: false, failure: first.failure, usage: mergeTurns(turns), turns, repair }\n }\n turns.push({ turn: 'first', usage: first.usage, rawUsage: first.rawUsage })\n\n let reply = first.content\n let parsed = extractPrimeJsonObject(reply)\n let defect = primeReplyDefect(parsed, contract.rowsField)\n\n if (defect !== null && options.repair) {\n repair.attempted = true\n const second = await callPrimeTurn(\n options,\n buildPrimeRepairPrompt({\n defect,\n previousReply: reply,\n repairContractLines: contract.repairContractLines,\n }),\n )\n if (!second.ok) {\n return { ok: false, failure: second.failure, usage: mergeTurns(turns), turns, repair, reply }\n }\n turns.push({ turn: 'repair', usage: second.usage, rawUsage: second.rawUsage })\n reply = second.content\n parsed = extractPrimeJsonObject(reply)\n defect = primeReplyDefect(parsed, contract.rowsField)\n repair.succeeded = defect === null\n }\n\n const usage = mergeTurns(turns)\n if (defect !== null) {\n return {\n ok: false,\n failure: {\n kind: 'malformed-reply',\n message: `${defect} in prime reply${repair.attempted ? ' even after the bounded repair turn' : ''}`,\n },\n usage,\n turns,\n repair,\n reply,\n }\n }\n\n const rawRows = parsed![contract.rowsField] as unknown[]\n const { rows, rejected, overflow } = decodeContractRows(contract, rawRows)\n const answer = parsed!.answer\n return {\n ok: true,\n answer: typeof answer === 'string' ? answer : null,\n rows,\n rejected,\n reportedRows: rawRows.length,\n overflow,\n usage,\n turns,\n repair,\n reply,\n }\n}\n\ntype PrimeTurnOutcome =\n | { ok: true; content: string; usage: PrimeRawUsage; rawUsage: unknown }\n | { ok: false; failure: PrimeFailure }\n\nasync function callPrimeTurn<TRow>(\n options: PrimeExchangeOptions<TRow>,\n content: string,\n): Promise<PrimeTurnOutcome> {\n const { transport, url, model, timeoutMs, signal } = options\n const controller = new AbortController()\n const forwardAbort = () => controller.abort(signal?.reason)\n if (signal?.aborted) controller.abort(signal.reason)\n else signal?.addEventListener('abort', forwardAbort, { once: true })\n const deadline = setTimeout(() => controller.abort(), timeoutMs)\n let result: PrimeBridgeTransportResult\n try {\n result = await transport({\n url,\n body: { model, messages: [{ role: 'user', content }] },\n signal: controller.signal,\n })\n } catch (error) {\n if (signal?.aborted) {\n return {\n ok: false,\n failure: {\n kind: 'aborted',\n message: 'prime exchange cancelled by the caller',\n cause: error,\n },\n }\n }\n if (controller.signal.aborted) {\n return {\n ok: false,\n failure: { kind: 'deadline', message: `bridge call exceeded ${timeoutMs}ms` },\n }\n }\n return {\n ok: false,\n failure: {\n kind: 'transport',\n message: `bridge transport failure: ${error instanceof Error ? error.message : String(error)}`,\n },\n }\n } finally {\n clearTimeout(deadline)\n signal?.removeEventListener('abort', forwardAbort)\n }\n\n if (result.status !== 200) {\n const bodySnippet = result.text.slice(0, 500)\n return {\n ok: false,\n failure: {\n kind: 'http-status',\n message: `bridge HTTP ${result.status}: ${bodySnippet}`,\n status: result.status,\n bodySnippet,\n },\n }\n }\n let response: unknown\n try {\n response = JSON.parse(result.text)\n } catch {\n return {\n ok: false,\n failure: {\n kind: 'unparseable-json',\n message: `bridge returned unparseable JSON (${result.text.length} bytes)`,\n },\n }\n }\n const replyContent = primeReplyContent(response)\n if (replyContent === null) {\n return {\n ok: false,\n failure: { kind: 'no-content', message: 'bridge reply carries no message content' },\n }\n }\n const rawUsage = primeReplyUsage(response)\n return { ok: true, content: replyContent, usage: normalizePrimeUsage(rawUsage), rawUsage }\n}\n\n/**\n * Fold from the FIRST turn, never from an empty receipt: an all-null identity\n * would poison every side it merged with and erase counts the bridge reported.\n */\nfunction mergeTurns(turns: readonly PrimeTurnRecord[]): PrimeRawUsage {\n if (turns.length === 0) return emptyPrimeRawUsage()\n return turns\n .slice(1)\n .reduce<PrimeRawUsage>((total, turn) => mergePrimeRawUsage(total, turn.usage), turns[0]!.usage)\n}\n\nfunction primeReplyContent(response: unknown): string | null {\n if (typeof response !== 'object' || response === null) return null\n const choices = (response as { choices?: unknown }).choices\n if (!Array.isArray(choices) || choices.length === 0) return null\n const message = (choices[0] as { message?: unknown })?.message\n if (typeof message !== 'object' || message === null) return null\n const content = (message as { content?: unknown }).content\n return typeof content === 'string' && content.length > 0 ? content : null\n}\n\nfunction primeReplyUsage(response: unknown): unknown {\n if (typeof response !== 'object' || response === null) return null\n return (response as { usage?: unknown }).usage ?? null\n}\n\n// ── Trajectory projection ────────────────────────────────────────────\n\n/**\n * Where the inlined trajectory comes from. The protocol needs only two moves —\n * fetch it all, or fetch a reduced version — so no store, artifact path, or\n * span type enters the shared signature.\n */\nexport interface PrimeProjectionSource<TItem> {\n /** The full projection, or null when the source declares itself oversized. */\n full(): Promise<readonly TItem[] | null>\n /** A reduced projection of the same material. */\n capped(): Promise<readonly TItem[]>\n /** How `capped` reduces, named for the failure message, e.g. `per-attribute cap 1200`. */\n cappedDescription: string\n}\n\nexport interface PrimeProjectionDelivery {\n mode: 'inline-json'\n fetch: 'full' | 'capped'\n renderedChars: number\n}\n\nexport type PrimeProjectionOutcome<TItem> =\n | {\n ok: true\n items: readonly TItem[]\n rendered: string\n delivery: PrimeProjectionDelivery\n }\n | { ok: false; reason: string; renderedChars: number }\n\n/**\n * Render, measure, fall back to the capped projection, re-measure, fail loud.\n *\n * Inline is the only delivery prime has, so an oversized trajectory is a\n * refusal rather than a silent truncation: dropping spans would understate the\n * trajectory and the analyst would answer a question about a different run.\n */\nexport async function projectPrimeTrajectory<TItem>(\n source: PrimeProjectionSource<TItem>,\n limits: { maxInlineChars: number },\n): Promise<PrimeProjectionOutcome<TItem>> {\n let fetch: PrimeProjectionDelivery['fetch'] = 'full'\n let items = await source.full()\n if (items === null) {\n fetch = 'capped'\n items = await source.capped()\n }\n let rendered = JSON.stringify(items)\n if (rendered.length > limits.maxInlineChars && fetch === 'full') {\n fetch = 'capped'\n items = await source.capped()\n rendered = JSON.stringify(items)\n }\n if (rendered.length > limits.maxInlineChars) {\n return {\n ok: false,\n reason: `trajectory renders to ${rendered.length} chars even at ${source.cappedDescription}; inline delivery impossible`,\n renderedChars: rendered.length,\n }\n }\n return {\n ok: true,\n items,\n rendered,\n delivery: { mode: 'inline-json', fetch, renderedChars: rendered.length },\n }\n}\n\n// ── Protocol identity ────────────────────────────────────────────────\n\nexport interface PrimeProtocolIdentity {\n question: string\n taskDefinition?: string\n contractLines: readonly string[]\n repairContractLines: readonly string[]\n /** Numeric limits the contract states, e.g. row and width caps. */\n limits: Readonly<Record<string, number>>\n}\n\n/**\n * Digest of everything a consumer can send to the bridge under the prime\n * protocol, recorded per observation so a prime result names the exact contract\n * that produced it.\n *\n * Computed over the ACTUALLY composed contract, so two consumers that both\n * stamp `analyst_id: 'prime'` while asking materially different questions get\n * different digests by construction. That is what makes 'prime' a reproducible\n * claim rather than a label.\n */\nexport function primeProtocolSha256(identity: PrimeProtocolIdentity): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n kind: 'prime-analyst-protocol',\n question: identity.question,\n taskPrompt: identity.taskDefinition ?? null,\n outputContract: identity.contractLines,\n repairContract: buildPrimeRepairPrompt({\n defect: '<defect>',\n previousReply: '<previous-reply>',\n repairContractLines: identity.repairContractLines,\n }),\n limits: identity.limits,\n }),\n )\n .digest('hex')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prime-protocol-CHKgA3a6.js","names":[],"sources":["../src/analyst/reply-contract.ts","../src/analyst/prime-protocol.ts"],"sourcesContent":["/**\n * The reply grammar an analyst arm holds a model to, independent of transport.\n *\n * One contract serves every arm shape: the inline bridge protocol\n * (`runPrimeExchange`) reads the base fields, and one-shot JSON arms\n * additionally use the strict-envelope and all-rejected knobs. `PrimeReplyContract`\n * in ./prime-protocol is a type alias of this contract, so a consumer written\n * against the prime protocol names the same grammar object.\n */\n\nimport { ValidationError } from '../errors'\n\n/** Verdict of decoding one raw reply row. */\nexport type ReplyRowDecoded<TRow> = { ok: true; row: TRow } | { ok: false; reason: string }\n\n/** A strictly parsed reply envelope: the row array plus retained extras. */\nexport interface ReplyEnvelope {\n rows: readonly unknown[]\n /** Envelope fields beside the rows the arm retains (e.g. a `report` string). */\n extras: Record<string, unknown>\n}\n\nexport interface ReplyContract<TRow> {\n /** Name of the reply's row array, e.g. `blocks` or `findings`. */\n rowsField: string\n /** Row-grammar lines spliced into the first-turn prompt. */\n contractLines: readonly string[]\n /**\n * The same grammar restated for the repair turn, which never carries the\n * evidence. Empty when the arm declares zero repair turns.\n */\n repairContractLines: readonly string[]\n /**\n * Validate and convert one raw row in a single pass. One function rather than\n * a separate validator and constructor, so the two can never disagree about\n * what a valid row is.\n */\n decodeRow(row: unknown, index: number): ReplyRowDecoded<TRow>\n /**\n * Cap on ACCEPTED rows. The cap is applied after decoding, so malformed rows\n * never consume an accepted slot; the surplus is reported as `overflow`.\n * Omit when the consumer's own expansion owns the cap and records the drop.\n */\n maxRows?: number\n /**\n * Strict envelope parse for one-shot JSON arms. Throws on an envelope defect\n * (missing report, unknown key, over-cap row count). When absent, rows are\n * read from `rowsField` on the parsed reply object.\n */\n parseEnvelope?(value: unknown): ReplyEnvelope\n /**\n * What a reply whose EVERY reported row was rejected means. `fail` throws a\n * validation error carrying each rejection; `accept-empty` (the default)\n * keeps the honest empty result beside the recorded rejections.\n */\n whenAllRowsRejected?: 'fail' | 'accept-empty'\n /**\n * Message prefix for the `fail` case, in the contract's own row vocabulary\n * (e.g. \"every reported failure block was malformed\").\n */\n allRejectedMessage?: string\n}\n\n/** One rejected row, indexed as the model reported it. */\nexport interface ReplyRowRejection {\n index: number\n reason: string\n}\n\nexport interface DecodedReply<TRow> {\n rows: TRow[]\n /** Envelope fields beside the rows (empty when the contract has no envelope). */\n extras: Record<string, unknown>\n rejected: ReplyRowRejection[]\n /** Rows the model reported, before decoding or the count cap. */\n reportedRows: number\n /** Valid rows dropped by `maxRows`. */\n overflow: number\n}\n\n/**\n * The per-row half of a decode: validate each raw row under the contract's\n * grammar and cap ACCEPTED rows. Shape before count — a malformed row never\n * consumes an accepted slot. Shared by every consumer of a `ReplyContract`\n * row array, whatever envelope handling surrounds it.\n */\nexport function decodeContractRows<TRow>(\n contract: Pick<ReplyContract<TRow>, 'decodeRow' | 'maxRows'>,\n rawRows: readonly unknown[],\n): { rows: TRow[]; rejected: ReplyRowRejection[]; overflow: number } {\n const rows: TRow[] = []\n const rejected: ReplyRowRejection[] = []\n let overflow = 0\n rawRows.forEach((row, index) => {\n const decoded = contract.decodeRow(row, index)\n if (!decoded.ok) {\n rejected.push({ index, reason: decoded.reason })\n return\n }\n if (contract.maxRows !== undefined && rows.length >= contract.maxRows) {\n overflow += 1\n return\n }\n rows.push(decoded.row)\n })\n return { rows, rejected, overflow }\n}\n\n/**\n * Decode a parsed reply value under a contract: strict envelope when declared,\n * then per-row decoding, then the all-rejected policy.\n */\nexport function decodeReplyRows<TRow>(\n contract: ReplyContract<TRow>,\n value: unknown,\n): DecodedReply<TRow> {\n let rawRows: readonly unknown[]\n let extras: Record<string, unknown> = {}\n if (contract.parseEnvelope) {\n const envelope = contract.parseEnvelope(value)\n rawRows = envelope.rows\n extras = envelope.extras\n } else {\n const record =\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n const field = record?.[contract.rowsField]\n if (!Array.isArray(field)) {\n throw new ValidationError(`reply has no \"${contract.rowsField}\" array`)\n }\n rawRows = field\n }\n const { rows, rejected, overflow } = decodeContractRows(contract, rawRows)\n if (rows.length === 0 && rawRows.length > 0 && contract.whenAllRowsRejected === 'fail') {\n throw new ValidationError(\n `${contract.allRejectedMessage ?? 'every reported row was malformed'}: ${rejected\n .map((entry) => entry.reason)\n .join(' | ')}`,\n )\n }\n return { rows, extras, rejected, reportedRows: rawRows.length, overflow }\n}\n","import { createHash } from 'node:crypto'\nimport type { CustomTokenPricing } from '../cost-ledger'\nimport type { PrimeBridgeTransport, PrimeBridgeTransportResult } from './prime-bridge-transport'\nimport { decodeContractRows, type ReplyContract, type ReplyRowDecoded } from './reply-contract'\nimport type { AnalystUsageReceipt } from './types'\n\n/**\n * The prime analyst protocol: a one-shot RLM reached through an\n * OpenAI-compatible bridge, given the whole trajectory inline because it has no\n * REPL and no trace tools, answering in one fenced JSON block of short strings.\n *\n * This module owns every part of that protocol that does not depend on what the\n * rows MEAN: prompt and contract composition, the bounded repair turn, reply\n * extraction, row decoding order, the render-measure-fall-back-fail-loud\n * projection ladder, usage normalization, and the protocol identity digest.\n *\n * The cut: the core speaks RAW ROWS and never names a finding type. It knows a\n * prime reply carries an `answer` string plus an array of rows under a named\n * field, and that each row is decoded by a caller-supplied function. Consumers\n * — the CodeTraceBench benchmark runner here, a span-grounded trace analyzer\n * elsewhere — map decoded rows into their own finding shape on the way out. So\n * nothing in this file may import a block type, a finding type, or a trace\n * store, and no consumer needs another copy of the protocol.\n */\n\n// ── Reply contract ───────────────────────────────────────────────────\n\n/**\n * The prime reply grammar is the general analyst reply contract: these aliases\n * keep every prime-protocol consumer compiling against the shared type in\n * ./reply-contract. The exchange below reads the base fields (`rowsField`,\n * contract lines, `decodeRow`, `maxRows`); the strict-envelope knobs serve\n * one-shot JSON arms and are inert here.\n */\nexport type PrimeRowDecoded<TRow> = ReplyRowDecoded<TRow>\n\nexport type PrimeReplyContract<TRow> = ReplyContract<TRow>\n\n// ── Prompt composition ───────────────────────────────────────────────\n\nexport interface PrimePromptSpec {\n question: string\n /** Task definition spliced under a `TASK DEFINITION:` heading. Omit when the question is the whole task. */\n taskDefinition?: string\n contractLines: readonly string[]\n /** Line introducing the trajectory, e.g. `TRAJECTORY (trace_id X; 12 assistant step spans; ...):`. */\n trajectoryHeader: string\n renderedTrajectory: string\n /** Material appended after the trajectory, e.g. the final-verification spans. */\n trailer?: string\n}\n\nexport function buildPrimePrompt(spec: PrimePromptSpec): string {\n return [\n `QUESTION: ${spec.question}`,\n '',\n ...(spec.taskDefinition === undefined ? [] : ['TASK DEFINITION:', spec.taskDefinition, '']),\n ...spec.contractLines,\n '',\n spec.trajectoryHeader,\n spec.renderedTrajectory,\n ...(spec.trailer === undefined ? [] : ['', spec.trailer]),\n ].join('\\n')\n}\n\nexport interface PrimeRepairPromptSpec {\n defect: string\n previousReply: string\n repairContractLines: readonly string[]\n}\n\n/** Carries the malformed reply and the contract — never the trajectory. */\nexport function buildPrimeRepairPrompt(spec: PrimeRepairPromptSpec): string {\n return [\n 'Your previous reply to a trace-analysis task was structurally malformed and could not be parsed',\n `(${spec.defect}). Below is your previous reply verbatim. Re-emit ONLY the corrected JSON — one`,\n 'fenced ```json block, no other text, no tools. The JSON object has exactly two fields:',\n ...spec.repairContractLines,\n '',\n 'PREVIOUS REPLY:',\n spec.previousReply,\n ].join('\\n')\n}\n\n// ── Reply extraction ─────────────────────────────────────────────────\n\n/**\n * Recover the reply's JSON object.\n *\n * Distinct from `extractJsonPayload` in ../llm-client, which serves a response\n * that DECLARES a JSON root and therefore must not scan onward. A prime reply\n * is prose plus a fenced block, and when the model emits several fences the\n * last one is its answer — so fences are scanned in reverse, and only then is a\n * brace-to-brace slice tried.\n */\nexport function extractPrimeJsonObject(text: string): Record<string, unknown> | null {\n const direct = parsePrimeJsonObject(text)\n if (direct) return direct\n const fenced = [...text.matchAll(/```(?:json)?\\s*\\n?([\\s\\S]*?)```/g)]\n for (let index = fenced.length - 1; index >= 0; index -= 1) {\n const candidate = parsePrimeJsonObject(fenced[index]![1]!)\n if (candidate) return candidate\n }\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start >= 0 && end > start) {\n const candidate = parsePrimeJsonObject(text.slice(start, end + 1))\n if (candidate) return candidate\n }\n return null\n}\n\n/** Why the reply cannot be read as a prime answer, or null when it can. */\nexport function primeReplyDefect(\n parsed: Record<string, unknown> | null,\n rowsField: string,\n): string | null {\n if (parsed === null) return 'no parseable JSON object'\n if (!Array.isArray(parsed[rowsField])) return `JSON has no \"${rowsField}\" array`\n return null\n}\n\nfunction parsePrimeJsonObject(text: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(text.trim())\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null\n } catch {\n return null\n }\n}\n\n// ── Usage ────────────────────────────────────────────────────────────\n\n/**\n * Token accounting exactly as the bridge reported it. Lossless on purpose: a\n * side the bridge did not report stays null rather than becoming a zero, and a\n * side it DID report survives even when its partner is missing.\n */\nexport interface PrimeRawUsage {\n /**\n * Model-usage records the bridge observed. NOT a count of bridge round trips:\n * one prime turn routes several internal model calls, so a single turn\n * typically reports 3-5.\n */\n calls: number | null\n /** Prompt tokens the bridge reported; null when it reported none. */\n inputTokens: number | null\n /** Completion tokens the bridge reported; null when it reported none. */\n outputTokens: number | null\n /**\n * True when the bridge DERIVED the counts (from character lengths) because\n * the backend reported no usage of its own. Pricing derived counts produces a\n * guess about a guess, which a reader must be able to tell apart from a\n * rate-estimated cost over exact tokens.\n */\n bridgeEstimated: boolean\n}\n\nexport function emptyPrimeRawUsage(): PrimeRawUsage {\n return { calls: null, inputTokens: null, outputTokens: null, bridgeEstimated: false }\n}\n\n/** Read the bridge's OpenAI-shaped `usage` object. */\nexport function normalizePrimeUsage(raw: unknown): PrimeRawUsage {\n if (typeof raw !== 'object' || raw === null) return emptyPrimeRawUsage()\n const record = raw as Record<string, unknown>\n return {\n calls: tokenCountOrNull(record.model_requests),\n inputTokens: tokenCountOrNull(record.prompt_tokens),\n outputTokens: tokenCountOrNull(record.completion_tokens),\n bridgeEstimated: record.estimated === true,\n }\n}\n\n/**\n * Sum two turns. Each side poisons independently: two turns that both report\n * input and neither report output yield a real input total beside a null\n * output, because discarding a measured count is as wrong as inventing one.\n */\nexport function mergePrimeRawUsage(a: PrimeRawUsage, b: PrimeRawUsage): PrimeRawUsage {\n return {\n calls: sumOrNull(a.calls, b.calls),\n inputTokens: sumOrNull(a.inputTokens, b.inputTokens),\n outputTokens: sumOrNull(a.outputTokens, b.outputTokens),\n bridgeEstimated: a.bridgeEstimated || b.bridgeEstimated,\n }\n}\n\nfunction sumOrNull(a: number | null, b: number | null): number | null {\n return a !== null && b !== null ? a + b : null\n}\n\nfunction tokenCountOrNull(value: unknown): number | null {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null\n}\n\n/**\n * Bind raw prime usage to agent-eval's typed receipt.\n *\n * `RunTokenUsage.input` and `.output` are non-nullable, so a one-sided count\n * cannot round-trip through `tokens` without writing a zero nobody measured.\n * The complete-accounting field therefore stays null, the reported side is\n * carried verbatim in `partialTokens`, and its price becomes the receipt's\n * `knownCostUsd` lower bound.\n *\n * Only agent-eval calls this; consumers with no pricing table read\n * `PrimeRawUsage` directly.\n */\nexport function analystUsageReceiptFromPrimeUsage(\n usage: PrimeRawUsage,\n pricing: CustomTokenPricing,\n): AnalystUsageReceipt {\n const { calls, inputTokens, outputTokens, bridgeEstimated } = usage\n const estimatedTokens = bridgeEstimated ? { tokensEstimated: true } : {}\n if (inputTokens !== null && outputTokens !== null) {\n return {\n calls,\n tokens: { input: inputTokens, output: outputTokens },\n cost: { kind: 'estimated', usd: priceTokens(inputTokens, outputTokens, pricing) },\n ...estimatedTokens,\n }\n }\n if (inputTokens === null && outputTokens === null) {\n return { calls, tokens: null, cost: { kind: 'uncaptured', usd: null }, ...estimatedTokens }\n }\n return {\n calls,\n tokens: null,\n partialTokens: { input: inputTokens, output: outputTokens },\n cost: { kind: 'uncaptured', usd: null },\n knownCostUsd: priceTokens(inputTokens ?? 0, outputTokens ?? 0, pricing),\n ...estimatedTokens,\n }\n}\n\nfunction priceTokens(input: number, output: number, pricing: CustomTokenPricing): number {\n return (input * pricing.inputUsdPerMillion + output * pricing.outputUsdPerMillion) / 1_000_000\n}\n\n// ── Two-turn exchange ────────────────────────────────────────────────\n\n/**\n * Why an exchange ended without a readable reply. `deadline` and `aborted` are\n * separate members from `transport` on purpose: a model that ran past its\n * deadline, a caller who cancelled, and a bridge that refused the connection\n * demand three different responses, and a record that conflates them cannot be\n * acted on.\n */\nexport type PrimeFailure =\n | {\n kind: 'transport' | 'unparseable-json' | 'no-content' | 'deadline' | 'malformed-reply'\n message: string\n }\n | { kind: 'http-status'; message: string; status: number; bodySnippet: string }\n | { kind: 'aborted'; message: string; cause: unknown }\n\nexport interface PrimeRepairState {\n attempted: boolean\n /** Null when no repair turn ran, or when the repair turn never returned a reply. */\n succeeded: boolean | null\n}\n\n/** One completed bridge turn. A turn that failed produces no record. */\nexport interface PrimeTurnRecord {\n turn: 'first' | 'repair'\n usage: PrimeRawUsage\n /** The reply's `usage` object verbatim; null when the bridge sent none. */\n rawUsage: unknown\n}\n\nexport interface PrimeRejectedRow {\n index: number\n reason: string\n}\n\nexport type PrimeExchangeOutcome<TRow> =\n | {\n ok: true\n /** The reply's `answer` field; null when absent or not a string. */\n answer: string | null\n rows: TRow[]\n rejected: PrimeRejectedRow[]\n /** Rows the model reported, before decoding or the count cap. */\n reportedRows: number\n /** Valid rows dropped by `contract.maxRows`. */\n overflow: number\n usage: PrimeRawUsage\n turns: PrimeTurnRecord[]\n repair: PrimeRepairState\n reply: string\n }\n | {\n ok: false\n failure: PrimeFailure\n usage: PrimeRawUsage\n turns: PrimeTurnRecord[]\n repair: PrimeRepairState\n /** The last reply received, when one arrived — the diagnostic artifact for a malformed case. */\n reply?: string\n }\n\nexport interface PrimeExchangeOptions<TRow> {\n contract: PrimeReplyContract<TRow>\n prompt: string\n transport: PrimeBridgeTransport\n /** Full endpoint, e.g. `http://localhost:4181/v1/chat/completions`. */\n url: string\n model: string\n /** Deadline for ONE turn. Prime analyses routinely exceed five minutes. */\n timeoutMs: number\n /** Whether a structurally malformed reply gets one bounded repair turn. */\n repair: boolean\n signal?: AbortSignal\n}\n\n/**\n * Run the protocol: one call, one bounded repair turn on a structurally\n * malformed reply, then decode. Zero valid rows from a well-formed reply is an\n * honest null, not a failure.\n */\nexport async function runPrimeExchange<TRow>(\n options: PrimeExchangeOptions<TRow>,\n): Promise<PrimeExchangeOutcome<TRow>> {\n const { contract } = options\n const turns: PrimeTurnRecord[] = []\n const repair: PrimeRepairState = { attempted: false, succeeded: null }\n\n const first = await callPrimeTurn(options, options.prompt)\n if (!first.ok) {\n return { ok: false, failure: first.failure, usage: mergeTurns(turns), turns, repair }\n }\n turns.push({ turn: 'first', usage: first.usage, rawUsage: first.rawUsage })\n\n let reply = first.content\n let parsed = extractPrimeJsonObject(reply)\n let defect = primeReplyDefect(parsed, contract.rowsField)\n\n if (defect !== null && options.repair) {\n repair.attempted = true\n const second = await callPrimeTurn(\n options,\n buildPrimeRepairPrompt({\n defect,\n previousReply: reply,\n repairContractLines: contract.repairContractLines,\n }),\n )\n if (!second.ok) {\n return { ok: false, failure: second.failure, usage: mergeTurns(turns), turns, repair, reply }\n }\n turns.push({ turn: 'repair', usage: second.usage, rawUsage: second.rawUsage })\n reply = second.content\n parsed = extractPrimeJsonObject(reply)\n defect = primeReplyDefect(parsed, contract.rowsField)\n repair.succeeded = defect === null\n }\n\n const usage = mergeTurns(turns)\n if (defect !== null) {\n return {\n ok: false,\n failure: {\n kind: 'malformed-reply',\n message: `${defect} in prime reply${repair.attempted ? ' even after the bounded repair turn' : ''}`,\n },\n usage,\n turns,\n repair,\n reply,\n }\n }\n\n const rawRows = parsed![contract.rowsField] as unknown[]\n const { rows, rejected, overflow } = decodeContractRows(contract, rawRows)\n const answer = parsed!.answer\n return {\n ok: true,\n answer: typeof answer === 'string' ? answer : null,\n rows,\n rejected,\n reportedRows: rawRows.length,\n overflow,\n usage,\n turns,\n repair,\n reply,\n }\n}\n\ntype PrimeTurnOutcome =\n | { ok: true; content: string; usage: PrimeRawUsage; rawUsage: unknown }\n | { ok: false; failure: PrimeFailure }\n\nasync function callPrimeTurn<TRow>(\n options: PrimeExchangeOptions<TRow>,\n content: string,\n): Promise<PrimeTurnOutcome> {\n const { transport, url, model, timeoutMs, signal } = options\n const controller = new AbortController()\n const forwardAbort = () => controller.abort(signal?.reason)\n if (signal?.aborted) controller.abort(signal.reason)\n else signal?.addEventListener('abort', forwardAbort, { once: true })\n const deadline = setTimeout(() => controller.abort(), timeoutMs)\n let result: PrimeBridgeTransportResult\n try {\n result = await transport({\n url,\n body: { model, messages: [{ role: 'user', content }] },\n signal: controller.signal,\n })\n } catch (error) {\n if (signal?.aborted) {\n return {\n ok: false,\n failure: {\n kind: 'aborted',\n message: 'prime exchange cancelled by the caller',\n cause: error,\n },\n }\n }\n if (controller.signal.aborted) {\n return {\n ok: false,\n failure: { kind: 'deadline', message: `bridge call exceeded ${timeoutMs}ms` },\n }\n }\n return {\n ok: false,\n failure: {\n kind: 'transport',\n message: `bridge transport failure: ${error instanceof Error ? error.message : String(error)}`,\n },\n }\n } finally {\n clearTimeout(deadline)\n signal?.removeEventListener('abort', forwardAbort)\n }\n\n if (result.status !== 200) {\n const bodySnippet = result.text.slice(0, 500)\n return {\n ok: false,\n failure: {\n kind: 'http-status',\n message: `bridge HTTP ${result.status}: ${bodySnippet}`,\n status: result.status,\n bodySnippet,\n },\n }\n }\n let response: unknown\n try {\n response = JSON.parse(result.text)\n } catch {\n return {\n ok: false,\n failure: {\n kind: 'unparseable-json',\n message: `bridge returned unparseable JSON (${result.text.length} bytes)`,\n },\n }\n }\n const replyContent = primeReplyContent(response)\n if (replyContent === null) {\n return {\n ok: false,\n failure: { kind: 'no-content', message: 'bridge reply carries no message content' },\n }\n }\n const rawUsage = primeReplyUsage(response)\n return { ok: true, content: replyContent, usage: normalizePrimeUsage(rawUsage), rawUsage }\n}\n\n/**\n * Fold from the FIRST turn, never from an empty receipt: an all-null identity\n * would poison every side it merged with and erase counts the bridge reported.\n */\nfunction mergeTurns(turns: readonly PrimeTurnRecord[]): PrimeRawUsage {\n if (turns.length === 0) return emptyPrimeRawUsage()\n return turns\n .slice(1)\n .reduce<PrimeRawUsage>((total, turn) => mergePrimeRawUsage(total, turn.usage), turns[0]!.usage)\n}\n\nfunction primeReplyContent(response: unknown): string | null {\n if (typeof response !== 'object' || response === null) return null\n const choices = (response as { choices?: unknown }).choices\n if (!Array.isArray(choices) || choices.length === 0) return null\n const message = (choices[0] as { message?: unknown })?.message\n if (typeof message !== 'object' || message === null) return null\n const content = (message as { content?: unknown }).content\n return typeof content === 'string' && content.length > 0 ? content : null\n}\n\nfunction primeReplyUsage(response: unknown): unknown {\n if (typeof response !== 'object' || response === null) return null\n return (response as { usage?: unknown }).usage ?? null\n}\n\n// ── Trajectory projection ────────────────────────────────────────────\n\n/**\n * Where the inlined trajectory comes from. The protocol needs only two moves —\n * fetch it all, or fetch a reduced version — so no store, artifact path, or\n * span type enters the shared signature.\n */\nexport interface PrimeProjectionSource<TItem> {\n /** The full projection, or null when the source declares itself oversized. */\n full(): Promise<readonly TItem[] | null>\n /** A reduced projection of the same material. */\n capped(): Promise<readonly TItem[]>\n /** How `capped` reduces, named for the failure message, e.g. `per-attribute cap 1200`. */\n cappedDescription: string\n}\n\nexport interface PrimeProjectionDelivery {\n mode: 'inline-json'\n fetch: 'full' | 'capped'\n renderedChars: number\n}\n\nexport type PrimeProjectionOutcome<TItem> =\n | {\n ok: true\n items: readonly TItem[]\n rendered: string\n delivery: PrimeProjectionDelivery\n }\n | { ok: false; reason: string; renderedChars: number }\n\n/**\n * Render, measure, fall back to the capped projection, re-measure, fail loud.\n *\n * Inline is the only delivery prime has, so an oversized trajectory is a\n * refusal rather than a silent truncation: dropping spans would understate the\n * trajectory and the analyst would answer a question about a different run.\n */\nexport async function projectPrimeTrajectory<TItem>(\n source: PrimeProjectionSource<TItem>,\n limits: { maxInlineChars: number },\n): Promise<PrimeProjectionOutcome<TItem>> {\n let fetch: PrimeProjectionDelivery['fetch'] = 'full'\n let items = await source.full()\n if (items === null) {\n fetch = 'capped'\n items = await source.capped()\n }\n let rendered = JSON.stringify(items)\n if (rendered.length > limits.maxInlineChars && fetch === 'full') {\n fetch = 'capped'\n items = await source.capped()\n rendered = JSON.stringify(items)\n }\n if (rendered.length > limits.maxInlineChars) {\n return {\n ok: false,\n reason: `trajectory renders to ${rendered.length} chars even at ${source.cappedDescription}; inline delivery impossible`,\n renderedChars: rendered.length,\n }\n }\n return {\n ok: true,\n items,\n rendered,\n delivery: { mode: 'inline-json', fetch, renderedChars: rendered.length },\n }\n}\n\n// ── Protocol identity ────────────────────────────────────────────────\n\nexport interface PrimeProtocolIdentity {\n question: string\n taskDefinition?: string\n contractLines: readonly string[]\n repairContractLines: readonly string[]\n /** Numeric limits the contract states, e.g. row and width caps. */\n limits: Readonly<Record<string, number>>\n}\n\n/**\n * Digest of everything a consumer can send to the bridge under the prime\n * protocol, recorded per observation so a prime result names the exact contract\n * that produced it.\n *\n * Computed over the ACTUALLY composed contract, so two consumers that both\n * stamp `analyst_id: 'prime'` while asking materially different questions get\n * different digests by construction. That is what makes 'prime' a reproducible\n * claim rather than a label.\n */\nexport function primeProtocolSha256(identity: PrimeProtocolIdentity): string {\n return createHash('sha256')\n .update(\n JSON.stringify({\n kind: 'prime-analyst-protocol',\n question: identity.question,\n taskPrompt: identity.taskDefinition ?? null,\n outputContract: identity.contractLines,\n repairContract: buildPrimeRepairPrompt({\n defect: '<defect>',\n previousReply: '<previous-reply>',\n repairContractLines: identity.repairContractLines,\n }),\n limits: identity.limits,\n }),\n )\n .digest('hex')\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { m as AnalystUsageReceipt } from "./types-
|
|
1
|
+
import { p as CustomTokenPricing } from "./cost-ledger-Jk62OBfF.js";
|
|
2
|
+
import { m as AnalystUsageReceipt } from "./types-C1tnkEgM.js";
|
|
3
3
|
import { t as PrimeBridgeTransport } from "./prime-bridge-transport-6feEglLf.js";
|
|
4
4
|
//#region src/analyst/reply-contract.d.ts
|
|
5
5
|
/**
|
|
@@ -328,4 +328,4 @@ interface PrimeProtocolIdentity {
|
|
|
328
328
|
declare function primeProtocolSha256(identity: PrimeProtocolIdentity): string;
|
|
329
329
|
//#endregion
|
|
330
330
|
export { ReplyRowDecoded as A, primeProtocolSha256 as C, DecodedReply as D, runPrimeExchange as E, decodeReplyRows as M, ReplyContract as O, normalizePrimeUsage as S, projectPrimeTrajectory as T, buildPrimePrompt as _, PrimeProjectionOutcome as a, extractPrimeJsonObject as b, PrimeProtocolIdentity as c, PrimeRepairPromptSpec as d, PrimeRepairState as f, analystUsageReceiptFromPrimeUsage as g, PrimeTurnRecord as h, PrimeProjectionDelivery as i, ReplyRowRejection as j, ReplyEnvelope as k, PrimeRawUsage as l, PrimeRowDecoded as m, PrimeExchangeOutcome as n, PrimeProjectionSource as o, PrimeReplyContract as p, PrimeFailure as r, PrimePromptSpec as s, PrimeExchangeOptions as t, PrimeRejectedRow as u, buildPrimeRepairPrompt as v, primeReplyDefect as w, mergePrimeRawUsage as x, emptyPrimeRawUsage as y };
|
|
331
|
-
//# sourceMappingURL=prime-protocol-
|
|
331
|
+
//# sourceMappingURL=prime-protocol-HiB9HX7E.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prime-protocol-
|
|
1
|
+
{"version":3,"file":"prime-protocol-HiB9HX7E.d.ts","names":[],"sources":["../src/analyst/reply-contract.ts","../src/analyst/prime-protocol.ts"],"mappings":";;;;;;;;;;;;;;KAaY,gBAAgB;EAAU;EAAU,KAAK;;EAAW;EAAW;;;UAG1D;EACf;;EAEA,QAAQ;;UAGO,cAAc;;EAE7B;;EAEA;;;;;EAKA;;;;;;EAMA,UAAU,cAAc,gBAAgB,gBAAgB;;;;;;EAMxD;;;;;;EAMA,eAAe,iBAAiB;;;;;;EAMhC;;;;;EAKA;;;UAIe;EACf;EACA;;UAGe,aAAa;EAC5B,MAAM;;EAEN,QAAQ;EACR,UAAU;;EAEV;;EAEA;;;;;;iBAmCc,gBAAgB,MAC9B,UAAU,cAAc,OACxB,iBACC,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCjFJ,gBAAgB,QAAQ,gBAAgB;KAExC,mBAAmB,QAAQ,cAAc;UAIpC;EACf;;EAEA;EACA;;EAEA;EACA;;EAEA;;iBAGc,iBAAiB,MAAM;UAatB;EACf;EACA;EACA;;;iBAIc,uBAAuB,MAAM;;;;;;;;;;iBAuB7B,uBAAuB,eAAe;;iBAkBtC,iBACd,QAAQ,gCACR;;;;;;UAyBe;;;;;;EAMf;;EAEA;;EAEA;;;;;;;EAOA;;iBAGc,sBAAsB;;iBAKtB,oBAAoB,eAAe;;;;;;iBAgBnC,mBAAmB,GAAG,eAAe,GAAG,gBAAgB;;;;;;;;;;;;;iBA6BxD,kCACd,OAAO,eACP,SAAS,qBACR;;;;;;;;KAqCS;EAEN;EACA;;EAEA;EAAqB;EAAiB;EAAgB;;EACtD;EAAiB;EAAiB;;UAEvB;EACf;;EAEA;;;UAIe;EACf;EACA,OAAO;;EAEP;;UAGe;EACf;EACA;;KAGU,qBAAqB;EAE3B;;EAEA;EACA,MAAM;EACN,UAAU;;EAEV;;EAEA;EACA,OAAO;EACP,OAAO;EACP,QAAQ;EACR;;EAGA;EACA,SAAS;EACT,OAAO;EACP,OAAO;EACP,QAAQ;;EAER;;UAGW,qBAAqB;EACpC,UAAU,mBAAmB;EAC7B;EACA,WAAW;;EAEX;EACA;;EAEA;;EAEA;EACA,SAAS;;;;;;;iBAQW,iBAAiB,MACrC,SAAS,qBAAqB,QAC7B,QAAQ,qBAAqB;;;;;;UAyLf,sBAAsB;;EAErC,QAAQ,iBAAiB;;EAEzB,UAAU,iBAAiB;;EAE3B;;UAGe;EACf;EACA;EACA;;KAGU,uBAAuB;EAE7B;EACA,gBAAgB;EAChB;EACA,UAAU;;EAEV;EAAW;EAAgB;;;;;;;;;iBASX,uBAAuB,OAC3C,QAAQ,sBAAsB,QAC9B;EAAU;IACT,QAAQ,uBAAuB;UA8BjB;EACf;EACA;EACA;EACA;;EAEA,QAAQ,SAAS;;;;;;;;;;;;iBAaH,oBAAoB,UAAU"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { s as ValidationError } from "./errors-
|
|
2
|
-
import { r as canonicalString } from "./canonical-
|
|
3
|
-
import { n as JudgeParseError } from "./llm-judge-
|
|
4
|
-
import {
|
|
5
|
-
import { w as recoverTruncatedJson } from "./campaign-evidence-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { s as ValidationError } from "./errors-DVZiqS7K.js";
|
|
2
|
+
import { r as canonicalString } from "./canonical-B2RqLofv.js";
|
|
3
|
+
import { n as JudgeParseError } from "./llm-judge-CG12SQJq.js";
|
|
4
|
+
import { t as CostLedger } from "./cost-ledger-BP8V4kUQ.js";
|
|
5
|
+
import { w as recoverTruncatedJson } from "./campaign-evidence-Clrn4hBV.js";
|
|
6
|
+
import { t as certificationEvidenceDigest } from "./verdict-Dl0tiT1X.js";
|
|
7
|
+
import { a as maximumChargeForLlmRequest, c as ModelSubstitutionError, d as assertServedModel, i as costReceiptFromLlmError, r as costReceiptFromLlm } from "./llm-client-CyBAoYiX.js";
|
|
8
8
|
import { createHash, randomUUID } from "node:crypto";
|
|
9
9
|
import { harnessSupportsModel } from "@tangle-network/agent-interface";
|
|
10
10
|
//#region src/agent-profile.ts
|
|
@@ -591,4 +591,4 @@ function extractProducedState(events) {
|
|
|
591
591
|
//#endregion
|
|
592
592
|
export { CODING_HARNESSES as a, agentProfileId as c, harnessAxisOf as d, verifyCompletion as i, agentProfileModelId as l, completionVerdict as n, HARNESS_NATIVE_MODEL as o, createLlmCorrectnessChecker as r, agentProfileHash as s, extractProducedState as t, expandProfileAxes as u };
|
|
593
593
|
|
|
594
|
-
//# sourceMappingURL=produced-state-
|
|
594
|
+
//# sourceMappingURL=produced-state-BsDmnwxc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"produced-state-ZCtDBxAE.js","names":[],"sources":["../src/agent-profile.ts","../src/completion-verifier.ts","../src/produced-state.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport { type HarnessType, harnessSupportsModel } from '@tangle-network/agent-interface'\nimport { ValidationError } from './errors'\nimport { canonicalString } from './ledger-core/canonical'\n\nexport type { AgentProfile, HarnessType } from '@tangle-network/agent-interface'\n\n/**\n * The agentic coding harnesses an eval sweeps by default — the ones we care about\n * ranking. This is the SINGLE source of that list; consumers import it instead of\n * re-declaring their own (a re-declared list is how the fleet drifts). Pass an\n * explicit `harnesses` (e.g. `harnessTypeSchema.options` for literally every known\n * harness) to widen beyond these.\n */\nexport const CODING_HARNESSES: readonly HarnessType[] = [\n 'opencode',\n 'claude-code',\n 'codex',\n 'kimi-code',\n]\n\nexport interface ProfileAxisSpec {\n /** The domain profile to sweep. Its prompt/tools/skills are held fixed; only the\n * harness and model vary. `model.default` is the fallback model. */\n base: AgentProfile\n /** Harnesses to cross. Default: {@link CODING_HARNESSES}. */\n harnesses?: readonly HarnessType[]\n /** Models to cross. Default: `[base.model.default]` — one model, i.e. today's\n * single-model behaviour, so omitting this never changes an existing run. */\n models?: readonly string[]\n /** Force every (harness, model) pair verbatim, even ones the harness can't run —\n * for deliberately testing failure modes. Default (false): SNAP instead — a\n * vendor-locked harness runs only the swept models in its family, or its native\n * default when it supports none, so no harness is dropped and none gets a\n * guaranteed-failing foreign-model cell. */\n keepIncompatible?: boolean\n}\n\n/** Model sentinel for a vendor-locked harness that supports none of the swept models:\n * it carries no provider prefix, so `harnessSupportsModel` accepts it and the harness\n * resolves it to its own native default model at runtime (e.g. kimi-code → its Kimi\n * model). Lets `expandProfileAxes` snap-instead-of-drop without a per-harness flagship\n * table that would rot as router catalogs change. */\nexport const HARNESS_NATIVE_MODEL = 'default'\n\n/**\n * Expand a base profile across the harness × model matrix into the `AgentProfile[]`\n * that `runProfileMatrix` / `selfImprove` score — the ONE place \"which harnesses ×\n * which models do we evaluate\" lives, so no product hand-rolls its own harness list\n * or column→profile mapping (the pattern that let those copies drift and silently\n * break the harness pivot).\n *\n * Each cell clones `base`, sets the canonical top-level `harness` and `model.default`,\n * and stamps `metadata.harness` + `metadata.harnessModel` for matrix grouping. Both\n * metadata fields are hash-bearing, so every cell gets a distinct `agentProfileId` row\n * and results join back by harness/model via {@link harnessAxisOf} with no\n * hand-recomputed key. A vendor-locked harness snaps to its family's swept models — or\n * its native default ({@link HARNESS_NATIVE_MODEL}) when it supports none — so every\n * requested harness runs; `keepIncompatible` forces every pair verbatim.\n *\n * Omit `harnesses`/`models` to sweep the full default set — the \"turn it on for\n * everything we care about\" switch, identical in shape whether one harness or all.\n */\nexport function expandProfileAxes(spec: ProfileAxisSpec): AgentProfile[] {\n const harnesses = spec.harnesses ?? CODING_HARNESSES\n if (harnesses.length === 0) throw new ValidationError('expandProfileAxes: no harnesses to sweep')\n const baseModel = spec.base.model?.default\n const models = spec.models ?? (baseModel ? [baseModel] : [])\n if (models.length === 0) {\n throw new ValidationError(\n 'expandProfileAxes: no models to sweep — base profile has no model.default and none were supplied',\n )\n }\n const out: AgentProfile[] = []\n const seen = new Set<string>()\n for (const harness of harnesses) {\n // A universal (router-backed) harness — opencode/pi/claudish — runs every swept\n // model. A vendor-locked harness — codex/claude-code/kimi-code — runs only the\n // swept models in its own family; when it supports NONE of them it snaps to its\n // native default (the `HARNESS_NATIVE_MODEL` sentinel it resolves at runtime)\n // rather than being dropped, so every requested harness still appears in the\n // sweep on a model it can actually run — e.g. sweeping `deepseek/x` puts opencode\n // on deepseek and kimi-code on its own Kimi model, a real head-to-head.\n // `keepIncompatible` forces every (harness, model) pair verbatim (failure-mode runs).\n const supported = spec.keepIncompatible\n ? models\n : models.filter((model) => harnessSupportsModel(harness, model))\n const effective = supported.length > 0 ? supported : [HARNESS_NATIVE_MODEL]\n for (const model of effective) {\n const profile: AgentProfile = {\n ...spec.base,\n harness,\n name: `${spec.base.name ?? 'agent'}/${harness}/${model}`,\n model: { ...spec.base.model, default: model },\n metadata: { ...(spec.base.metadata ?? {}), harness, harnessModel: model },\n }\n const id = agentProfileId(profile)\n if (seen.has(id)) continue\n seen.add(id)\n out.push(profile)\n }\n }\n if (out.length === 0) {\n // Unreachable in normal use — snapping guarantees ≥1 cell per harness — but keep a\n // fail-closed guard so a future refactor can't silently produce an empty sweep.\n throw new ValidationError(\n `expandProfileAxes: produced no profiles (harnesses=[${harnesses.join(', ')}], models=[${models.join(', ')}]).`,\n )\n }\n return out\n}\n\n/**\n * Read the (harness, model) a matrix cell ran under, off a profile or a result row's\n * profile — the join-back for a `byHarness` pivot. Returns undefined when the profile\n * wasn't produced by {@link expandProfileAxes}. Callers group `result.byProfile` by\n * this instead of recomputing an id (recomputing the wrong key is what broke the pivot\n * in the hand-rolled copies).\n */\nexport function harnessAxisOf(\n profile: Pick<AgentProfile, 'metadata'>,\n): { harness: HarnessType; model: string } | undefined {\n const m = profile.metadata as Record<string, unknown> | undefined\n const harness = m?.harness\n const model = m?.harnessModel\n if (typeof harness === 'string' && typeof model === 'string') {\n return { harness: harness as HarnessType, model }\n }\n return undefined\n}\n\n/**\n * Collision-resistant, path-safe, human-readable profile id for eval artifacts.\n * Scorecard joins still use `agentProfileHash`; this id is for run ids, matrix\n * keys, and directory names where two profiles must not collapse onto one row.\n * The suffix is the first 64 bits of the behaviour hash, enough for ordinary\n * eval matrices while keeping filenames readable.\n */\nexport function agentProfileId(profile: AgentProfile): string {\n const label = pathSafeProfileLabel(agentProfileDisplayLabel(profile)) ?? 'profile'\n return `${label}-${agentProfileHash(profile).slice(0, 16)}`\n}\n\n/**\n * Model snapshot used for `RunRecord.model`. Eval surfaces require a concrete\n * model id because run records reject bare/missing model aliases.\n */\nexport function agentProfileModelId(profile: AgentProfile): string {\n const model = profile.model?.default?.trim()\n if (!model) {\n const label = agentProfileDisplayLabel(profile) ?? 'unnamed profile'\n throw new ValidationError(\n `AgentProfile \"${label}\" has no model.default — cannot record eval run`,\n )\n }\n return model\n}\n\nfunction agentProfileDisplayLabel(profile: AgentProfile): string | undefined {\n return profile.name?.trim() || profile.version?.trim() || undefined\n}\n\nfunction pathSafeProfileLabel(label: string | undefined): string | undefined {\n const safe = label\n ?.trim()\n .replace(/[^A-Za-z0-9._-]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n return safe || undefined\n}\n\nfunction compact<T extends Record<string, unknown>>(input: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(input)) {\n if (value !== undefined) out[key] = value\n }\n return out as Partial<T>\n}\n\n/**\n * Deterministic behaviour identity for the canonical\n * `@tangle-network/agent-interface` AgentProfile.\n *\n * `name` and `description` are labels and do not affect the hash. Profile\n * `version`, prompt, model hints, tools, resources, hooks, modes, permissions,\n * and extensions do affect the hash. Resource array order is hash-bearing\n * because mount order can change agent behaviour. Undefined fields are treated\n * as absent; explicit `null` fields remain hash-bearing.\n */\nexport function agentProfileHash(profile: AgentProfile): string {\n const model = agentProfileModelId(profile)\n const behaviour = compact({\n ...profile,\n name: undefined,\n description: undefined,\n tags: profile.tags ? [...profile.tags].sort() : undefined,\n model: compact({ ...profile.model, default: model }),\n })\n return createHash('sha256').update(canonicalString(behaviour)).digest('hex')\n}\n","/**\n * Completion verifier — the task-completion oracle.\n *\n * Answers the only eval question that is not a proxy: did the agent actually\n * COMPLETE the task — produce every required deliverable, persisted and\n * correct — rather than describe what should be done. A fluent transcript\n * that never produces the artifact scores zero here.\n *\n * Per requirement, a two-stage check:\n * 1. Structural — a produced item (vault artifact / approved proposal /\n * tool call) of the right kind is matched against the requirement and\n * carries non-empty content. Deterministic; no LLM.\n * 2. Correctness — only if structurally present AND the matched item\n * carries content, one targeted check decides whether that item\n * actually fulfils the requirement. A hallucinated artifact fails here;\n * an absent one already failed stage 1.\n *\n * `completionRate` is satisfied / MEASURABLE requirements (unmeasured rows —\n * checker failures — are excluded from the denominator, never scored as\n * zeros). Quality dimensions are meaningless on an incomplete task — callers\n * gate on `fullyComplete` / `completionRate` before scoring quality.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type { ChatClient, ChatRequest } from './analyst/chat-client'\nimport type { Artifact } from './artifact-validator'\nimport { CostLedger, type CostLedgerHandle } from './cost-ledger'\nimport { assertServedModel, ModelSubstitutionError } from './integrity/served-model'\nimport { recoverTruncatedJson } from './json-recovery'\nimport { JudgeParseError } from './judges'\nimport {\n costReceiptFromLlm,\n costReceiptFromLlmError,\n maximumChargeForLlmRequest,\n} from './llm-client'\nimport type { RawProviderEvent, RawProviderSink } from './trace/raw-provider-sink'\nimport {\n certificationEvidenceDigest,\n type DefaultVerdict,\n type VerdictCertification,\n} from './verdict'\nimport type { CheckerIdentity, VerificationStrategySource } from './verification-strategy'\n\n/** What kind of produced state can satisfy a requirement structurally. */\nexport type SatisfiedBy = 'artifact' | 'proposal' | 'tool-call' | 'any'\n\nexport interface CompletionRequirement {\n /** Stable id from the task gold (e.g. a persona's `expected_requirements[].req_id`). */\n reqId: string\n /** Human-readable description of the required deliverable. */\n title: string\n /** Optional kind/category hint, matched against a produced item's kind. */\n category?: string\n /** What produced state satisfies this requirement. Defaults to 'any'. */\n satisfiedBy?: SatisfiedBy\n}\n\nexport interface TaskGold {\n taskId: string\n requirements: CompletionRequirement[]\n}\n\nexport interface ProducedProposal {\n id: string\n title: string\n status: 'pending' | 'approved' | 'rejected'\n /** Optional persisted body — when present, enables a correctness check. */\n content?: string\n}\n\n/** Everything observable about what a run actually produced. */\nexport interface ProducedState {\n /** Persisted vault artifacts. Reuses the shared `Artifact` shape. */\n artifacts: Artifact[]\n /** Proposals / filings the agent created. */\n proposals: ProducedProposal[]\n /** Names of tools the agent invoked. */\n toolCalls: string[]\n}\n\nexport interface RequirementCheck {\n reqId: string\n title: string\n /** A produced item of the right kind matched the requirement, non-empty. */\n structurallyPresent: boolean\n /**\n * Whether the matched item actually fulfils the requirement. `null` when\n * not structurally present, when the matched item carries no content\n * to assess, or when the correctness check itself failed (`unmeasured`).\n */\n correct: boolean | null\n /** structurallyPresent && !unmeasured && correct !== false. */\n satisfied: boolean\n /**\n * Set when the correctness check itself errored (LLM call failure or an\n * unparseable response after retry). The requirement's fulfilment is\n * UNKNOWN — `correct` stays null, `satisfied` is false, and\n * `completionVerdict` excludes the row from `completionRate`'s\n * denominator. Never folded into a zero: a synthetic zero is\n * indistinguishable from a real failure (see `JudgeParseError`).\n */\n unmeasured?: true\n /** Why the correctness check could not be measured (present iff `unmeasured`). */\n unmeasuredReason?: string\n /** Human-readable evidence for the verdict. */\n evidence: string[]\n}\n\n/** Extends the substrate verdict spine: `valid` = `fullyComplete` and\n * `score` = `completionRate` — derived in `completionVerdict()`, the one\n * place those equalities hold by construction. */\nexport interface CompletionVerdict extends DefaultVerdict {\n taskId: string\n requirements: RequirementCheck[]\n /** satisfied / MEASURABLE requirements (unmeasured rows leave the denominator). */\n completionRate: number\n /** Every measurable requirement satisfied (false when anything is unmeasured). */\n fullyComplete: boolean\n /** Requirements whose correctness check errored — reported, never scored as zero. */\n unmeasuredCount: number\n}\n\n/**\n * Construct a `CompletionVerdict` from the per-requirement checks, deriving\n * `completionRate` / `fullyComplete` and the spine fields (`valid` =\n * `fullyComplete`, `score` = `completionRate`) in one place. Throws on zero\n * requirements — a verdict over nothing is a misconfiguration, mirroring\n * `verifyCompletion`'s gold-spec guard.\n */\nexport function completionVerdict(input: {\n taskId: string\n requirements: RequirementCheck[]\n /** What certified the correctness stage, when anything did. Omitted =\n * an uncertified verdict — the honest default for a bare checker. */\n certification?: VerdictCertification\n}): CompletionVerdict {\n if (input.requirements.length === 0) {\n throw new Error(\n `completionVerdict: task '${input.taskId}' has no requirement checks — nothing to derive a verdict from`,\n )\n }\n const measurable = input.requirements.filter((r) => !r.unmeasured)\n const unmeasuredCount = input.requirements.length - measurable.length\n if (measurable.length === 0) {\n // Every check errored: this is an infrastructure failure, not a scored\n // run. A 0-rate verdict here would be a fabricated measurement.\n throw new Error(\n `completionVerdict: task '${input.taskId}' has no measurable requirements — all ${input.requirements.length} correctness checks failed (${input.requirements[0]?.unmeasuredReason ?? 'unknown reason'})`,\n )\n }\n const satisfiedCount = measurable.filter((r) => r.satisfied).length\n const completionRate = satisfiedCount / measurable.length\n // A run with unmeasured rows can still report a rate over what WAS\n // measured, but must not claim full completion.\n const fullyComplete = unmeasuredCount === 0 && satisfiedCount === measurable.length\n return {\n taskId: input.taskId,\n requirements: input.requirements,\n completionRate,\n fullyComplete,\n unmeasuredCount,\n valid: fullyComplete,\n score: completionRate,\n ...(input.certification === undefined ? {} : { certification: input.certification }),\n }\n}\n\n/**\n * What a correctness checker declares about itself so the completion\n * verdict can carry a certification: which strategy member it discharges,\n * its exact identity, and the steps its answers rest on unverified.\n */\nexport interface CorrectnessCheckerAttestation {\n strategy: VerificationStrategySource\n checker: CheckerIdentity\n assumptions: string[]\n}\n\n/**\n * Decides whether a produced item's content actually fulfils a requirement.\n * Injected so the structural verifier stays pure and unit-testable; the\n * production implementation is `createLlmCorrectnessChecker`.\n *\n * `attestation` is optional metadata on the function value: a checker that\n * carries one yields certified completion verdicts; a bare function yields\n * the same verdict uncertified. A plain arrow function remains a valid\n * checker.\n */\nexport interface CorrectnessChecker {\n (\n requirement: CompletionRequirement,\n content: string,\n ): Promise<{ correct: boolean; reason: string }>\n attestation?: CorrectnessCheckerAttestation\n}\n\nconst STOPWORDS = new Set([\n 'the',\n 'a',\n 'an',\n 'of',\n 'for',\n 'and',\n 'or',\n 'to',\n 'in',\n 'on',\n 'with',\n 'by',\n])\n\n// Deliverable-FORM vocabulary — words that name the SHAPE of an output, not its\n// domain content. A correct \"swap-comparison view persisted as a ui/** artifact\"\n// is an OpenUI JSON whose body says nothing about \"artifact\" / \"persisted\" /\n// \"view\"; the discriminative tokens are the domain nouns (swap, comparison).\n// Stripped from the REQUIREMENT side of structural recall so a deliverable is\n// matched on what it IS about, not on the boilerplate describing its form. The\n// correctness checker strips the same class via TITLE_STOPWORDS. Anti-game holds:\n// the distinctive domain tokens remain, so an off-topic item still fails.\nconst REQUIREMENT_FORM_STOPWORDS = new Set([\n 'generated',\n 'generate',\n 'view',\n 'render',\n 'rendered',\n 'persisted',\n 'persist',\n 'artifact',\n 'file',\n 'document',\n 'note',\n 'proposal',\n 'deliverable',\n 'output',\n 'created',\n 'create',\n 'produce',\n 'produced',\n 'flag',\n])\n\nconst MATCH_THRESHOLD = 0.5\nconst MIN_CONTENT_CHARS = 50\n\nfunction tokens(s: string, extraStop?: Set<string>): Set<string> {\n return new Set(\n s\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 1 && !STOPWORDS.has(t) && !extraStop?.has(t)),\n )\n}\n\n/**\n * Recall of the requirement's tokens within a candidate's identifying text.\n * Recall, not Jaccard — a candidate's path/id legitimately carries extra\n * tokens the requirement does not name. The requirement side drops\n * deliverable-FORM vocabulary so recall keys on the distinctive domain tokens.\n */\nfunction tokenRecall(requirementText: string, candidateText: string): number {\n const req = tokens(requirementText, REQUIREMENT_FORM_STOPWORDS)\n if (req.size === 0) return 0\n const cand = tokens(candidateText)\n let hit = 0\n for (const t of req) if (cand.has(t)) hit++\n return hit / req.size\n}\n\ninterface Candidate {\n reqIndex: number\n /** Unique key for a produced item — each item satisfies at most one requirement. */\n itemKey: string\n score: number\n evidence: string\n /** Content to correctness-check, or null when the matched item has none. */\n content: string | null\n}\n\nfunction artifactCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n artifacts: Artifact[],\n): Candidate[] {\n const reqText = `${req.title} ${req.category ?? ''}`\n const out: Candidate[] = []\n artifacts.forEach((a, i) => {\n if ((a.content ?? '').trim().length < MIN_CONTENT_CHARS) return\n // Match against the artifact CONTENT too, not just its path + kind — a\n // generated view / note whose path is generic still satisfies a requirement\n // when its body covers it (e.g. an OpenUI comparison grounded in the on-file\n // figures). Bounded slice keeps the recall text cheap; MATCH_THRESHOLD holds.\n let score = tokenRecall(\n reqText,\n `${a.path ?? ''} ${a.kind} ${(a.content ?? '').slice(0, 4000)}`,\n )\n if (req.category && a.kind && req.category.toLowerCase() === a.kind.toLowerCase()) {\n score = Math.max(score, 1)\n }\n if (score < MATCH_THRESHOLD) return\n out.push({\n reqIndex,\n itemKey: `artifact:${i}`,\n score,\n evidence: `artifact '${a.path ?? a.kind}' matched (token recall ${score.toFixed(2)})`,\n content: a.content ?? null,\n })\n })\n return out\n}\n\nfunction proposalCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n proposals: ProducedProposal[],\n): Candidate[] {\n const reqText = `${req.title} ${req.category ?? ''}`\n const out: Candidate[] = []\n for (const p of proposals) {\n // Pending or rejected work is not a completed deliverable.\n if (p.status !== 'approved') continue\n // A proposal needs an assessable BODY to be a deliverable. A bare title is\n // not completion: correctness cannot be judged on it, so a title-only match\n // would auto-pass the oracle (structurallyPresent && correct===null →\n // satisfied) with no verifiable content. Tool calls are the only\n // legitimately content-less deliverable (`toolCallCandidates`).\n const body = (p.content ?? '').trim()\n if (body.length < MIN_CONTENT_CHARS) continue\n // Match against the body as well as the (often short) title — a refusal /\n // flag / analysis proposal whose title is a label still satisfies a\n // descriptively-worded requirement when its content covers it. MATCH_THRESHOLD\n // + the requirement's distinctive tokens keep an off-topic proposal out;\n // correctness (a SEMANTIC checker, NOT this lexical pass) then judges\n // polarity/fulfilment, so a negation that merely contains the tokens fails.\n // Structural and correctness must use different evidence or the two-stage\n // check collapses to one lexical gate.\n const score = tokenRecall(reqText, `${p.title} ${body}`)\n if (score < MATCH_THRESHOLD) continue\n out.push({\n reqIndex,\n itemKey: `proposal:${p.id}`,\n score,\n evidence: `approved proposal '${p.title}' matched (token recall ${score.toFixed(2)})`,\n content: body,\n })\n }\n return out\n}\n\nfunction toolCallCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n toolCalls: string[],\n): Candidate[] {\n const out: Candidate[] = []\n toolCalls.forEach((name, i) => {\n const score = tokenRecall(req.title, name)\n if (score < MATCH_THRESHOLD) return\n out.push({\n reqIndex,\n itemKey: `tool:${i}`,\n score,\n evidence: `tool call '${name}' matched (token recall ${score.toFixed(2)})`,\n content: null,\n })\n })\n return out\n}\n\n/**\n * Verify whether a run completed the task. `checkCorrectness` is injected —\n * `createLlmCorrectnessChecker` for production, a deterministic stub in tests.\n *\n * Throws on a gold spec with no requirements: an eval task that requires\n * nothing is a misconfiguration, not a vacuously-complete task.\n */\nexport async function verifyCompletion(\n gold: TaskGold,\n state: ProducedState,\n checkCorrectness: CorrectnessChecker,\n): Promise<CompletionVerdict> {\n if (gold.requirements.length === 0) {\n throw new Error(\n `verifyCompletion: task '${gold.taskId}' has no requirements — malformed gold spec`,\n )\n }\n\n // Collect every above-threshold (requirement, produced-item) candidate, then\n // assign greedily by descending score: each requirement and each produced\n // item is used at most once. One deliverable fulfils one requirement.\n const candidates: Candidate[] = []\n gold.requirements.forEach((req, i) => {\n const by = req.satisfiedBy ?? 'any'\n if (by === 'artifact' || by === 'any') {\n candidates.push(...artifactCandidates(req, i, state.artifacts))\n }\n if (by === 'proposal' || by === 'any') {\n candidates.push(...proposalCandidates(req, i, state.proposals))\n }\n if (by === 'tool-call' || by === 'any') {\n candidates.push(...toolCallCandidates(req, i, state.toolCalls))\n }\n })\n candidates.sort((a, b) => b.score - a.score)\n\n const assigned = new Map<number, Candidate>()\n const itemTaken = new Set<string>()\n for (const c of candidates) {\n if (assigned.has(c.reqIndex) || itemTaken.has(c.itemKey)) continue\n assigned.set(c.reqIndex, c)\n itemTaken.add(c.itemKey)\n }\n\n const requirements: RequirementCheck[] = []\n for (let i = 0; i < gold.requirements.length; i++) {\n const req = gold.requirements[i]!\n const match = assigned.get(i)\n const evidence: string[] = []\n let correct: boolean | null = null\n let unmeasuredReason: string | undefined\n\n if (match) {\n evidence.push(match.evidence)\n if (match.content !== null) {\n try {\n const r = await checkCorrectness(req, match.content)\n correct = r.correct\n evidence.push(`correctness: ${r.correct ? 'pass' : 'fail'} — ${r.reason}`)\n } catch (err) {\n // The CHECKER failed, not the requirement. Recording this as a\n // zero would fabricate a model failure out of an infrastructure\n // one; the requirement is unmeasured and leaves the denominator.\n unmeasuredReason =\n err instanceof JudgeParseError\n ? `checker response unparseable after retry: ${err.raw.slice(0, 200)}`\n : `checker call failed: ${err instanceof Error ? err.message : String(err)}`\n evidence.push(`correctness: UNMEASURED — ${unmeasuredReason}`)\n }\n } else {\n evidence.push('correctness: not assessed — matched item carries no content')\n }\n } else {\n const by = req.satisfiedBy ?? 'any'\n const kind = by === 'any' ? 'artifact/proposal/tool-call' : by\n evidence.push(`no produced ${kind} matched this requirement`)\n }\n\n const structurallyPresent = match !== undefined\n const unmeasured = unmeasuredReason !== undefined\n const satisfied = structurallyPresent && !unmeasured && correct !== false\n requirements.push({\n reqId: req.reqId,\n title: req.title,\n structurallyPresent,\n correct,\n satisfied,\n ...(unmeasured ? { unmeasured: true as const, unmeasuredReason } : {}),\n evidence,\n })\n }\n\n // The verdict blends the deterministic structural stage with the injected\n // correctness stage, so the certification names the checker's own member\n // and carries the structural stage's lexical nature as an assumption. A\n // checker without an attestation yields an uncertified verdict.\n const attestation = checkCorrectness.attestation\n const certification: VerdictCertification | undefined = attestation\n ? {\n strategy: attestation.strategy,\n checker: attestation.checker,\n assumptions: [\n 'structural matching is lexical token recall over produced items — the correctness stage only sees items it matched',\n ...attestation.assumptions,\n ],\n evidenceDigest: certificationEvidenceDigest({ taskId: gold.taskId, requirements }),\n }\n : undefined\n\n return completionVerdict({\n taskId: gold.taskId,\n requirements,\n ...(certification === undefined ? {} : { certification }),\n })\n}\n\nexport interface LlmCorrectnessCheckerOpts {\n model?: string\n /** Optional ledger for direct use. */\n costLedger?: CostLedgerHandle\n costPhase?: string\n costTags?: Record<string, string>\n signal?: AbortSignal\n /** Max chars of artifact content sent to the checker. */\n maxContentChars?: number\n /**\n * Checker LLM calls per requirement before giving up (parse failures and\n * call errors both consume attempts). The failure then surfaces as an\n * `unmeasured` requirement, never a zero.\n */\n maxAttempts?: number\n /**\n * Forensic capture of every checker request/response/error — without it a\n * checker failure is unauditable (the agent-turn raws never contain the\n * checker's own calls). Same sink contract as `LlmClient`.\n */\n rawSink?: RawProviderSink\n}\n\n/**\n * Parse the correctness checker's model response. Tolerates a response\n * truncated mid-JSON (max_tokens cap) by auto-closing the prefix — the\n * verdict boolean usually lands in the first few tokens, so a recovered\n * prefix with a boolean `correct` is a real measurement, not a guess.\n * Fails loud (JudgeParseError) when no boolean verdict is recoverable.\n */\nexport function parseCorrectnessResponse(raw: string): { correct: boolean; reason: string } {\n const readVerdict = (candidate: unknown): { correct: boolean; reason: string } | null => {\n if (candidate === null || typeof candidate !== 'object') return null\n const { correct, reason } = candidate as { correct?: unknown; reason?: unknown }\n if (typeof correct !== 'boolean') return null\n return { correct, reason: typeof reason === 'string' ? reason : '' }\n }\n\n const match = raw.match(/\\{[\\s\\S]*\\}/)\n if (match) {\n try {\n const strict = readVerdict(JSON.parse(match[0]))\n if (strict) return strict\n } catch {\n // fall through to truncation recovery\n }\n }\n // The strict path needs a closing `}`; a cap-hit response has none. Take\n // everything from the first `{` and auto-close it.\n const start = raw.indexOf('{')\n if (start !== -1) {\n const recovered = readVerdict(recoverTruncatedJson(raw.slice(start)))\n if (recovered) return recovered\n }\n throw new JudgeParseError('correctness-checker', raw)\n}\n\n/**\n * Production `CorrectnessChecker` — one LLM call per matched artifact,\n * deterministic (temperature 0), structured JSON out. Judges fulfilment\n * only: a plan, a gesture, or a description of what should be done does not\n * fulfil a requirement — the artifact must BE the deliverable.\n */\nexport function createLlmCorrectnessChecker(\n chat: ChatClient,\n opts: LlmCorrectnessCheckerOpts = {},\n): CorrectnessChecker {\n const model = opts.model ?? 'claude-sonnet-4-6'\n const maxContentChars = opts.maxContentChars ?? 8000\n const maxAttempts = opts.maxAttempts ?? 2\n const costLedger = opts.costLedger ?? new CostLedger()\n const sink = opts.rawSink\n const record = async (event: RawProviderEvent): Promise<void> => {\n // Forensic capture is best-effort; the verdict is the system of record.\n try {\n await sink?.record(event)\n } catch {\n // Intentionally swallowed.\n }\n }\n const checker: CorrectnessChecker = async (requirement, content) => {\n const request = {\n model,\n messages: [\n {\n role: 'system' as const,\n content:\n 'You verify whether a produced work artifact actually fulfils a stated requirement. Judge fulfilment only — is the deliverable substantively present and on-point — not polish. A plan to do it later, a vague gesture, or a description of what should be done does NOT fulfil a requirement; the artifact must BE the deliverable. Respond with a single JSON object: {\"correct\": boolean, \"reason\": string (<= 30 words)}.',\n },\n {\n role: 'user' as const,\n content: `Requirement: ${requirement.title}\\n${\n requirement.category ? `Category: ${requirement.category}\\n` : ''\n }\\nProduced artifact:\\n${content.slice(0, maxContentChars)}`,\n },\n ],\n temperature: 0,\n maxTokens: 200,\n } satisfies ChatRequest\n let lastErr: unknown\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const started = Date.now()\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'request',\n timestamp: started,\n requestBody: request,\n redactedFields: [],\n })\n try {\n const paid = await costLedger.runPaidCall({\n channel: 'verifier',\n phase: opts.costPhase ?? 'completion.correctness',\n actor: 'correctness-checker',\n model,\n maximumCharge:\n chat.maximumAttempts === undefined\n ? undefined\n : maximumChargeForLlmRequest(request, { maximumAttempts: chat.maximumAttempts }),\n tags: {\n ...opts.costTags,\n requirementId: requirement.reqId,\n attempt: String(attempt),\n },\n signal: opts.signal,\n execute: (signal, callId) => chat.chat(request, { signal, idempotencyKey: callId }),\n receipt: costReceiptFromLlm,\n receiptFromError: costReceiptFromLlmError,\n })\n if (!paid.succeeded) throw paid.error\n const resp = paid.value\n // Hold the transport to its own word: a verdict produced by a model\n // other than the one requested is not this model's verdict. A\n // transport that echoes no id cannot be made to prove identity here —\n // callers needing that proof enable it at the client\n // (`LlmClientOptions.assertServedModel`) or gate on `assertModelsServed`.\n assertServedModel(model, resp.servedModel, {\n allowUnreported: true,\n context: `correctness checker for requirement ${requirement.reqId}`,\n })\n const raw = resp.content\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'response',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n responseBody: resp,\n redactedFields: [],\n })\n return parseCorrectnessResponse(raw)\n } catch (err) {\n lastErr = err\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n // Substitution is a verdict about identity, not a transient fault:\n // another attempt reaches the same wrong model and spends more tokens.\n if (err instanceof ModelSubstitutionError) throw err\n }\n }\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n }\n checker.attestation = {\n strategy: 'judge',\n checker: { name: 'llm-correctness-checker', version: model },\n assumptions: [\n 'served-model identity is accepted when the transport reports none (assertServedModel allowUnreported)',\n ],\n }\n return checker\n}\n","/**\n * Produced-state extraction — normalize a run's runtime event stream into the\n * typed `ProducedState` the completion oracle consumes.\n *\n * `ProducedState` answers \"what did the agent actually produce\" — vault\n * artifacts, proposals, tool calls. The runtime emits these as a stream of\n * events; this module is the single normalization point from that stream to\n * the shape `verifyCompletion` expects.\n *\n * Input is structurally typed (`RuntimeEventLike`) so this module does not\n * depend on agent-runtime — agent-runtime's `RuntimeStreamEvent` satisfies it\n * structurally. The `content` on `ArtifactEventLike` and the whole\n * `proposal_created` variant are the runtime-side enrichments this contract\n * requires; the runtime emits them, this module consumes them.\n */\n\nimport type { Artifact } from './artifact-validator'\nimport type { ProducedProposal, ProducedState } from './completion-verifier'\n\n/** A tool the agent invoked. */\nexport interface ToolCallEventLike {\n type: 'tool_call'\n toolName: string\n}\n\n/**\n * An artifact the agent produced. `content` is the enriched field — the\n * runtime's base `artifact` event carries only metadata; the completion\n * oracle needs the body to verify the deliverable, so the runtime emits it.\n */\nexport interface ArtifactEventLike {\n type: 'artifact'\n artifactId: string\n name?: string\n mimeType?: string\n uri?: string\n content?: string\n}\n\n/** A proposal / filing the agent created. */\nexport interface ProposalEventLike {\n type: 'proposal_created'\n proposalId: string\n title: string\n status?: 'pending' | 'approved' | 'rejected'\n // body of the proposal (e.g. a submit_proposal `description`). When present,\n // the completion oracle correctness-checks it like artifact content; absent,\n // the proposal is graded presence-only.\n content?: string\n}\n\n/**\n * The subset of runtime stream events `extractProducedState` consumes.\n * agent-runtime's full `RuntimeStreamEvent` union satisfies this structurally;\n * the `{ type: string }` catch-all keeps the input permissive so callers can\n * pass the whole unfiltered telemetry stream — unrecognized events are skipped.\n */\nexport type RuntimeEventLike =\n | ToolCallEventLike\n | ArtifactEventLike\n | ProposalEventLike\n | { type: string }\n\nfunction artifactKind(mimeType: string | undefined): string {\n if (!mimeType) return 'file'\n if (mimeType.includes('json')) return 'json'\n if (mimeType.startsWith('text/')) return 'text'\n return 'file'\n}\n\n/**\n * Normalize an emission-ordered stream into its latest observed produced state.\n * Artifacts are keyed by their exact output path (name, then URI, then id);\n * proposals by id. Later observations replace earlier ones, including missing\n * content or a rejected status. An obsolete version cannot prove completion.\n * Distinct paths remain distinct; no path normalization or aliasing is inferred.\n * Results retain first-seen identity order. Tool names describe invocation,\n * not success, and are deduplicated in first-seen order.\n *\n * An artifact without observed content yields empty content, which the\n * completion oracle rejects. This projection does not verify external effects,\n * recover dropped events, or establish freshness beyond the supplied stream.\n */\nexport function extractProducedState(events: readonly RuntimeEventLike[]): ProducedState {\n const artifacts = new Map<string, Artifact>()\n const proposals = new Map<string, ProducedProposal>()\n const toolCalls: string[] = []\n const seenTools = new Set<string>()\n\n for (const ev of events) {\n if (ev.type === 'tool_call') {\n const name = (ev as ToolCallEventLike).toolName\n if (name && !seenTools.has(name)) {\n seenTools.add(name)\n toolCalls.push(name)\n }\n } else if (ev.type === 'artifact') {\n const a = ev as ArtifactEventLike\n const path = a.name ?? a.uri ?? a.artifactId\n artifacts.set(path, {\n kind: artifactKind(a.mimeType),\n path,\n content: a.content ?? '',\n })\n } else if (ev.type === 'proposal_created') {\n const p = ev as ProposalEventLike\n proposals.set(p.proposalId, {\n id: p.proposalId,\n title: p.title,\n status: p.status ?? 'pending',\n ...(p.content !== undefined ? { content: p.content } : {}),\n })\n }\n }\n\n return { artifacts: [...artifacts.values()], proposals: [...proposals.values()], toolCalls }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"produced-state-BsDmnwxc.js","names":[],"sources":["../src/agent-profile.ts","../src/completion-verifier.ts","../src/produced-state.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport { type HarnessType, harnessSupportsModel } from '@tangle-network/agent-interface'\nimport { ValidationError } from './errors'\nimport { canonicalString } from './ledger-core/canonical'\n\nexport type { AgentProfile, HarnessType } from '@tangle-network/agent-interface'\n\n/**\n * The agentic coding harnesses an eval sweeps by default — the ones we care about\n * ranking. This is the SINGLE source of that list; consumers import it instead of\n * re-declaring their own (a re-declared list is how the fleet drifts). Pass an\n * explicit `harnesses` (e.g. `harnessTypeSchema.options` for literally every known\n * harness) to widen beyond these.\n */\nexport const CODING_HARNESSES: readonly HarnessType[] = [\n 'opencode',\n 'claude-code',\n 'codex',\n 'kimi-code',\n]\n\nexport interface ProfileAxisSpec {\n /** The domain profile to sweep. Its prompt/tools/skills are held fixed; only the\n * harness and model vary. `model.default` is the fallback model. */\n base: AgentProfile\n /** Harnesses to cross. Default: {@link CODING_HARNESSES}. */\n harnesses?: readonly HarnessType[]\n /** Models to cross. Default: `[base.model.default]` — one model, i.e. today's\n * single-model behaviour, so omitting this never changes an existing run. */\n models?: readonly string[]\n /** Force every (harness, model) pair verbatim, even ones the harness can't run —\n * for deliberately testing failure modes. Default (false): SNAP instead — a\n * vendor-locked harness runs only the swept models in its family, or its native\n * default when it supports none, so no harness is dropped and none gets a\n * guaranteed-failing foreign-model cell. */\n keepIncompatible?: boolean\n}\n\n/** Model sentinel for a vendor-locked harness that supports none of the swept models:\n * it carries no provider prefix, so `harnessSupportsModel` accepts it and the harness\n * resolves it to its own native default model at runtime (e.g. kimi-code → its Kimi\n * model). Lets `expandProfileAxes` snap-instead-of-drop without a per-harness flagship\n * table that would rot as router catalogs change. */\nexport const HARNESS_NATIVE_MODEL = 'default'\n\n/**\n * Expand a base profile across the harness × model matrix into the `AgentProfile[]`\n * that `runProfileMatrix` / `selfImprove` score — the ONE place \"which harnesses ×\n * which models do we evaluate\" lives, so no product hand-rolls its own harness list\n * or column→profile mapping (the pattern that let those copies drift and silently\n * break the harness pivot).\n *\n * Each cell clones `base`, sets the canonical top-level `harness` and `model.default`,\n * and stamps `metadata.harness` + `metadata.harnessModel` for matrix grouping. Both\n * metadata fields are hash-bearing, so every cell gets a distinct `agentProfileId` row\n * and results join back by harness/model via {@link harnessAxisOf} with no\n * hand-recomputed key. A vendor-locked harness snaps to its family's swept models — or\n * its native default ({@link HARNESS_NATIVE_MODEL}) when it supports none — so every\n * requested harness runs; `keepIncompatible` forces every pair verbatim.\n *\n * Omit `harnesses`/`models` to sweep the full default set — the \"turn it on for\n * everything we care about\" switch, identical in shape whether one harness or all.\n */\nexport function expandProfileAxes(spec: ProfileAxisSpec): AgentProfile[] {\n const harnesses = spec.harnesses ?? CODING_HARNESSES\n if (harnesses.length === 0) throw new ValidationError('expandProfileAxes: no harnesses to sweep')\n const baseModel = spec.base.model?.default\n const models = spec.models ?? (baseModel ? [baseModel] : [])\n if (models.length === 0) {\n throw new ValidationError(\n 'expandProfileAxes: no models to sweep — base profile has no model.default and none were supplied',\n )\n }\n const out: AgentProfile[] = []\n const seen = new Set<string>()\n for (const harness of harnesses) {\n // A universal (router-backed) harness — opencode/pi/claudish — runs every swept\n // model. A vendor-locked harness — codex/claude-code/kimi-code — runs only the\n // swept models in its own family; when it supports NONE of them it snaps to its\n // native default (the `HARNESS_NATIVE_MODEL` sentinel it resolves at runtime)\n // rather than being dropped, so every requested harness still appears in the\n // sweep on a model it can actually run — e.g. sweeping `deepseek/x` puts opencode\n // on deepseek and kimi-code on its own Kimi model, a real head-to-head.\n // `keepIncompatible` forces every (harness, model) pair verbatim (failure-mode runs).\n const supported = spec.keepIncompatible\n ? models\n : models.filter((model) => harnessSupportsModel(harness, model))\n const effective = supported.length > 0 ? supported : [HARNESS_NATIVE_MODEL]\n for (const model of effective) {\n const profile: AgentProfile = {\n ...spec.base,\n harness,\n name: `${spec.base.name ?? 'agent'}/${harness}/${model}`,\n model: { ...spec.base.model, default: model },\n metadata: { ...(spec.base.metadata ?? {}), harness, harnessModel: model },\n }\n const id = agentProfileId(profile)\n if (seen.has(id)) continue\n seen.add(id)\n out.push(profile)\n }\n }\n if (out.length === 0) {\n // Unreachable in normal use — snapping guarantees ≥1 cell per harness — but keep a\n // fail-closed guard so a future refactor can't silently produce an empty sweep.\n throw new ValidationError(\n `expandProfileAxes: produced no profiles (harnesses=[${harnesses.join(', ')}], models=[${models.join(', ')}]).`,\n )\n }\n return out\n}\n\n/**\n * Read the (harness, model) a matrix cell ran under, off a profile or a result row's\n * profile — the join-back for a `byHarness` pivot. Returns undefined when the profile\n * wasn't produced by {@link expandProfileAxes}. Callers group `result.byProfile` by\n * this instead of recomputing an id (recomputing the wrong key is what broke the pivot\n * in the hand-rolled copies).\n */\nexport function harnessAxisOf(\n profile: Pick<AgentProfile, 'metadata'>,\n): { harness: HarnessType; model: string } | undefined {\n const m = profile.metadata as Record<string, unknown> | undefined\n const harness = m?.harness\n const model = m?.harnessModel\n if (typeof harness === 'string' && typeof model === 'string') {\n return { harness: harness as HarnessType, model }\n }\n return undefined\n}\n\n/**\n * Collision-resistant, path-safe, human-readable profile id for eval artifacts.\n * Scorecard joins still use `agentProfileHash`; this id is for run ids, matrix\n * keys, and directory names where two profiles must not collapse onto one row.\n * The suffix is the first 64 bits of the behaviour hash, enough for ordinary\n * eval matrices while keeping filenames readable.\n */\nexport function agentProfileId(profile: AgentProfile): string {\n const label = pathSafeProfileLabel(agentProfileDisplayLabel(profile)) ?? 'profile'\n return `${label}-${agentProfileHash(profile).slice(0, 16)}`\n}\n\n/**\n * Model snapshot used for `RunRecord.model`. Eval surfaces require a concrete\n * model id because run records reject bare/missing model aliases.\n */\nexport function agentProfileModelId(profile: AgentProfile): string {\n const model = profile.model?.default?.trim()\n if (!model) {\n const label = agentProfileDisplayLabel(profile) ?? 'unnamed profile'\n throw new ValidationError(\n `AgentProfile \"${label}\" has no model.default — cannot record eval run`,\n )\n }\n return model\n}\n\nfunction agentProfileDisplayLabel(profile: AgentProfile): string | undefined {\n return profile.name?.trim() || profile.version?.trim() || undefined\n}\n\nfunction pathSafeProfileLabel(label: string | undefined): string | undefined {\n const safe = label\n ?.trim()\n .replace(/[^A-Za-z0-9._-]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n return safe || undefined\n}\n\nfunction compact<T extends Record<string, unknown>>(input: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(input)) {\n if (value !== undefined) out[key] = value\n }\n return out as Partial<T>\n}\n\n/**\n * Deterministic behaviour identity for the canonical\n * `@tangle-network/agent-interface` AgentProfile.\n *\n * `name` and `description` are labels and do not affect the hash. Profile\n * `version`, prompt, model hints, tools, resources, hooks, modes, permissions,\n * and extensions do affect the hash. Resource array order is hash-bearing\n * because mount order can change agent behaviour. Undefined fields are treated\n * as absent; explicit `null` fields remain hash-bearing.\n */\nexport function agentProfileHash(profile: AgentProfile): string {\n const model = agentProfileModelId(profile)\n const behaviour = compact({\n ...profile,\n name: undefined,\n description: undefined,\n tags: profile.tags ? [...profile.tags].sort() : undefined,\n model: compact({ ...profile.model, default: model }),\n })\n return createHash('sha256').update(canonicalString(behaviour)).digest('hex')\n}\n","/**\n * Completion verifier — the task-completion oracle.\n *\n * Answers the only eval question that is not a proxy: did the agent actually\n * COMPLETE the task — produce every required deliverable, persisted and\n * correct — rather than describe what should be done. A fluent transcript\n * that never produces the artifact scores zero here.\n *\n * Per requirement, a two-stage check:\n * 1. Structural — a produced item (vault artifact / approved proposal /\n * tool call) of the right kind is matched against the requirement and\n * carries non-empty content. Deterministic; no LLM.\n * 2. Correctness — only if structurally present AND the matched item\n * carries content, one targeted check decides whether that item\n * actually fulfils the requirement. A hallucinated artifact fails here;\n * an absent one already failed stage 1.\n *\n * `completionRate` is satisfied / MEASURABLE requirements (unmeasured rows —\n * checker failures — are excluded from the denominator, never scored as\n * zeros). Quality dimensions are meaningless on an incomplete task — callers\n * gate on `fullyComplete` / `completionRate` before scoring quality.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type { ChatClient, ChatRequest } from './analyst/chat-client'\nimport type { Artifact } from './artifact-validator'\nimport { CostLedger, type CostLedgerHandle } from './cost-ledger'\nimport { assertServedModel, ModelSubstitutionError } from './integrity/served-model'\nimport { recoverTruncatedJson } from './json-recovery'\nimport { JudgeParseError } from './judges'\nimport {\n costReceiptFromLlm,\n costReceiptFromLlmError,\n maximumChargeForLlmRequest,\n} from './llm-client'\nimport type { RawProviderEvent, RawProviderSink } from './trace/raw-provider-sink'\nimport {\n certificationEvidenceDigest,\n type DefaultVerdict,\n type VerdictCertification,\n} from './verdict'\nimport type { CheckerIdentity, VerificationStrategySource } from './verification-strategy'\n\n/** What kind of produced state can satisfy a requirement structurally. */\nexport type SatisfiedBy = 'artifact' | 'proposal' | 'tool-call' | 'any'\n\nexport interface CompletionRequirement {\n /** Stable id from the task gold (e.g. a persona's `expected_requirements[].req_id`). */\n reqId: string\n /** Human-readable description of the required deliverable. */\n title: string\n /** Optional kind/category hint, matched against a produced item's kind. */\n category?: string\n /** What produced state satisfies this requirement. Defaults to 'any'. */\n satisfiedBy?: SatisfiedBy\n}\n\nexport interface TaskGold {\n taskId: string\n requirements: CompletionRequirement[]\n}\n\nexport interface ProducedProposal {\n id: string\n title: string\n status: 'pending' | 'approved' | 'rejected'\n /** Optional persisted body — when present, enables a correctness check. */\n content?: string\n}\n\n/** Everything observable about what a run actually produced. */\nexport interface ProducedState {\n /** Persisted vault artifacts. Reuses the shared `Artifact` shape. */\n artifacts: Artifact[]\n /** Proposals / filings the agent created. */\n proposals: ProducedProposal[]\n /** Names of tools the agent invoked. */\n toolCalls: string[]\n}\n\nexport interface RequirementCheck {\n reqId: string\n title: string\n /** A produced item of the right kind matched the requirement, non-empty. */\n structurallyPresent: boolean\n /**\n * Whether the matched item actually fulfils the requirement. `null` when\n * not structurally present, when the matched item carries no content\n * to assess, or when the correctness check itself failed (`unmeasured`).\n */\n correct: boolean | null\n /** structurallyPresent && !unmeasured && correct !== false. */\n satisfied: boolean\n /**\n * Set when the correctness check itself errored (LLM call failure or an\n * unparseable response after retry). The requirement's fulfilment is\n * UNKNOWN — `correct` stays null, `satisfied` is false, and\n * `completionVerdict` excludes the row from `completionRate`'s\n * denominator. Never folded into a zero: a synthetic zero is\n * indistinguishable from a real failure (see `JudgeParseError`).\n */\n unmeasured?: true\n /** Why the correctness check could not be measured (present iff `unmeasured`). */\n unmeasuredReason?: string\n /** Human-readable evidence for the verdict. */\n evidence: string[]\n}\n\n/** Extends the substrate verdict spine: `valid` = `fullyComplete` and\n * `score` = `completionRate` — derived in `completionVerdict()`, the one\n * place those equalities hold by construction. */\nexport interface CompletionVerdict extends DefaultVerdict {\n taskId: string\n requirements: RequirementCheck[]\n /** satisfied / MEASURABLE requirements (unmeasured rows leave the denominator). */\n completionRate: number\n /** Every measurable requirement satisfied (false when anything is unmeasured). */\n fullyComplete: boolean\n /** Requirements whose correctness check errored — reported, never scored as zero. */\n unmeasuredCount: number\n}\n\n/**\n * Construct a `CompletionVerdict` from the per-requirement checks, deriving\n * `completionRate` / `fullyComplete` and the spine fields (`valid` =\n * `fullyComplete`, `score` = `completionRate`) in one place. Throws on zero\n * requirements — a verdict over nothing is a misconfiguration, mirroring\n * `verifyCompletion`'s gold-spec guard.\n */\nexport function completionVerdict(input: {\n taskId: string\n requirements: RequirementCheck[]\n /** What certified the correctness stage, when anything did. Omitted =\n * an uncertified verdict — the honest default for a bare checker. */\n certification?: VerdictCertification\n}): CompletionVerdict {\n if (input.requirements.length === 0) {\n throw new Error(\n `completionVerdict: task '${input.taskId}' has no requirement checks — nothing to derive a verdict from`,\n )\n }\n const measurable = input.requirements.filter((r) => !r.unmeasured)\n const unmeasuredCount = input.requirements.length - measurable.length\n if (measurable.length === 0) {\n // Every check errored: this is an infrastructure failure, not a scored\n // run. A 0-rate verdict here would be a fabricated measurement.\n throw new Error(\n `completionVerdict: task '${input.taskId}' has no measurable requirements — all ${input.requirements.length} correctness checks failed (${input.requirements[0]?.unmeasuredReason ?? 'unknown reason'})`,\n )\n }\n const satisfiedCount = measurable.filter((r) => r.satisfied).length\n const completionRate = satisfiedCount / measurable.length\n // A run with unmeasured rows can still report a rate over what WAS\n // measured, but must not claim full completion.\n const fullyComplete = unmeasuredCount === 0 && satisfiedCount === measurable.length\n return {\n taskId: input.taskId,\n requirements: input.requirements,\n completionRate,\n fullyComplete,\n unmeasuredCount,\n valid: fullyComplete,\n score: completionRate,\n ...(input.certification === undefined ? {} : { certification: input.certification }),\n }\n}\n\n/**\n * What a correctness checker declares about itself so the completion\n * verdict can carry a certification: which strategy member it discharges,\n * its exact identity, and the steps its answers rest on unverified.\n */\nexport interface CorrectnessCheckerAttestation {\n strategy: VerificationStrategySource\n checker: CheckerIdentity\n assumptions: string[]\n}\n\n/**\n * Decides whether a produced item's content actually fulfils a requirement.\n * Injected so the structural verifier stays pure and unit-testable; the\n * production implementation is `createLlmCorrectnessChecker`.\n *\n * `attestation` is optional metadata on the function value: a checker that\n * carries one yields certified completion verdicts; a bare function yields\n * the same verdict uncertified. A plain arrow function remains a valid\n * checker.\n */\nexport interface CorrectnessChecker {\n (\n requirement: CompletionRequirement,\n content: string,\n ): Promise<{ correct: boolean; reason: string }>\n attestation?: CorrectnessCheckerAttestation\n}\n\nconst STOPWORDS = new Set([\n 'the',\n 'a',\n 'an',\n 'of',\n 'for',\n 'and',\n 'or',\n 'to',\n 'in',\n 'on',\n 'with',\n 'by',\n])\n\n// Deliverable-FORM vocabulary — words that name the SHAPE of an output, not its\n// domain content. A correct \"swap-comparison view persisted as a ui/** artifact\"\n// is an OpenUI JSON whose body says nothing about \"artifact\" / \"persisted\" /\n// \"view\"; the discriminative tokens are the domain nouns (swap, comparison).\n// Stripped from the REQUIREMENT side of structural recall so a deliverable is\n// matched on what it IS about, not on the boilerplate describing its form. The\n// correctness checker strips the same class via TITLE_STOPWORDS. Anti-game holds:\n// the distinctive domain tokens remain, so an off-topic item still fails.\nconst REQUIREMENT_FORM_STOPWORDS = new Set([\n 'generated',\n 'generate',\n 'view',\n 'render',\n 'rendered',\n 'persisted',\n 'persist',\n 'artifact',\n 'file',\n 'document',\n 'note',\n 'proposal',\n 'deliverable',\n 'output',\n 'created',\n 'create',\n 'produce',\n 'produced',\n 'flag',\n])\n\nconst MATCH_THRESHOLD = 0.5\nconst MIN_CONTENT_CHARS = 50\n\nfunction tokens(s: string, extraStop?: Set<string>): Set<string> {\n return new Set(\n s\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 1 && !STOPWORDS.has(t) && !extraStop?.has(t)),\n )\n}\n\n/**\n * Recall of the requirement's tokens within a candidate's identifying text.\n * Recall, not Jaccard — a candidate's path/id legitimately carries extra\n * tokens the requirement does not name. The requirement side drops\n * deliverable-FORM vocabulary so recall keys on the distinctive domain tokens.\n */\nfunction tokenRecall(requirementText: string, candidateText: string): number {\n const req = tokens(requirementText, REQUIREMENT_FORM_STOPWORDS)\n if (req.size === 0) return 0\n const cand = tokens(candidateText)\n let hit = 0\n for (const t of req) if (cand.has(t)) hit++\n return hit / req.size\n}\n\ninterface Candidate {\n reqIndex: number\n /** Unique key for a produced item — each item satisfies at most one requirement. */\n itemKey: string\n score: number\n evidence: string\n /** Content to correctness-check, or null when the matched item has none. */\n content: string | null\n}\n\nfunction artifactCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n artifacts: Artifact[],\n): Candidate[] {\n const reqText = `${req.title} ${req.category ?? ''}`\n const out: Candidate[] = []\n artifacts.forEach((a, i) => {\n if ((a.content ?? '').trim().length < MIN_CONTENT_CHARS) return\n // Match against the artifact CONTENT too, not just its path + kind — a\n // generated view / note whose path is generic still satisfies a requirement\n // when its body covers it (e.g. an OpenUI comparison grounded in the on-file\n // figures). Bounded slice keeps the recall text cheap; MATCH_THRESHOLD holds.\n let score = tokenRecall(\n reqText,\n `${a.path ?? ''} ${a.kind} ${(a.content ?? '').slice(0, 4000)}`,\n )\n if (req.category && a.kind && req.category.toLowerCase() === a.kind.toLowerCase()) {\n score = Math.max(score, 1)\n }\n if (score < MATCH_THRESHOLD) return\n out.push({\n reqIndex,\n itemKey: `artifact:${i}`,\n score,\n evidence: `artifact '${a.path ?? a.kind}' matched (token recall ${score.toFixed(2)})`,\n content: a.content ?? null,\n })\n })\n return out\n}\n\nfunction proposalCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n proposals: ProducedProposal[],\n): Candidate[] {\n const reqText = `${req.title} ${req.category ?? ''}`\n const out: Candidate[] = []\n for (const p of proposals) {\n // Pending or rejected work is not a completed deliverable.\n if (p.status !== 'approved') continue\n // A proposal needs an assessable BODY to be a deliverable. A bare title is\n // not completion: correctness cannot be judged on it, so a title-only match\n // would auto-pass the oracle (structurallyPresent && correct===null →\n // satisfied) with no verifiable content. Tool calls are the only\n // legitimately content-less deliverable (`toolCallCandidates`).\n const body = (p.content ?? '').trim()\n if (body.length < MIN_CONTENT_CHARS) continue\n // Match against the body as well as the (often short) title — a refusal /\n // flag / analysis proposal whose title is a label still satisfies a\n // descriptively-worded requirement when its content covers it. MATCH_THRESHOLD\n // + the requirement's distinctive tokens keep an off-topic proposal out;\n // correctness (a SEMANTIC checker, NOT this lexical pass) then judges\n // polarity/fulfilment, so a negation that merely contains the tokens fails.\n // Structural and correctness must use different evidence or the two-stage\n // check collapses to one lexical gate.\n const score = tokenRecall(reqText, `${p.title} ${body}`)\n if (score < MATCH_THRESHOLD) continue\n out.push({\n reqIndex,\n itemKey: `proposal:${p.id}`,\n score,\n evidence: `approved proposal '${p.title}' matched (token recall ${score.toFixed(2)})`,\n content: body,\n })\n }\n return out\n}\n\nfunction toolCallCandidates(\n req: CompletionRequirement,\n reqIndex: number,\n toolCalls: string[],\n): Candidate[] {\n const out: Candidate[] = []\n toolCalls.forEach((name, i) => {\n const score = tokenRecall(req.title, name)\n if (score < MATCH_THRESHOLD) return\n out.push({\n reqIndex,\n itemKey: `tool:${i}`,\n score,\n evidence: `tool call '${name}' matched (token recall ${score.toFixed(2)})`,\n content: null,\n })\n })\n return out\n}\n\n/**\n * Verify whether a run completed the task. `checkCorrectness` is injected —\n * `createLlmCorrectnessChecker` for production, a deterministic stub in tests.\n *\n * Throws on a gold spec with no requirements: an eval task that requires\n * nothing is a misconfiguration, not a vacuously-complete task.\n */\nexport async function verifyCompletion(\n gold: TaskGold,\n state: ProducedState,\n checkCorrectness: CorrectnessChecker,\n): Promise<CompletionVerdict> {\n if (gold.requirements.length === 0) {\n throw new Error(\n `verifyCompletion: task '${gold.taskId}' has no requirements — malformed gold spec`,\n )\n }\n\n // Collect every above-threshold (requirement, produced-item) candidate, then\n // assign greedily by descending score: each requirement and each produced\n // item is used at most once. One deliverable fulfils one requirement.\n const candidates: Candidate[] = []\n gold.requirements.forEach((req, i) => {\n const by = req.satisfiedBy ?? 'any'\n if (by === 'artifact' || by === 'any') {\n candidates.push(...artifactCandidates(req, i, state.artifacts))\n }\n if (by === 'proposal' || by === 'any') {\n candidates.push(...proposalCandidates(req, i, state.proposals))\n }\n if (by === 'tool-call' || by === 'any') {\n candidates.push(...toolCallCandidates(req, i, state.toolCalls))\n }\n })\n candidates.sort((a, b) => b.score - a.score)\n\n const assigned = new Map<number, Candidate>()\n const itemTaken = new Set<string>()\n for (const c of candidates) {\n if (assigned.has(c.reqIndex) || itemTaken.has(c.itemKey)) continue\n assigned.set(c.reqIndex, c)\n itemTaken.add(c.itemKey)\n }\n\n const requirements: RequirementCheck[] = []\n for (let i = 0; i < gold.requirements.length; i++) {\n const req = gold.requirements[i]!\n const match = assigned.get(i)\n const evidence: string[] = []\n let correct: boolean | null = null\n let unmeasuredReason: string | undefined\n\n if (match) {\n evidence.push(match.evidence)\n if (match.content !== null) {\n try {\n const r = await checkCorrectness(req, match.content)\n correct = r.correct\n evidence.push(`correctness: ${r.correct ? 'pass' : 'fail'} — ${r.reason}`)\n } catch (err) {\n // The CHECKER failed, not the requirement. Recording this as a\n // zero would fabricate a model failure out of an infrastructure\n // one; the requirement is unmeasured and leaves the denominator.\n unmeasuredReason =\n err instanceof JudgeParseError\n ? `checker response unparseable after retry: ${err.raw.slice(0, 200)}`\n : `checker call failed: ${err instanceof Error ? err.message : String(err)}`\n evidence.push(`correctness: UNMEASURED — ${unmeasuredReason}`)\n }\n } else {\n evidence.push('correctness: not assessed — matched item carries no content')\n }\n } else {\n const by = req.satisfiedBy ?? 'any'\n const kind = by === 'any' ? 'artifact/proposal/tool-call' : by\n evidence.push(`no produced ${kind} matched this requirement`)\n }\n\n const structurallyPresent = match !== undefined\n const unmeasured = unmeasuredReason !== undefined\n const satisfied = structurallyPresent && !unmeasured && correct !== false\n requirements.push({\n reqId: req.reqId,\n title: req.title,\n structurallyPresent,\n correct,\n satisfied,\n ...(unmeasured ? { unmeasured: true as const, unmeasuredReason } : {}),\n evidence,\n })\n }\n\n // The verdict blends the deterministic structural stage with the injected\n // correctness stage, so the certification names the checker's own member\n // and carries the structural stage's lexical nature as an assumption. A\n // checker without an attestation yields an uncertified verdict.\n const attestation = checkCorrectness.attestation\n const certification: VerdictCertification | undefined = attestation\n ? {\n strategy: attestation.strategy,\n checker: attestation.checker,\n assumptions: [\n 'structural matching is lexical token recall over produced items — the correctness stage only sees items it matched',\n ...attestation.assumptions,\n ],\n evidenceDigest: certificationEvidenceDigest({ taskId: gold.taskId, requirements }),\n }\n : undefined\n\n return completionVerdict({\n taskId: gold.taskId,\n requirements,\n ...(certification === undefined ? {} : { certification }),\n })\n}\n\nexport interface LlmCorrectnessCheckerOpts {\n model?: string\n /** Optional ledger for direct use. */\n costLedger?: CostLedgerHandle\n costPhase?: string\n costTags?: Record<string, string>\n signal?: AbortSignal\n /** Max chars of artifact content sent to the checker. */\n maxContentChars?: number\n /**\n * Checker LLM calls per requirement before giving up (parse failures and\n * call errors both consume attempts). The failure then surfaces as an\n * `unmeasured` requirement, never a zero.\n */\n maxAttempts?: number\n /**\n * Forensic capture of every checker request/response/error — without it a\n * checker failure is unauditable (the agent-turn raws never contain the\n * checker's own calls). Same sink contract as `LlmClient`.\n */\n rawSink?: RawProviderSink\n}\n\n/**\n * Parse the correctness checker's model response. Tolerates a response\n * truncated mid-JSON (max_tokens cap) by auto-closing the prefix — the\n * verdict boolean usually lands in the first few tokens, so a recovered\n * prefix with a boolean `correct` is a real measurement, not a guess.\n * Fails loud (JudgeParseError) when no boolean verdict is recoverable.\n */\nexport function parseCorrectnessResponse(raw: string): { correct: boolean; reason: string } {\n const readVerdict = (candidate: unknown): { correct: boolean; reason: string } | null => {\n if (candidate === null || typeof candidate !== 'object') return null\n const { correct, reason } = candidate as { correct?: unknown; reason?: unknown }\n if (typeof correct !== 'boolean') return null\n return { correct, reason: typeof reason === 'string' ? reason : '' }\n }\n\n const match = raw.match(/\\{[\\s\\S]*\\}/)\n if (match) {\n try {\n const strict = readVerdict(JSON.parse(match[0]))\n if (strict) return strict\n } catch {\n // fall through to truncation recovery\n }\n }\n // The strict path needs a closing `}`; a cap-hit response has none. Take\n // everything from the first `{` and auto-close it.\n const start = raw.indexOf('{')\n if (start !== -1) {\n const recovered = readVerdict(recoverTruncatedJson(raw.slice(start)))\n if (recovered) return recovered\n }\n throw new JudgeParseError('correctness-checker', raw)\n}\n\n/**\n * Production `CorrectnessChecker` — one LLM call per matched artifact,\n * deterministic (temperature 0), structured JSON out. Judges fulfilment\n * only: a plan, a gesture, or a description of what should be done does not\n * fulfil a requirement — the artifact must BE the deliverable.\n */\nexport function createLlmCorrectnessChecker(\n chat: ChatClient,\n opts: LlmCorrectnessCheckerOpts = {},\n): CorrectnessChecker {\n const model = opts.model ?? 'claude-sonnet-4-6'\n const maxContentChars = opts.maxContentChars ?? 8000\n const maxAttempts = opts.maxAttempts ?? 2\n const costLedger = opts.costLedger ?? new CostLedger()\n const sink = opts.rawSink\n const record = async (event: RawProviderEvent): Promise<void> => {\n // Forensic capture is best-effort; the verdict is the system of record.\n try {\n await sink?.record(event)\n } catch {\n // Intentionally swallowed.\n }\n }\n const checker: CorrectnessChecker = async (requirement, content) => {\n const request = {\n model,\n messages: [\n {\n role: 'system' as const,\n content:\n 'You verify whether a produced work artifact actually fulfils a stated requirement. Judge fulfilment only — is the deliverable substantively present and on-point — not polish. A plan to do it later, a vague gesture, or a description of what should be done does NOT fulfil a requirement; the artifact must BE the deliverable. Respond with a single JSON object: {\"correct\": boolean, \"reason\": string (<= 30 words)}.',\n },\n {\n role: 'user' as const,\n content: `Requirement: ${requirement.title}\\n${\n requirement.category ? `Category: ${requirement.category}\\n` : ''\n }\\nProduced artifact:\\n${content.slice(0, maxContentChars)}`,\n },\n ],\n temperature: 0,\n maxTokens: 200,\n } satisfies ChatRequest\n let lastErr: unknown\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const started = Date.now()\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'request',\n timestamp: started,\n requestBody: request,\n redactedFields: [],\n })\n try {\n const paid = await costLedger.runPaidCall({\n channel: 'verifier',\n phase: opts.costPhase ?? 'completion.correctness',\n actor: 'correctness-checker',\n model,\n maximumCharge:\n chat.maximumAttempts === undefined\n ? undefined\n : maximumChargeForLlmRequest(request, { maximumAttempts: chat.maximumAttempts }),\n tags: {\n ...opts.costTags,\n requirementId: requirement.reqId,\n attempt: String(attempt),\n },\n signal: opts.signal,\n execute: (signal, callId) => chat.chat(request, { signal, idempotencyKey: callId }),\n receipt: costReceiptFromLlm,\n receiptFromError: costReceiptFromLlmError,\n })\n if (!paid.succeeded) throw paid.error\n const resp = paid.value\n // Hold the transport to its own word: a verdict produced by a model\n // other than the one requested is not this model's verdict. A\n // transport that echoes no id cannot be made to prove identity here —\n // callers needing that proof enable it at the client\n // (`LlmClientOptions.assertServedModel`) or gate on `assertModelsServed`.\n assertServedModel(model, resp.servedModel, {\n allowUnreported: true,\n context: `correctness checker for requirement ${requirement.reqId}`,\n })\n const raw = resp.content\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'response',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n responseBody: resp,\n redactedFields: [],\n })\n return parseCorrectnessResponse(raw)\n } catch (err) {\n lastErr = err\n await record({\n eventId: randomUUID(),\n provider: chat.transport,\n model,\n endpoint: '/chat',\n baseUrl: '',\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n // Substitution is a verdict about identity, not a transient fault:\n // another attempt reaches the same wrong model and spends more tokens.\n if (err instanceof ModelSubstitutionError) throw err\n }\n }\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n }\n checker.attestation = {\n strategy: 'judge',\n checker: { name: 'llm-correctness-checker', version: model },\n assumptions: [\n 'served-model identity is accepted when the transport reports none (assertServedModel allowUnreported)',\n ],\n }\n return checker\n}\n","/**\n * Produced-state extraction — normalize a run's runtime event stream into the\n * typed `ProducedState` the completion oracle consumes.\n *\n * `ProducedState` answers \"what did the agent actually produce\" — vault\n * artifacts, proposals, tool calls. The runtime emits these as a stream of\n * events; this module is the single normalization point from that stream to\n * the shape `verifyCompletion` expects.\n *\n * Input is structurally typed (`RuntimeEventLike`) so this module does not\n * depend on agent-runtime — agent-runtime's `RuntimeStreamEvent` satisfies it\n * structurally. The `content` on `ArtifactEventLike` and the whole\n * `proposal_created` variant are the runtime-side enrichments this contract\n * requires; the runtime emits them, this module consumes them.\n */\n\nimport type { Artifact } from './artifact-validator'\nimport type { ProducedProposal, ProducedState } from './completion-verifier'\n\n/** A tool the agent invoked. */\nexport interface ToolCallEventLike {\n type: 'tool_call'\n toolName: string\n}\n\n/**\n * An artifact the agent produced. `content` is the enriched field — the\n * runtime's base `artifact` event carries only metadata; the completion\n * oracle needs the body to verify the deliverable, so the runtime emits it.\n */\nexport interface ArtifactEventLike {\n type: 'artifact'\n artifactId: string\n name?: string\n mimeType?: string\n uri?: string\n content?: string\n}\n\n/** A proposal / filing the agent created. */\nexport interface ProposalEventLike {\n type: 'proposal_created'\n proposalId: string\n title: string\n status?: 'pending' | 'approved' | 'rejected'\n // body of the proposal (e.g. a submit_proposal `description`). When present,\n // the completion oracle correctness-checks it like artifact content; absent,\n // the proposal is graded presence-only.\n content?: string\n}\n\n/**\n * The subset of runtime stream events `extractProducedState` consumes.\n * agent-runtime's full `RuntimeStreamEvent` union satisfies this structurally;\n * the `{ type: string }` catch-all keeps the input permissive so callers can\n * pass the whole unfiltered telemetry stream — unrecognized events are skipped.\n */\nexport type RuntimeEventLike =\n | ToolCallEventLike\n | ArtifactEventLike\n | ProposalEventLike\n | { type: string }\n\nfunction artifactKind(mimeType: string | undefined): string {\n if (!mimeType) return 'file'\n if (mimeType.includes('json')) return 'json'\n if (mimeType.startsWith('text/')) return 'text'\n return 'file'\n}\n\n/**\n * Normalize an emission-ordered stream into its latest observed produced state.\n * Artifacts are keyed by their exact output path (name, then URI, then id);\n * proposals by id. Later observations replace earlier ones, including missing\n * content or a rejected status. An obsolete version cannot prove completion.\n * Distinct paths remain distinct; no path normalization or aliasing is inferred.\n * Results retain first-seen identity order. Tool names describe invocation,\n * not success, and are deduplicated in first-seen order.\n *\n * An artifact without observed content yields empty content, which the\n * completion oracle rejects. This projection does not verify external effects,\n * recover dropped events, or establish freshness beyond the supplied stream.\n */\nexport function extractProducedState(events: readonly RuntimeEventLike[]): ProducedState {\n const artifacts = new Map<string, Artifact>()\n const proposals = new Map<string, ProducedProposal>()\n const toolCalls: string[] = []\n const seenTools = new Set<string>()\n\n for (const ev of events) {\n if (ev.type === 'tool_call') {\n const name = (ev as ToolCallEventLike).toolName\n if (name && !seenTools.has(name)) {\n seenTools.add(name)\n toolCalls.push(name)\n }\n } else if (ev.type === 'artifact') {\n const a = ev as ArtifactEventLike\n const path = a.name ?? a.uri ?? a.artifactId\n artifacts.set(path, {\n kind: artifactKind(a.mimeType),\n path,\n content: a.content ?? '',\n })\n } else if (ev.type === 'proposal_created') {\n const p = ev as ProposalEventLike\n proposals.set(p.proposalId, {\n id: p.proposalId,\n title: p.title,\n status: p.status ?? 'pending',\n ...(p.content !== undefined ? { content: p.content } : {}),\n })\n }\n }\n\n return { artifacts: [...artifacts.values()], proposals: [...proposals.values()], toolCalls }\n}\n"],"mappings":"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"}
|
package/dist/profile-cell.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as buildAgentInterfaceProfileCell, c as requireAgentProfileCell, d as verifyAgentProfileCell, i as assertRunAgentProfileCell, l as toAgentProfileJson, n as AgentProfileCellValidationError, o as buildAgentProfileCell, r as agentProfileCellKey, s as groupRunsByAgentProfileCell, t as AGENT_PROFILE_KINDS, u as validateAgentProfileCell } from "./agent-profile-cell-
|
|
1
|
+
import { a as buildAgentInterfaceProfileCell, c as requireAgentProfileCell, d as verifyAgentProfileCell, i as assertRunAgentProfileCell, l as toAgentProfileJson, n as AgentProfileCellValidationError, o as buildAgentProfileCell, r as agentProfileCellKey, s as groupRunsByAgentProfileCell, t as AGENT_PROFILE_KINDS, u as validateAgentProfileCell } from "./agent-profile-cell-BK8mlqlq.js";
|
|
2
2
|
export { AGENT_PROFILE_KINDS, AgentProfileCellValidationError, agentProfileCellKey, assertRunAgentProfileCell, buildAgentInterfaceProfileCell, buildAgentProfileCell, groupRunsByAgentProfileCell, requireAgentProfileCell, toAgentProfileJson, validateAgentProfileCell, verifyAgentProfileCell };
|