@tangle-network/agent-eval 0.190.0 → 0.191.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/adapters/http.d.ts +2 -2
  3. package/dist/{agent-profile-DNV_U6QR.d.ts → agent-profile-DDfIjdyS.d.ts} +3 -3
  4. package/dist/{agent-profile-DNV_U6QR.d.ts.map → agent-profile-DDfIjdyS.d.ts.map} +1 -1
  5. package/dist/analyst/index.d.ts +11 -11
  6. package/dist/analyst/index.d.ts.map +1 -1
  7. package/dist/analyst/index.js +6 -6
  8. package/dist/{insight-report-CvPkEIcC.d.ts → analyze-runs-CPiKLJFs.d.ts} +73 -3
  9. package/dist/analyze-runs-CPiKLJFs.d.ts.map +1 -0
  10. package/dist/{attribute-vocabulary-DLJ6303h.d.ts → attribute-vocabulary-CcXqHODT.d.ts} +23 -12
  11. package/dist/attribute-vocabulary-CcXqHODT.d.ts.map +1 -0
  12. package/dist/{benchmark-command-TZlsuAh9.js → benchmark-command-3tZJnD82.js} +12 -11
  13. package/dist/benchmark-command-3tZJnD82.js.map +1 -0
  14. package/dist/benchmarks/index.d.ts +3 -3
  15. package/dist/benchmarks/index.js +3 -3
  16. package/dist/campaign/index.d.ts +6 -6
  17. package/dist/campaign/index.js +9 -7
  18. package/dist/{campaign-_29Qpc9Z.js → campaign-C8iWEF0M.js} +11 -9
  19. package/dist/{campaign-_29Qpc9Z.js.map → campaign-C8iWEF0M.js.map} +1 -1
  20. package/dist/{campaign-evidence-CWF8pEIk.js → campaign-evidence-BqjlTM3P.js} +11 -112
  21. package/dist/campaign-evidence-BqjlTM3P.js.map +1 -0
  22. package/dist/{chat-client-DbH06Ek6.js → chat-client-B_ItsSBw.js} +2 -2
  23. package/dist/{chat-client-DbH06Ek6.js.map → chat-client-B_ItsSBw.js.map} +1 -1
  24. package/dist/{chat-json-call-B0xTEY0I.js → chat-json-call-CXHBvUz8.js} +2 -2
  25. package/dist/{chat-json-call-B0xTEY0I.js.map → chat-json-call-CXHBvUz8.js.map} +1 -1
  26. package/dist/claim-V9Zqbq0J.js +54 -0
  27. package/dist/claim-V9Zqbq0J.js.map +1 -0
  28. package/dist/cli.js +101 -4
  29. package/dist/cli.js.map +1 -1
  30. package/dist/client-wFyDisxi.d.ts +236 -0
  31. package/dist/client-wFyDisxi.d.ts.map +1 -0
  32. package/dist/contract/index.d.ts +10 -11
  33. package/dist/contract/index.js +11 -141
  34. package/dist/contract/index.js.map +1 -1
  35. package/dist/{default-registry-B5HrwrPM.d.ts → default-registry-DK_9aVJf.d.ts} +6 -6
  36. package/dist/{default-registry-B5HrwrPM.d.ts.map → default-registry-DK_9aVJf.d.ts.map} +1 -1
  37. package/dist/{default-registry-16I-Bxlf.js → default-registry-xMLX160E.js} +3 -3
  38. package/dist/{default-registry-16I-Bxlf.js.map → default-registry-xMLX160E.js.map} +1 -1
  39. package/dist/{define-agent-eval-DrGfrCTZ.js → define-agent-eval-BE43YTm4.js} +27 -109
  40. package/dist/define-agent-eval-BE43YTm4.js.map +1 -0
  41. package/dist/{define-agent-eval-BWeyIpny.d.ts → define-agent-eval-P28y7mI1.d.ts} +16 -20
  42. package/dist/define-agent-eval-P28y7mI1.d.ts.map +1 -0
  43. package/dist/diagnosis/index.d.ts +16 -4
  44. package/dist/diagnosis/index.d.ts.map +1 -1
  45. package/dist/diagnosis/index.js +10 -3
  46. package/dist/diagnosis/index.js.map +1 -1
  47. package/dist/{dspy-rlm-engine-CTIGomgr.js → dspy-rlm-engine-MfpwoEaj.js} +3 -3
  48. package/dist/{dspy-rlm-engine-CTIGomgr.js.map → dspy-rlm-engine-MfpwoEaj.js.map} +1 -1
  49. package/dist/{engine-BkLCnZQX.d.ts → engine-vNiM02Ub.d.ts} +4 -4
  50. package/dist/{engine-BkLCnZQX.d.ts.map → engine-vNiM02Ub.d.ts.map} +1 -1
  51. package/dist/{eval-campaign-CMKRjWl0.js → eval-campaign-CwsBn0Gm.js} +2 -2
  52. package/dist/{eval-campaign-CMKRjWl0.js.map → eval-campaign-CwsBn0Gm.js.map} +1 -1
  53. package/dist/evaluation.d.ts +2 -2
  54. package/dist/{exact-types-CfpP2A4Z.d.ts → exact-types-KGxBWH4b.d.ts} +2 -2
  55. package/dist/{exact-types-CfpP2A4Z.d.ts.map → exact-types-KGxBWH4b.d.ts.map} +1 -1
  56. package/dist/experiment/index.d.ts +1 -1
  57. package/dist/experiment/index.js +2 -1
  58. package/dist/experiment/index.js.map +1 -1
  59. package/dist/{external-optimizer-process-Mc83UoWl.js → external-optimizer-process-xFTliuiK.js} +3 -3
  60. package/dist/{external-optimizer-process-Mc83UoWl.js.map → external-optimizer-process-xFTliuiK.js.map} +1 -1
  61. package/dist/{external-optimizer-subprocess-C0dHXH8e.js → external-optimizer-subprocess-B234V9V0.js} +5 -28
  62. package/dist/external-optimizer-subprocess-B234V9V0.js.map +1 -0
  63. package/dist/{extract-usage-BrQ8mCLX.js → extract-usage-DFATEuWW.js} +2 -2
  64. package/dist/{extract-usage-BrQ8mCLX.js.map → extract-usage-DFATEuWW.js.map} +1 -1
  65. package/dist/{feedback-trajectory-BYjh7NEM.d.ts → feedback-trajectory-BXCGTRkz.d.ts} +3 -3
  66. package/dist/{feedback-trajectory-BYjh7NEM.d.ts.map → feedback-trajectory-BXCGTRkz.d.ts.map} +1 -1
  67. package/dist/hosted/index.d.ts +66 -6
  68. package/dist/hosted/index.d.ts.map +1 -1
  69. package/dist/hosted/index.js +2 -2
  70. package/dist/{index-Ci0-EYzc.d.ts → index-CzfnASj_.d.ts} +18 -11
  71. package/dist/index-CzfnASj_.d.ts.map +1 -0
  72. package/dist/{index-2e_MTznj.d.ts → index-D-TN7ZRM.d.ts} +6 -6
  73. package/dist/{index-2e_MTznj.d.ts.map → index-D-TN7ZRM.d.ts.map} +1 -1
  74. package/dist/{index-BR_R1eBE.d.ts → index-DH-MWH5f.d.ts} +10 -104
  75. package/dist/index-DH-MWH5f.d.ts.map +1 -0
  76. package/dist/{index-BqDJ6fUK.d.ts → index-I4UJGRno.d.ts} +74 -2
  77. package/dist/index-I4UJGRno.d.ts.map +1 -0
  78. package/dist/index.d.ts +17 -18
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +17 -17
  81. package/dist/jev.d.ts +2 -2
  82. package/dist/{journal-CDP0Vhx_.js → journal-c3qY0SDP.js} +246 -5
  83. package/dist/journal-c3qY0SDP.js.map +1 -0
  84. package/dist/{kind-factory-ByZeXDqF.js → kind-factory-CdPPHtGZ.js} +10 -26
  85. package/dist/kind-factory-CdPPHtGZ.js.map +1 -0
  86. package/dist/ledger-core/index.d.ts +2 -2
  87. package/dist/ledger-core/index.js +2 -2
  88. package/dist/{llm-client-BqmRnibA.js → llm-client-KYQBh9C8.js} +2 -2
  89. package/dist/{llm-client-BqmRnibA.js.map → llm-client-KYQBh9C8.js.map} +1 -1
  90. package/dist/{llm-judge-bwbgDMP0.js → llm-judge-NJOHM0iA.js} +11 -1428
  91. package/dist/llm-judge-NJOHM0iA.js.map +1 -0
  92. package/dist/{matrix-CNypzP-v.d.ts → matrix-CgqdFm5N.d.ts} +2 -2
  93. package/dist/{matrix-CNypzP-v.d.ts.map → matrix-CgqdFm5N.d.ts.map} +1 -1
  94. package/dist/multishot/golden/index.d.ts +1 -1
  95. package/dist/multishot/index.d.ts +2 -2
  96. package/dist/openapi.json +1 -1
  97. package/dist/{otel-spans-CQY1pNiN.js → otel-spans-DS7t1t1J.js} +8 -19
  98. package/dist/otel-spans-DS7t1t1J.js.map +1 -0
  99. package/dist/otlp-attributes-D9ptWaIJ.js +53 -0
  100. package/dist/otlp-attributes-D9ptWaIJ.js.map +1 -0
  101. package/dist/pipelines/index.d.ts +1 -1
  102. package/dist/pipelines/index.js +1 -1
  103. package/dist/pipelines/index.js.map +1 -1
  104. package/dist/{prime-protocol-Fwvctmhm.d.ts → prime-protocol-T0i6xcAs.d.ts} +2 -2
  105. package/dist/{prime-protocol-Fwvctmhm.d.ts.map → prime-protocol-T0i6xcAs.d.ts.map} +1 -1
  106. package/dist/{produced-state-zSaGDC_Q.js → produced-state-CY-L7CqS.js} +4 -4
  107. package/dist/{produced-state-zSaGDC_Q.js.map → produced-state-CY-L7CqS.js.map} +1 -1
  108. package/dist/{raw-provider-sink-DIRCZjP_.js → raw-provider-sink-DYh4Bszw.js} +2 -2
  109. package/dist/{raw-provider-sink-DIRCZjP_.js.map → raw-provider-sink-DYh4Bszw.js.map} +1 -1
  110. package/dist/{redact-8fX8-uKr.js → redact-B7rt9Zot.js} +117 -6
  111. package/dist/redact-B7rt9Zot.js.map +1 -0
  112. package/dist/{redact-Du3WKUOP.d.ts → redact-CopuMxll.d.ts} +2 -2
  113. package/dist/{redact-Du3WKUOP.d.ts.map → redact-CopuMxll.d.ts.map} +1 -1
  114. package/dist/{registry-mAQVtuLx.d.ts → registry-Bu3lNole.d.ts} +3 -3
  115. package/dist/{registry-mAQVtuLx.d.ts.map → registry-Bu3lNole.d.ts.map} +1 -1
  116. package/dist/rl.d.ts +1 -1
  117. package/dist/rl.js +2 -2
  118. package/dist/{run-record-DnMFyg_g.js → run-record-tNnlQIrD.js} +2 -10
  119. package/dist/{run-record-DnMFyg_g.js.map → run-record-tNnlQIrD.js.map} +1 -1
  120. package/dist/search-ledger-CQ8Uy4FK.js +1451 -0
  121. package/dist/search-ledger-CQ8Uy4FK.js.map +1 -0
  122. package/dist/search-ledger-file-EvdDZRhv.js +27 -0
  123. package/dist/search-ledger-file-EvdDZRhv.js.map +1 -0
  124. package/dist/search-shipper-C55V7HE3.js +781 -0
  125. package/dist/search-shipper-C55V7HE3.js.map +1 -0
  126. package/dist/{semantic-concept-judge-BY0me-Jq.js → semantic-concept-judge-Bt7bXAAo.js} +6 -6
  127. package/dist/{semantic-concept-judge-BY0me-Jq.js.map → semantic-concept-judge-Bt7bXAAo.js.map} +1 -1
  128. package/dist/{server-DnJCDLf8.js → server-DtetGGoA.js} +2 -2
  129. package/dist/{server-DnJCDLf8.js.map → server-DtetGGoA.js.map} +1 -1
  130. package/dist/{skillopt-optimization-method-CfnQEjgT.js → skillopt-optimization-method-DwO3TOAV.js} +7 -6
  131. package/dist/{skillopt-optimization-method-CfnQEjgT.js.map → skillopt-optimization-method-DwO3TOAV.js.map} +1 -1
  132. package/dist/{spans-D1RftP_w.d.ts → spans-BWtjk_9c.d.ts} +2 -2
  133. package/dist/{spans-D1RftP_w.d.ts.map → spans-BWtjk_9c.d.ts.map} +1 -1
  134. package/dist/{statistical-heldout-CLpjYffJ.d.ts → statistical-heldout-BED3wBtX.d.ts} +2 -2
  135. package/dist/{statistical-heldout-CLpjYffJ.d.ts.map → statistical-heldout-BED3wBtX.d.ts.map} +1 -1
  136. package/dist/{store-otlp-84DH0OEH.js → store-otlp-BPowgPm6.js} +2 -2
  137. package/dist/{store-otlp-84DH0OEH.js.map → store-otlp-BPowgPm6.js.map} +1 -1
  138. package/dist/{store-tool-spans-DSbYpl7f.js → store-tool-spans-BcC_5ef-.js} +6 -6
  139. package/dist/{store-tool-spans-DSbYpl7f.js.map → store-tool-spans-BcC_5ef-.js.map} +1 -1
  140. package/dist/{store-tool-spans-BBXs8hDP.d.ts → store-tool-spans-Cfh9XUCm.d.ts} +5 -9
  141. package/dist/store-tool-spans-Cfh9XUCm.d.ts.map +1 -0
  142. package/dist/{task-failure-attributes-B34TiMBe.js → task-failure-attributes-CEqEfuIY.js} +17 -9
  143. package/dist/task-failure-attributes-CEqEfuIY.js.map +1 -0
  144. package/dist/{tool-groups-W7MJobX_.d.ts → tool-groups-D-mkeN0N.d.ts} +3 -3
  145. package/dist/tool-groups-D-mkeN0N.d.ts.map +1 -0
  146. package/dist/trace-attributes.d.ts +1 -1
  147. package/dist/trace-attributes.js +23 -75
  148. package/dist/trace-attributes.js.map +1 -1
  149. package/dist/trace-repair/index.d.ts +1 -1
  150. package/dist/traces.d.ts +12 -19
  151. package/dist/traces.d.ts.map +1 -1
  152. package/dist/traces.js +18 -18
  153. package/dist/traces.js.map +1 -1
  154. package/dist/{types-BvmWNjjs.d.ts → types-BmQRs661.d.ts} +2 -2
  155. package/dist/{types-BvmWNjjs.d.ts.map → types-BmQRs661.d.ts.map} +1 -1
  156. package/dist/{types-Bay1dh2o.d.ts → types-CeDfCRXp.d.ts} +11 -16
  157. package/dist/types-CeDfCRXp.d.ts.map +1 -0
  158. package/dist/{types-Cvqy7asY.d.ts → types-ClK-sHs8.d.ts} +2 -2
  159. package/dist/{types-Cvqy7asY.d.ts.map → types-ClK-sHs8.d.ts.map} +1 -1
  160. package/dist/wire/index.d.ts +1 -1
  161. package/dist/wire/index.js +1 -1
  162. package/docs/hosted-ingest-spec.md +92 -133
  163. package/docs/public-api.md +58 -43
  164. package/docs/search-ledger.md +17 -0
  165. package/package.json +2 -2
  166. package/dist/analyze-runs-BvK4-wSs.d.ts +0 -75
  167. package/dist/analyze-runs-BvK4-wSs.d.ts.map +0 -1
  168. package/dist/attribute-vocabulary-DLJ6303h.d.ts.map +0 -1
  169. package/dist/benchmark-command-TZlsuAh9.js.map +0 -1
  170. package/dist/campaign-evidence-CWF8pEIk.js.map +0 -1
  171. package/dist/client-BhEyAdfe.d.ts +0 -202
  172. package/dist/client-BhEyAdfe.d.ts.map +0 -1
  173. package/dist/client-QwJpsNYU.js +0 -655
  174. package/dist/client-QwJpsNYU.js.map +0 -1
  175. package/dist/define-agent-eval-BWeyIpny.d.ts.map +0 -1
  176. package/dist/define-agent-eval-DrGfrCTZ.js.map +0 -1
  177. package/dist/external-optimizer-subprocess-C0dHXH8e.js.map +0 -1
  178. package/dist/index-BR_R1eBE.d.ts.map +0 -1
  179. package/dist/index-BqDJ6fUK.d.ts.map +0 -1
  180. package/dist/index-Ci0-EYzc.d.ts.map +0 -1
  181. package/dist/insight-report-CvPkEIcC.d.ts.map +0 -1
  182. package/dist/journal-CDP0Vhx_.js.map +0 -1
  183. package/dist/kind-factory-ByZeXDqF.js.map +0 -1
  184. package/dist/llm-judge-bwbgDMP0.js.map +0 -1
  185. package/dist/otel-spans-CQY1pNiN.js.map +0 -1
  186. package/dist/otlp-attributes-BpC_blLF.js +0 -83
  187. package/dist/otlp-attributes-BpC_blLF.js.map +0 -1
  188. package/dist/redact-8fX8-uKr.js.map +0 -1
  189. package/dist/store-tool-spans-BBXs8hDP.d.ts.map +0 -1
  190. package/dist/task-failure-attributes-B34TiMBe.js.map +0 -1
  191. package/dist/tool-groups-W7MJobX_.d.ts.map +0 -1
  192. package/dist/types-Bay1dh2o.d.ts.map +0 -1
@@ -5,17 +5,18 @@ import { t as decidePairedPromotion } from "./paired-promotion-decision-6cn3bLc3
5
5
  import { a as heldoutSignificance, i as dimensionRegressions, o as pairHoldout } from "./statistical-heldout-GcLIPxk4.js";
6
6
  import { i as modelHasSnapshot, l as searchCellRunId } from "./run-record-BRlM99rX.js";
7
7
  import { n as contentHash } from "./verdict-cache-BQEsVy9n.js";
8
- import { o as projectCampaignCellQuality, t as campaignCellCostProvenance } from "./run-record-DnMFyg_g.js";
8
+ import { r as projectCampaignCellQuality, t as campaignCellCostProvenance } from "./run-record-tNnlQIrD.js";
9
9
  import { i as CostLedger, t as CostAccountingIncompleteError } from "./cost-ledger-_IbkejCF.js";
10
- import { A as FinalEvidenceConflictError, B as surfaceContentHash, C as campaignMeanCompositeOrNull, F as summarizeEvaluationUnits, H as surfaceHash, J as assertCampaignSplitIdentity, N as defineEvaluationClaim, P as evaluationClaimSchema, Q as campaignSplitDigest, S as campaignMeanComposite, U as surfaceHashMatches, V as surfaceDispatchRef, W as BackendIntegrityError, X as campaignCoverage, Y as assertCompleteCampaign, Z as campaignScenarioIdentity, b as assertFiniteRankKey, et as formatCoverageFailures, j as FinalEvidenceError, q as assertCampaignDesign, t as createCampaignEvidenceReceipt, w as compareRankKeys, x as campaignBreakdown, z as renderSurfaceDiff } from "./campaign-evidence-CWF8pEIk.js";
11
- import { d as mapConcurrent, n as replayLedgerText, t as FileLedgerJournal } from "./journal-CDP0Vhx_.js";
10
+ import { A as FinalEvidenceConflictError, B as surfaceHashMatches, C as campaignMeanCompositeOrNull, G as assertCampaignSplitIdentity, I as renderSurfaceDiff, J as campaignScenarioIdentity, K as assertCompleteCampaign, L as surfaceContentHash, R as surfaceDispatchRef, S as campaignMeanComposite, V as BackendIntegrityError, W as assertCampaignDesign, Y as campaignSplitDigest, Z as formatCoverageFailures, b as assertFiniteRankKey, j as FinalEvidenceError, q as campaignCoverage, t as createCampaignEvidenceReceipt, w as compareRankKeys, x as campaignBreakdown, z as surfaceHash } from "./campaign-evidence-BqjlTM3P.js";
11
+ import { p as mapConcurrent } from "./journal-c3qY0SDP.js";
12
12
  import { t as deepFreezeCanonicalJson } from "./deep-freeze-CurcOQg3.js";
13
- import "./ledger-core/index.js";
14
- import { D as SearchLedgerIntegrityError, E as SearchLedgerError, S as fsCampaignStorage, T as SearchLedgerConflictError, g as isRecord, h as isExternalTextCandidate, w as SEARCH_LEDGER_FILE_CONTEXT, x as createRunCostLedger } from "./external-optimizer-subprocess-C0dHXH8e.js";
15
- import { f as redactText, n as REDACTION_VERSION, o as detectCredential, s as detectPersonalData } from "./redact-8fX8-uKr.js";
13
+ import { S as fsCampaignStorage, g as isRecord, h as isExternalTextCandidate, x as createRunCostLedger } from "./external-optimizer-subprocess-B234V9V0.js";
14
+ import { r as summarizeEvaluationUnits, t as defineEvaluationClaim } from "./claim-V9Zqbq0J.js";
15
+ import { f as redactText, n as REDACTION_VERSION, o as detectCredential, s as detectPersonalData } from "./redact-B7rt9Zot.js";
16
16
  import { t as detectRewardHacking } from "./reward-hacking-D0XwhVWE.js";
17
17
  import { n as assertProposalFindings, t as combineAbortSignals } from "./abort-signal-CtzAM_sJ.js";
18
- import { d as stripFencedJson, o as costReceiptFromLlm, s as costReceiptFromLlmError, u as maximumChargeForLlmRequest } from "./llm-client-BqmRnibA.js";
18
+ import { a as validateSearchLedgerEvent, c as searchCellId, i as replaySearchLedgerText, l as searchNodeId, u as searchTaskSetDigest } from "./search-ledger-CQ8Uy4FK.js";
19
+ import { d as stripFencedJson, o as costReceiptFromLlm, s as costReceiptFromLlmError, u as maximumChargeForLlmRequest } from "./llm-client-KYQBh9C8.js";
19
20
  import { createHash } from "node:crypto";
20
21
  import { writeFileSync } from "node:fs";
21
22
  import { z } from "zod";
@@ -2547,1424 +2548,6 @@ function labelTrustRank(trust) {
2547
2548
  return LABEL_TRUST_RANK[trust ?? "unverified"];
2548
2549
  }
2549
2550
  //#endregion
2550
- //#region src/campaign/search-ledger-ordering.ts
2551
- function artifactKey(artifact) {
2552
- return canonicalString(artifact);
2553
- }
2554
- function compareStrings(a, b) {
2555
- return a < b ? -1 : a > b ? 1 : 0;
2556
- }
2557
- //#endregion
2558
- //#region src/campaign/search-ledger-types.ts
2559
- /**
2560
- * Schema tag every search-ledger entry carries. A ledger written under another
2561
- * tag, such as the retired `tangle.search-ledger.v1` candidate-slot format, is
2562
- * refused with its tag named; it is never translated.
2563
- */
2564
- const SEARCH_LEDGER_SCHEMA = "tangle.search-ledger.2026-09";
2565
- //#endregion
2566
- //#region src/campaign/search-state.ts
2567
- /**
2568
- * `SearchState`: the one projection of a search ledger.
2569
- *
2570
- * The same code checks every invariant for the producer's journal, the kernel,
2571
- * and the Intelligence verifier, and builds the read model they share. It keeps
2572
- * compact indexes (nodes, edges, cells, per-unit score sums, running audit
2573
- * totals), not the raw event list, and applies each entry in time proportional
2574
- * to that entry, so a search of any length appends at a constant cost.
2575
- *
2576
- * The journal asks for a snapshot after every append. A snapshot is a
2577
- * `SearchStateView` that reads the live indexes, so taking one costs nothing.
2578
- * The view is valid until the state applies its next entry; a read after that
2579
- * throws rather than returning numbers from a later ledger position. Read the
2580
- * ledger's state again to see newer entries. The audit, header, head and claim
2581
- * on a view are plain values and stay readable.
2582
- */
2583
- /** Deterministic node id: identical content in one search is one node. */
2584
- function searchNodeId(searchId, artifactDigest) {
2585
- return `node_${shortDigest([searchId, artifactDigest])}`;
2586
- }
2587
- /** Deterministic cell id: one node on one task in one split at one repeat. */
2588
- function searchCellId(searchId, nodeId, taskId, split, rep) {
2589
- return `cell_${shortDigest([
2590
- searchId,
2591
- nodeId,
2592
- taskId,
2593
- split,
2594
- rep
2595
- ])}`;
2596
- }
2597
- /** Digest a split's task list in taskId order. */
2598
- function searchTaskSetDigest(tasks) {
2599
- return hashCanonical([...tasks].sort((left, right) => compareCodeUnits(left.taskId, right.taskId)));
2600
- }
2601
- /** 128 bits of SHA-256 over the canonical encoding: collision-safe and short
2602
- * enough for directory names. */
2603
- function shortDigest(value) {
2604
- return createHash("sha256").update(canonicalString(value)).digest("hex").slice(0, 32);
2605
- }
2606
- const MAX_LABEL_CHARS$1 = 200;
2607
- const USD_TOLERANCE = 1e-9;
2608
- const SPLITS = [
2609
- "train",
2610
- "selection",
2611
- "test"
2612
- ];
2613
- /**
2614
- * Per-unit means of scored cells, in unitId order. Each unit sums its cells in
2615
- * cellId order, so the result depends on the set of cells alone, never on the
2616
- * order they settled in: a verifier that reads the same cells from a database
2617
- * gets the same bits.
2618
- */
2619
- function searchUnitScores(cells) {
2620
- const byUnit = /* @__PURE__ */ new Map();
2621
- for (const cell of cells) {
2622
- const unit = byUnit.get(cell.unitId);
2623
- if (unit) unit.push(cell);
2624
- else byUnit.set(cell.unitId, [cell]);
2625
- }
2626
- return [...byUnit.entries()].sort(([left], [right]) => compareCodeUnits(left, right)).map(([unitId, unitCells]) => {
2627
- let sum = 0;
2628
- for (const cell of unitCells.sort((left, right) => compareCodeUnits(left.cellId, right.cellId))) sum += cell.score;
2629
- return {
2630
- unitId,
2631
- sum,
2632
- count: unitCells.length,
2633
- mean: sum / unitCells.length
2634
- };
2635
- });
2636
- }
2637
- /**
2638
- * The pure, incremental projection of one search ledger. `apply` refuses any
2639
- * entry that breaks an invariant; the journal then discards this instance and
2640
- * replays into a new one, so a refused entry leaves no partial state behind.
2641
- */
2642
- var SearchState = class {
2643
- searchId;
2644
- version = 0;
2645
- header = null;
2646
- closed = null;
2647
- head = null;
2648
- lastOccurredAt = Number.NEGATIVE_INFINITY;
2649
- lastOccurredAtText = null;
2650
- tasks = /* @__PURE__ */ new Map();
2651
- nodes = /* @__PURE__ */ new Map();
2652
- nodeOrder = [];
2653
- nodeByDigest = /* @__PURE__ */ new Map();
2654
- edges = /* @__PURE__ */ new Map();
2655
- edgeOrder = [];
2656
- cells = /* @__PURE__ */ new Map();
2657
- operations = /* @__PURE__ */ new Map();
2658
- selectedNodeId = null;
2659
- claimUsedUsd = 0;
2660
- audit;
2661
- constructor(searchId) {
2662
- this.searchId = searchId;
2663
- this.audit = {
2664
- searchId,
2665
- eventCount: 0,
2666
- headHash: null,
2667
- status: "open",
2668
- closeReason: null,
2669
- nodes: 0,
2670
- nodesWithoutEdge: 0,
2671
- undecidedNodes: 0,
2672
- selectedNodeId: null,
2673
- edges: {
2674
- explicit: 0,
2675
- correlated: 0,
2676
- unknown: 0,
2677
- reproposals: 0
2678
- },
2679
- cells: {
2680
- allocated: 0,
2681
- settled: 0,
2682
- cancelled: 0,
2683
- open: 0
2684
- },
2685
- attempts: 0,
2686
- outcomes: {
2687
- passed: 0,
2688
- failed: 0,
2689
- errored: 0
2690
- },
2691
- operations: {
2692
- started: 0,
2693
- recorded: 0,
2694
- open: 0
2695
- },
2696
- spend: {
2697
- knownUsd: 0,
2698
- floorUsd: 0,
2699
- unknownCostCells: 0,
2700
- unknownCostOperations: 0,
2701
- committedUsd: 0,
2702
- openReservationUsd: 0,
2703
- overspendUsd: 0,
2704
- unreservedCells: 0,
2705
- boxMinutes: 0
2706
- },
2707
- tokens: {
2708
- inputTokens: 0,
2709
- outputTokens: 0,
2710
- cachedTokens: 0,
2711
- unknownTokenAttempts: 0
2712
- }
2713
- };
2714
- }
2715
- apply(entry, index) {
2716
- const event = entry.event;
2717
- if (this.closed) throw integrity(`event ${event.eventId} follows search-closed ${this.closed.eventId}`);
2718
- const occurredAt = Date.parse(event.occurredAt);
2719
- if (occurredAt < this.lastOccurredAt) throw integrity(`event ${event.eventId} occurred before the preceding event`);
2720
- assertUnique(event.artifacts.map(artifactKey), "artifact receipt", event.eventId);
2721
- if (event.kind === "search-opened") {
2722
- if (index !== 0 || this.header) throw integrity("search-opened must be the first and only opening event");
2723
- this.open(event);
2724
- } else {
2725
- if (!this.header) throw integrity(`event ${event.eventId} appears before search-opened`);
2726
- this.applyEvent(event, index);
2727
- }
2728
- this.lastOccurredAt = occurredAt;
2729
- this.lastOccurredAtText = event.occurredAt;
2730
- this.head = {
2731
- sequence: index,
2732
- entryHash: entry.entryHash
2733
- };
2734
- this.audit.eventCount = index + 1;
2735
- this.audit.headHash = entry.entryHash;
2736
- this.version += 1;
2737
- }
2738
- snapshot() {
2739
- return new SearchStateView(this, this.version);
2740
- }
2741
- /** @internal Views check this before every read of the live indexes. */
2742
- isAt(version) {
2743
- return this.version === version;
2744
- }
2745
- applyEvent(event, index) {
2746
- switch (event.kind) {
2747
- case "operation-started":
2748
- this.startOperation(event);
2749
- return;
2750
- case "operation-recorded":
2751
- this.recordOperation(event);
2752
- return;
2753
- case "node-registered":
2754
- this.registerNode(event, index);
2755
- return;
2756
- case "edge-recorded":
2757
- this.recordEdge(event, index);
2758
- return;
2759
- case "cell-allocated":
2760
- this.allocateCell(event, index);
2761
- return;
2762
- case "cell-settled":
2763
- this.settleCell(event, index);
2764
- return;
2765
- case "cell-cancelled":
2766
- this.cancelCell(event, index);
2767
- return;
2768
- case "node-decided":
2769
- this.decideNode(event, index);
2770
- return;
2771
- case "search-closed":
2772
- this.close(event);
2773
- return;
2774
- }
2775
- }
2776
- open(event) {
2777
- if (event.containment?.searchId === this.searchId) throw integrity("a search cannot contain itself");
2778
- if (event.derivedFrom?.searchId === this.searchId) throw integrity("a search cannot derive from itself");
2779
- const units = {
2780
- train: /* @__PURE__ */ new Set(),
2781
- selection: /* @__PURE__ */ new Set(),
2782
- test: /* @__PURE__ */ new Set()
2783
- };
2784
- for (const split of SPLITS) {
2785
- const { tasks, taskSetDigest } = event.splits[split];
2786
- if (searchTaskSetDigest(tasks) !== taskSetDigest) throw integrity(`the ${split} split's taskSetDigest does not match its tasks`);
2787
- for (const task of tasks) {
2788
- const owner = this.tasks.get(task.taskId);
2789
- if (owner) throw integrity(`task ${task.taskId} is in both the ${owner.split} and ${split} splits`);
2790
- this.tasks.set(task.taskId, {
2791
- split,
2792
- unitId: task.unitId
2793
- });
2794
- units[split].add(task.unitId);
2795
- }
2796
- }
2797
- if (event.splits.heldOutUnits) {
2798
- const seen = [...units.test].filter((unit) => units.train.has(unit) || units.selection.has(unit));
2799
- if (seen.length > 0) throw integrity(`test units ${seen.join(", ")} also appear in train or selection, but the splits declare heldOutUnits`);
2800
- }
2801
- const { budget } = event;
2802
- if (budget.maxUsd !== null && budget.reservedClaimUsd > budget.maxUsd + USD_TOLERANCE) throw integrity(`the claim reserve $${budget.reservedClaimUsd} exceeds the search cap $${budget.maxUsd}`);
2803
- this.header = event;
2804
- }
2805
- startOperation(event) {
2806
- if (this.operations.has(event.operationId)) throw integrity(`operation ${event.operationId} was started twice`);
2807
- this.admit(event.reservation, false, `operation ${event.operationId}`);
2808
- this.operations.set(event.operationId, {
2809
- operationId: event.operationId,
2810
- operationKind: event.operationKind,
2811
- reservation: event.reservation,
2812
- recorded: false,
2813
- spentUsd: 0
2814
- });
2815
- this.audit.operations.started += 1;
2816
- this.audit.operations.open += 1;
2817
- this.audit.spend.openReservationUsd += event.reservation?.usd ?? 0;
2818
- }
2819
- recordOperation(event) {
2820
- const operation = this.operations.get(event.operationId);
2821
- if (!operation) throw integrity(`operation ${event.operationId} was recorded before it started`);
2822
- if (operation.recorded) throw integrity(`operation ${event.operationId} was recorded twice`);
2823
- if (operation.operationKind !== event.operationKind) throw integrity(`operation ${event.operationId} started as ${operation.operationKind} but recorded as ${event.operationKind}`);
2824
- const cost = this.book(event.accounting);
2825
- if (cost.unknown) this.audit.spend.unknownCostOperations += 1;
2826
- const reserved = operation.reservation?.usd ?? 0;
2827
- this.audit.spend.openReservationUsd -= reserved;
2828
- if (operation.reservation) this.audit.spend.overspendUsd += Math.max(0, cost.usd - reserved);
2829
- operation.recorded = true;
2830
- operation.spentUsd = cost.usd;
2831
- this.audit.operations.recorded += 1;
2832
- this.audit.operations.open -= 1;
2833
- }
2834
- registerNode(event, index) {
2835
- const expected = searchNodeId(this.searchId, event.artifactDigest);
2836
- if (event.nodeId !== expected) throw integrity(`node ${event.nodeId} does not match its artifact digest (expected ${expected})`);
2837
- if (this.nodes.has(event.nodeId)) throw integrity(`node ${event.nodeId} was registered twice; a re-proposal is a second edge into it`);
2838
- assertUnique(event.surfaces.map((surface) => surface.surfaceId), "surfaceId", event.eventId);
2839
- const maxNodes = this.header.budget.maxNodes;
2840
- if (maxNodes !== null && this.nodes.size + 1 > maxNodes) throw integrity(`node ${event.nodeId} exceeds the search's maxNodes ${maxNodes}`);
2841
- this.nodes.set(event.nodeId, {
2842
- event,
2843
- ordinal: this.nodeOrder.length,
2844
- registeredSequence: index,
2845
- updatedSequence: index,
2846
- edgeIds: [],
2847
- parents: [],
2848
- parentKeys: /* @__PURE__ */ new Set(),
2849
- primaryParentId: null,
2850
- depth: null,
2851
- children: [],
2852
- decisions: [],
2853
- finalist: false,
2854
- cellIds: [],
2855
- scoredCells: 0,
2856
- spend: {
2857
- knownUsd: 0,
2858
- floorUsd: 0,
2859
- unknownCostCells: 0,
2860
- boxMinutes: 0
2861
- }
2862
- });
2863
- this.nodeOrder.push(event.nodeId);
2864
- this.nodeByDigest.set(event.artifactDigest, event.nodeId);
2865
- this.audit.nodes += 1;
2866
- this.audit.nodesWithoutEdge += 1;
2867
- this.audit.undecidedNodes += 1;
2868
- }
2869
- recordEdge(event, index) {
2870
- if (this.edges.has(event.edgeId)) throw integrity(`edge ${event.edgeId} was recorded twice`);
2871
- const child = this.nodes.get(event.childNodeId);
2872
- if (!child) throw integrity(`edge ${event.edgeId} names unregistered child ${event.childNodeId}`);
2873
- if (event.label.length > MAX_LABEL_CHARS$1) throw integrity(`edge ${event.edgeId} label exceeds ${MAX_LABEL_CHARS$1} characters`);
2874
- if (event.diffs.length !== event.parents.length) throw integrity(`edge ${event.edgeId} needs one diff per parent`);
2875
- assertUnique(event.parents.map((parent) => canonicalString(parent)), "parent", event.eventId);
2876
- const { operator, attribution, parents } = event;
2877
- if (operator === "seed" !== (event.proposer === null)) throw integrity(`edge ${event.edgeId}: exactly the seed edge has no proposer`);
2878
- if (operator === "seed" && (parents.length > 0 || attribution === "unknown")) throw integrity(`seed edge ${event.edgeId} must have no parents and a known attribution`);
2879
- if (attribution === "unknown" && parents.length > 0) throw integrity(`edge ${event.edgeId} has unknown attribution but names parents`);
2880
- if (operator !== "seed" && attribution !== "unknown" && parents.length === 0) throw integrity(`${operator} edge ${event.edgeId} names no parent`);
2881
- if (operator === "merge" && attribution !== "unknown" && parents.length < 2) throw integrity(`merge edge ${event.edgeId} needs at least two parents`);
2882
- const operationId = event.proposer?.operationId ?? null;
2883
- if (operationId !== null && !this.operations.has(operationId)) throw integrity(`edge ${event.edgeId} names operation ${operationId}, which never started`);
2884
- const inSearch = [];
2885
- for (const parent of parents) {
2886
- if (parent.searchId !== this.searchId) {
2887
- const from = this.header.derivedFrom;
2888
- if (operator !== "derive" || parents.length !== 1 || !from || from.searchId !== parent.searchId || from.nodeId !== parent.nodeId) throw integrity(`edge ${event.edgeId} names a parent in search ${parent.searchId}; only a derive edge matching derivedFrom may`);
2889
- continue;
2890
- }
2891
- if (operator === "derive") throw integrity(`derive edge ${event.edgeId} must name the parent in derivedFrom`);
2892
- const record = this.nodes.get(parent.nodeId);
2893
- if (!record) throw integrity(`edge ${event.edgeId} names unregistered parent ${parent.nodeId}`);
2894
- if (record.ordinal >= child.ordinal) throw integrity(`edge ${event.edgeId}: parent ${parent.nodeId} registered after child ${child.event.nodeId}`);
2895
- if (record.edgeIds.length === 0) throw integrity(`edge ${event.edgeId}: parent ${parent.nodeId} has no edge of its own yet`);
2896
- inSearch.push(record);
2897
- }
2898
- if (child.edgeIds.length === 0) {
2899
- const primary = inSearch[0];
2900
- child.primaryParentId = primary?.event.nodeId ?? null;
2901
- child.depth = operator === "seed" || operator === "derive" ? 0 : primary && primary.depth !== null ? primary.depth + 1 : null;
2902
- this.audit.nodesWithoutEdge -= 1;
2903
- } else this.audit.edges.reproposals += 1;
2904
- child.edgeIds.push(event.edgeId);
2905
- for (const parent of parents) {
2906
- const key = canonicalString(parent);
2907
- if (child.parentKeys.has(key)) continue;
2908
- child.parentKeys.add(key);
2909
- child.parents.push(parent);
2910
- }
2911
- for (const parent of inSearch) if (!parent.children.includes(child.event.nodeId)) parent.children.push(child.event.nodeId);
2912
- child.updatedSequence = index;
2913
- this.edges.set(event.edgeId, event);
2914
- this.edgeOrder.push(event.edgeId);
2915
- this.audit.edges[attribution] += 1;
2916
- }
2917
- allocateCell(event, index) {
2918
- const expected = searchCellId(this.searchId, event.nodeId, event.taskId, event.split, event.rep);
2919
- if (event.cellId !== expected) throw integrity(`cell ${event.cellId} does not match its coordinates (expected ${expected})`);
2920
- if (this.cells.has(event.cellId)) throw integrity(`cell ${event.cellId} was allocated twice`);
2921
- const node = this.nodes.get(event.nodeId);
2922
- if (!node) throw integrity(`cell ${event.cellId} names unregistered node ${event.nodeId}`);
2923
- if (node.edgeIds.length === 0) throw integrity(`cell ${event.cellId}: node ${event.nodeId} has no edge yet`);
2924
- const task = this.tasks.get(event.taskId);
2925
- if (!task || task.split !== event.split) throw integrity(`cell ${event.cellId}: task ${event.taskId} is not in the ${event.split} split`);
2926
- if (task.unitId !== event.unitId) throw integrity(`cell ${event.cellId}: task ${event.taskId} samples unit ${task.unitId}`);
2927
- assertStageSplit(event.cellId, event.stage, event.split, node.ordinal === 0);
2928
- if (event.split === "test" && node.ordinal !== 0 && !node.finalist) throw integrity(`cell ${event.cellId}: the test split is sealed; only the root and finalists run on it`);
2929
- const maxCells = this.header.budget.maxCells;
2930
- if (maxCells !== null && this.audit.cells.allocated + 1 > maxCells) throw integrity(`cell ${event.cellId} exceeds the search's maxCells ${maxCells}`);
2931
- this.admit(event.reservation, event.stage === "claim", `cell ${event.cellId}`);
2932
- this.cells.set(event.cellId, {
2933
- cellId: event.cellId,
2934
- nodeId: event.nodeId,
2935
- taskId: event.taskId,
2936
- unitId: event.unitId,
2937
- split: event.split,
2938
- rep: event.rep,
2939
- stage: event.stage,
2940
- lane: event.lane,
2941
- reservation: event.reservation,
2942
- attempts: 0,
2943
- lastRunId: null,
2944
- outcome: null,
2945
- score: null,
2946
- final: false,
2947
- cancelled: null,
2948
- spentUsd: 0,
2949
- costKnown: true,
2950
- traceId: null,
2951
- allocatedSequence: index,
2952
- updatedSequence: index
2953
- });
2954
- node.cellIds.push(event.cellId);
2955
- node.updatedSequence = index;
2956
- this.audit.cells.allocated += 1;
2957
- this.audit.cells.open += 1;
2958
- this.audit.spend.openReservationUsd += event.reservation?.usd ?? 0;
2959
- if (event.stage === "claim") this.claimUsedUsd += event.reservation?.usd ?? 0;
2960
- }
2961
- settleCell(event, index) {
2962
- const cell = this.cells.get(event.cellId);
2963
- if (!cell) throw integrity(`attempt ${event.eventId} names unallocated cell ${event.cellId}`);
2964
- if (cell.cancelled) throw integrity(`cell ${event.cellId} was settled after it was cancelled`);
2965
- if (cell.final) throw integrity(`cell ${event.cellId} was attempted again after a final ${cell.outcome} outcome; only a retryable error admits another attempt`);
2966
- if (event.attempt !== cell.attempts + 1) throw integrity(`cell ${event.cellId} attempt ${event.attempt} is not contiguous (expected ${cell.attempts + 1})`);
2967
- const runId = searchCellRunId({
2968
- cellId: event.cellId,
2969
- attempt: event.attempt
2970
- });
2971
- if (event.runId !== runId) throw integrity(`cell ${event.cellId} attempt ${event.attempt} must have runId ${runId}`);
2972
- const node = this.nodes.get(cell.nodeId);
2973
- const declared = new Set(node.event.surfaces.map((surface) => surface.surfaceId));
2974
- assertUnique(event.surfaceEvidence.map((evidence) => evidence.surfaceId), "surface evidence", event.eventId);
2975
- for (const evidence of event.surfaceEvidence) if (!declared.has(evidence.surfaceId)) throw integrity(`attempt ${event.eventId} reports surface ${evidence.surfaceId}, which node ${cell.nodeId} does not declare`);
2976
- if (event.artifacts.filter((artifact) => artifact.role === "run-record").length > 1) throw integrity(`attempt ${event.eventId} binds more than one RunRecord`);
2977
- const before = this.reservationParts(cell);
2978
- const cost = this.book(event.accounting);
2979
- if (cell.attempts === 0) {
2980
- this.audit.cells.settled += 1;
2981
- this.audit.cells.open -= 1;
2982
- if (cell.reservation === null) this.audit.spend.unreservedCells += 1;
2983
- }
2984
- if (cost.unknown && cell.costKnown) {
2985
- cell.costKnown = false;
2986
- this.audit.spend.unknownCostCells += 1;
2987
- node.spend.unknownCostCells += 1;
2988
- }
2989
- cell.attempts = event.attempt;
2990
- cell.lastRunId = runId;
2991
- cell.outcome = event.outcome.status;
2992
- cell.spentUsd += cost.usd;
2993
- cell.updatedSequence = index;
2994
- if ("traceId" in event.traceRef) cell.traceId = event.traceRef.traceId;
2995
- if (event.outcome.status === "errored") cell.final = !event.outcome.error.retryable;
2996
- else {
2997
- cell.final = true;
2998
- cell.score = event.outcome.score;
2999
- node.scoredCells += 1;
3000
- }
3001
- const after = this.reservationParts(cell);
3002
- this.audit.spend.openReservationUsd += after.open - before.open;
3003
- this.audit.spend.overspendUsd += after.over - before.over;
3004
- if (cell.stage === "claim") this.claimUsedUsd += after.used - before.used;
3005
- if (cost.unknown) node.spend.floorUsd += cost.usd;
3006
- else node.spend.knownUsd += cost.usd;
3007
- const boxMinutes = event.boxMinutes ?? 0;
3008
- node.spend.boxMinutes += boxMinutes;
3009
- this.audit.spend.boxMinutes += boxMinutes;
3010
- node.updatedSequence = index;
3011
- this.audit.attempts += 1;
3012
- this.audit.outcomes[event.outcome.status] += 1;
3013
- }
3014
- cancelCell(event, index) {
3015
- const cell = this.cells.get(event.cellId);
3016
- if (!cell) throw integrity(`cancellation ${event.eventId} names unallocated cell ${event.cellId}`);
3017
- if (cell.cancelled) throw integrity(`cell ${event.cellId} was cancelled twice`);
3018
- if (cell.final) throw integrity(`cell ${event.cellId} was cancelled after a final outcome`);
3019
- const before = this.reservationParts(cell);
3020
- cell.cancelled = event.reason;
3021
- cell.updatedSequence = index;
3022
- const after = this.reservationParts(cell);
3023
- this.audit.spend.openReservationUsd += after.open - before.open;
3024
- this.audit.spend.overspendUsd += after.over - before.over;
3025
- if (cell.stage === "claim") this.claimUsedUsd += after.used - before.used;
3026
- if (cell.attempts === 0) {
3027
- this.audit.cells.cancelled += 1;
3028
- this.audit.cells.open -= 1;
3029
- }
3030
- this.nodes.get(cell.nodeId).updatedSequence = index;
3031
- }
3032
- decideNode(event, index) {
3033
- const node = this.nodes.get(event.nodeId);
3034
- if (!node) throw integrity(`decision ${event.eventId} names unregistered node ${event.nodeId}`);
3035
- if (node.edgeIds.length === 0) throw integrity(`decision ${event.eventId}: node ${event.nodeId} has no edge yet`);
3036
- const status = event.decision.status;
3037
- if (status === "selected") {
3038
- if (this.selectedNodeId !== null && this.selectedNodeId !== event.nodeId) throw integrity(`node ${event.nodeId} was selected while ${this.selectedNodeId} is still selected`);
3039
- if (node.scoredCells === 0) throw integrity(`node ${event.nodeId} cannot be selected without a scored cell`);
3040
- }
3041
- const previous = node.decisions.at(-1)?.decision.status ?? null;
3042
- const wasUndecided = previous === null || previous === "advanced";
3043
- const isUndecided = status === "advanced";
3044
- this.audit.undecidedNodes += (isUndecided ? 1 : 0) - (wasUndecided ? 1 : 0);
3045
- if (previous === "selected" && status !== "selected") this.selectedNodeId = null;
3046
- if (status === "selected") this.selectedNodeId = event.nodeId;
3047
- if (status === "finalist") node.finalist = true;
3048
- node.decisions.push({
3049
- sequence: index,
3050
- decision: event.decision,
3051
- basis: event.basis,
3052
- rule: event.rule,
3053
- reason: event.reason
3054
- });
3055
- node.updatedSequence = index;
3056
- this.audit.selectedNodeId = this.selectedNodeId;
3057
- }
3058
- close(event) {
3059
- const reasons = this.incompleteReasons();
3060
- if (reasons.length > 0) throw integrity(`search-closed while incomplete: ${reasons.join("; ")}`);
3061
- if (event.claim) this.checkClaim(event.claim);
3062
- this.closed = event;
3063
- this.audit.status = "closed";
3064
- this.audit.closeReason = event.reason;
3065
- this.audit.spend.openReservationUsd = 0;
3066
- }
3067
- checkClaim(claim) {
3068
- if (claim.finalists.length > 3) throw integrity(`the claim names ${claim.finalists.length} finalists; at most 3 are allowed`);
3069
- assertUnique(claim.finalists.map((finalist) => finalist.nodeId), "claim finalist", "search-closed");
3070
- for (const finalist of claim.finalists) if (!this.nodes.get(finalist.nodeId)?.finalist) throw integrity(`claim finalist ${finalist.nodeId} was never decided finalist`);
3071
- if (claim.selected !== this.selectedNodeId) throw integrity(`the claim selects ${claim.selected ?? "nothing"} but the selected node is ${this.selectedNodeId ?? "none"}`);
3072
- const root = this.nodeOrder[0] ?? null;
3073
- if (claim.decision === "ship") {
3074
- const shipped = claim.finalists.find((finalist) => finalist.nodeId === claim.selected);
3075
- if (claim.selected === null || claim.selected === root || !shipped?.promote) throw integrity("a ship claim must select a finalist that the paired test promoted");
3076
- if (!this.header.splits.heldOutUnits) throw integrity("a ship claim needs test units held out from train and selection");
3077
- } else if (claim.selected !== null && claim.selected !== root) throw integrity(`a ${claim.decision} claim keeps the root; it cannot select another node`);
3078
- if (claim.decision === "test-cannot-resolve") {
3079
- for (const cell of this.cells.values()) if (cell.split === "test" && cell.attempts > 0) throw integrity("a test-cannot-resolve claim spends nothing on test cells");
3080
- }
3081
- }
3082
- /** @internal */
3083
- incompleteReasons() {
3084
- const reasons = [];
3085
- if (!this.header) reasons.push("search-opened is missing");
3086
- if (this.audit.cells.open > 0) reasons.push(count(this.audit.cells.open, "cell", "has no outcome"));
3087
- if (this.audit.operations.open > 0) reasons.push(count(this.audit.operations.open, "operation", "is unrecorded"));
3088
- if (this.audit.nodesWithoutEdge > 0) reasons.push(count(this.audit.nodesWithoutEdge, "node", "has no edge"));
3089
- if (this.audit.undecidedNodes > 0) reasons.push(count(this.audit.undecidedNodes, "node", "has no terminal decision"));
3090
- return reasons;
3091
- }
3092
- /** Book an attempt's or operation's accounting into the running totals. An
3093
- * unknown cost counts as its proven floor. */
3094
- book(accounting) {
3095
- const { tokens, cost } = accounting;
3096
- if (tokens.status === "known") {
3097
- this.audit.tokens.inputTokens += tokens.inputTokens;
3098
- this.audit.tokens.outputTokens += tokens.outputTokens;
3099
- this.audit.tokens.cachedTokens += tokens.cachedTokens;
3100
- } else this.audit.tokens.unknownTokenAttempts += 1;
3101
- const usd = cost.status === "known" ? cost.usd : cost.knownLowerBoundUsd;
3102
- if (cost.status === "known") this.audit.spend.knownUsd += usd;
3103
- else this.audit.spend.floorUsd += usd;
3104
- this.audit.spend.committedUsd += usd;
3105
- return {
3106
- usd,
3107
- unknown: cost.status === "unknown"
3108
- };
3109
- }
3110
- /** A cell's share of the open reservations, its overspend, and what it draws
3111
- * from the claim reserve: the larger of its hold and its spend. */
3112
- reservationParts(cell) {
3113
- const reserved = cell.reservation?.usd ?? 0;
3114
- const holding = !cell.final && cell.cancelled === null;
3115
- return {
3116
- open: holding ? Math.max(0, reserved - cell.spentUsd) : 0,
3117
- over: cell.reservation ? Math.max(0, cell.spentUsd - reserved) : 0,
3118
- used: holding ? Math.max(reserved, cell.spentUsd) : cell.spentUsd
3119
- };
3120
- }
3121
- /** The admission rule: committed spend, open holds, the unspent claim
3122
- * reserve and the new hold stay within the cap. A claim cell draws on the
3123
- * claim reserve instead of adding to it. */
3124
- admit(reservation, claim, subject) {
3125
- const { maxUsd, reservedClaimUsd } = this.header.budget;
3126
- if (maxUsd === null) return;
3127
- const hold = reservation?.usd ?? 0;
3128
- const remainingClaim = Math.max(0, reservedClaimUsd - this.claimUsedUsd);
3129
- if (this.audit.spend.committedUsd + this.audit.spend.openReservationUsd + (claim ? Math.max(0, remainingClaim - hold) : remainingClaim) + hold > maxUsd + USD_TOLERANCE) throw integrity(`${subject} is not admissible: committed $${round(this.audit.spend.committedUsd)} + open $${round(this.audit.spend.openReservationUsd)} + claim reserve $${round(remainingClaim)} + hold $${round(hold)} exceeds the cap $${maxUsd}`);
3130
- }
3131
- /** @internal */
3132
- readHeader() {
3133
- return this.header;
3134
- }
3135
- /** @internal */
3136
- readClosed() {
3137
- return this.closed;
3138
- }
3139
- /** @internal */
3140
- readHead() {
3141
- return this.head;
3142
- }
3143
- /** @internal */
3144
- readLastOccurredAt() {
3145
- return this.lastOccurredAtText;
3146
- }
3147
- /** @internal */
3148
- readAudit() {
3149
- const audit = this.audit;
3150
- return {
3151
- ...audit,
3152
- edges: { ...audit.edges },
3153
- cells: { ...audit.cells },
3154
- outcomes: { ...audit.outcomes },
3155
- operations: { ...audit.operations },
3156
- spend: { ...audit.spend },
3157
- tokens: { ...audit.tokens }
3158
- };
3159
- }
3160
- /** @internal */
3161
- readNode(nodeId) {
3162
- const record = this.nodes.get(nodeId);
3163
- return record ? nodeView(record) : void 0;
3164
- }
3165
- /** @internal */
3166
- readNodeIds() {
3167
- return this.nodeOrder;
3168
- }
3169
- /** @internal */
3170
- readHasNode(nodeId) {
3171
- return this.nodes.has(nodeId);
3172
- }
3173
- /** @internal */
3174
- readNodeIdForDigest(artifactDigest) {
3175
- return this.nodeByDigest.get(artifactDigest);
3176
- }
3177
- /** @internal */
3178
- readEdge(edgeId) {
3179
- return this.edges.get(edgeId);
3180
- }
3181
- /** @internal */
3182
- readEdgeIds() {
3183
- return this.edgeOrder;
3184
- }
3185
- /** @internal */
3186
- readCell(cellId) {
3187
- const cell = this.cells.get(cellId);
3188
- return cell ? { ...cell } : void 0;
3189
- }
3190
- /** @internal */
3191
- readCellIds(nodeId) {
3192
- if (nodeId === void 0) return [...this.cells.keys()];
3193
- return this.nodes.get(nodeId)?.cellIds ?? [];
3194
- }
3195
- /** @internal */
3196
- readOperation(operationId) {
3197
- const operation = this.operations.get(operationId);
3198
- return operation ? { ...operation } : void 0;
3199
- }
3200
- /** @internal */
3201
- readScoredCells(nodeId, split) {
3202
- const scored = [];
3203
- for (const cellId of this.nodes.get(nodeId)?.cellIds ?? []) {
3204
- const cell = this.cells.get(cellId);
3205
- if (cell.split === split && cell.score !== null) scored.push({
3206
- cellId,
3207
- unitId: cell.unitId,
3208
- attempt: cell.attempts,
3209
- score: cell.score
3210
- });
3211
- }
3212
- return scored;
3213
- }
3214
- };
3215
- /**
3216
- * A read of `SearchState` at one ledger position. Header, head, audit and
3217
- * claim are values. Node, edge, cell and score reads go to the live indexes and
3218
- * throw once the state has applied a later entry.
3219
- */
3220
- var SearchStateView = class {
3221
- searchId;
3222
- header;
3223
- closed;
3224
- head;
3225
- /** `occurredAt` of the head entry; a writer stamps later events at or after it. */
3226
- lastOccurredAt;
3227
- audit;
3228
- completion;
3229
- state;
3230
- version;
3231
- constructor(state, version) {
3232
- this.state = state;
3233
- this.version = version;
3234
- this.searchId = state.searchId;
3235
- this.header = state.readHeader();
3236
- this.closed = state.readClosed();
3237
- this.head = state.readHead();
3238
- this.lastOccurredAt = state.readLastOccurredAt();
3239
- this.audit = state.readAudit();
3240
- const reasons = state.incompleteReasons();
3241
- if (!this.closed) reasons.unshift("search is open");
3242
- this.completion = {
3243
- complete: this.closed !== null,
3244
- reasons
3245
- };
3246
- }
3247
- /** The node the search started from: the first registered. */
3248
- get rootNodeId() {
3249
- return this.live().readNodeIds()[0] ?? null;
3250
- }
3251
- node(nodeId) {
3252
- return this.live().readNode(nodeId);
3253
- }
3254
- hasNode(nodeId) {
3255
- return this.live().readHasNode(nodeId);
3256
- }
3257
- /** Node ids in registration order. */
3258
- nodeIds() {
3259
- return [...this.live().readNodeIds()];
3260
- }
3261
- /** Nodes in registration order. */
3262
- nodes() {
3263
- const state = this.live();
3264
- return state.readNodeIds().map((nodeId) => state.readNode(nodeId));
3265
- }
3266
- nodeIdForDigest(artifactDigest) {
3267
- return this.live().readNodeIdForDigest(artifactDigest);
3268
- }
3269
- edge(edgeId) {
3270
- return this.live().readEdge(edgeId);
3271
- }
3272
- /** Edges in ledger order. */
3273
- edges() {
3274
- const state = this.live();
3275
- return state.readEdgeIds().map((edgeId) => state.readEdge(edgeId));
3276
- }
3277
- cell(cellId) {
3278
- return this.live().readCell(cellId);
3279
- }
3280
- /** Cells in allocation order, optionally of one node. */
3281
- cells(filter = {}) {
3282
- const state = this.live();
3283
- return state.readCellIds(filter.nodeId).map((cellId) => state.readCell(cellId));
3284
- }
3285
- operation(operationId) {
3286
- return this.live().readOperation(operationId);
3287
- }
3288
- /** A node's scored cells on one split, in allocation order. Unscored cells
3289
- * (errored, cancelled or in flight) are absent, never zero. */
3290
- scoredCells(nodeId, split) {
3291
- return this.live().readScoredCells(nodeId, split);
3292
- }
3293
- /** Per-unit score means of a node on one split, in unitId order. */
3294
- unitScores(nodeId, split) {
3295
- return searchUnitScores(this.scoredCells(nodeId, split));
3296
- }
3297
- /** The lineage a RunRecord mint needs for one cell attempt. */
3298
- lineage(coordinates) {
3299
- const state = this.live();
3300
- if (coordinates.searchId !== this.searchId) throw new SearchLedgerError(`coordinates name search ${coordinates.searchId}, not ${this.searchId}`);
3301
- const cell = state.readCell(coordinates.cellId);
3302
- if (!cell || cell.nodeId !== coordinates.nodeId) throw new SearchLedgerError(`cell ${coordinates.cellId} of node ${coordinates.nodeId} is not in search ${this.searchId}`);
3303
- if (coordinates.attempt < 1 || coordinates.attempt > cell.attempts) throw new SearchLedgerError(`cell ${coordinates.cellId} has ${cell.attempts} settled attempt(s), not attempt ${coordinates.attempt}`);
3304
- const node = state.readNode(cell.nodeId);
3305
- if (node.depth === null) throw new SearchLedgerError(`node ${node.nodeId} has unknown lineage, so its depth is unknown`);
3306
- const containment = this.header?.containment ?? null;
3307
- return {
3308
- depth: node.depth,
3309
- ordinal: node.ordinal,
3310
- rep: cell.rep,
3311
- containingRunId: containment ? searchCellRunId({
3312
- cellId: containment.cellId,
3313
- attempt: containment.attempt
3314
- }) : null
3315
- };
3316
- }
3317
- live() {
3318
- if (!this.state.isAt(this.version)) throw new SearchLedgerError(`this SearchStateView is from sequence ${this.head?.sequence ?? -1}, and the ledger has moved on; read the ledger's state again`);
3319
- return this.state;
3320
- }
3321
- };
3322
- function nodeView(record) {
3323
- const latest = record.decisions.at(-1)?.decision ?? null;
3324
- return {
3325
- nodeId: record.event.nodeId,
3326
- ordinal: record.ordinal,
3327
- artifactDigest: record.event.artifactDigest,
3328
- artifact: record.event.artifact,
3329
- surfaces: record.event.surfaces,
3330
- primaryParentId: record.primaryParentId,
3331
- depth: record.depth,
3332
- parents: [...record.parents],
3333
- children: [...record.children],
3334
- edgeIds: [...record.edgeIds],
3335
- status: latest?.status ?? null,
3336
- rung: latest?.status === "advanced" ? latest.rung : null,
3337
- finalist: record.finalist,
3338
- decisions: [...record.decisions],
3339
- cellCount: record.cellIds.length,
3340
- spend: { ...record.spend },
3341
- registeredSequence: record.registeredSequence,
3342
- updatedSequence: record.updatedSequence
3343
- };
3344
- }
3345
- function assertStageSplit(cellId, stage, split, isRoot) {
3346
- if (!{
3347
- root: ["train", "selection"],
3348
- train: ["train"],
3349
- screen: ["selection"],
3350
- rung: ["selection"],
3351
- claim: ["test"],
3352
- external: ["train", "selection"]
3353
- }[stage].includes(split)) throw integrity(`cell ${cellId}: a ${stage} cell cannot run on the ${split} split`);
3354
- if (stage === "root" && !isRoot) throw integrity(`cell ${cellId}: only the root node runs root cells`);
3355
- }
3356
- function assertUnique(values, label, eventId) {
3357
- if (new Set(values).size !== values.length) throw integrity(`event ${eventId} contains duplicate ${label} values`);
3358
- }
3359
- function count(value, noun, predicate) {
3360
- const verb = predicate.replace(/^(has|is) /, (word) => value === 1 ? word : word === "has " ? "have " : "are ");
3361
- return `${value} ${value === 1 ? noun : `${noun}s`} ${verb}`;
3362
- }
3363
- function round(usd) {
3364
- return Math.round(usd * 1e6) / 1e6;
3365
- }
3366
- function integrity(message) {
3367
- return new SearchLedgerIntegrityError(message);
3368
- }
3369
- //#endregion
3370
- //#region src/campaign/search-ledger.ts
3371
- /**
3372
- * Durable, append-only event log of one search: nodes (content-addressed
3373
- * artifacts), edges (the proposals that derived them), cells (one run of one
3374
- * node on one task), operations, decisions, and the claim.
3375
- *
3376
- * The ledger is the search's only lineage record and its only resume
3377
- * checkpoint. A RunRecord owns one measured run and `CostLedger` owns per-call
3378
- * accounting; this ledger binds them by digest instead of copying them.
3379
- *
3380
- * The file format is canonical JSONL with a SHA-256 hash chain. Every append is
3381
- * serialized across processes, fsynced before acknowledgement, and idempotent
3382
- * by `eventId`. A malformed, non-canonical, truncated, reordered, or conflicting
3383
- * log fails loudly; a bad row is never skipped. A ledger written under another
3384
- * schema tag is refused with that tag named, never translated.
3385
- *
3386
- * The journal machinery is the generic `ledger-core` journal. This module is
3387
- * the search codec: event schemas and canonical ordering. `SearchState` is the
3388
- * state machine and read model.
3389
- */
3390
- const NON_EMPTY = z.string().min(1).refine((value) => value.trim() === value, "must not contain surrounding whitespace");
3391
- const HASH = z.string().regex(/^sha256:[a-f0-9]{64}$/);
3392
- const IMMUTABLE_REVISION = z.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64}|sha256:[a-f0-9]{64}|sha512:[A-Za-z0-9+/=]+)$/);
3393
- const ISO_TIMESTAMP = z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/).refine((value) => Number.isFinite(Date.parse(value)), "invalid timestamp");
3394
- const NON_NEGATIVE_INT = z.number().int().nonnegative().safe();
3395
- const POSITIVE_INT = z.number().int().positive().safe();
3396
- const FINITE_NUMBER = z.number().finite();
3397
- const USD = z.number().finite().nonnegative();
3398
- const NODE_ID = z.string().regex(/^node_[a-f0-9]{32}$/);
3399
- const CELL_ID = z.string().regex(/^cell_[a-f0-9]{32}$/);
3400
- const ArtifactRefSchema = z.object({
3401
- role: NON_EMPTY,
3402
- uri: NON_EMPTY,
3403
- sha256: HASH,
3404
- byteLength: NON_NEGATIVE_INT
3405
- }).strict();
3406
- const SourceRefSchema = z.object({
3407
- uri: NON_EMPTY,
3408
- revision: IMMUTABLE_REVISION
3409
- }).strict();
3410
- const UnknownRefSchema = z.object({ unknown: NON_EMPTY }).strict();
3411
- const FailureReasonSchema = z.object({
3412
- code: NON_EMPTY,
3413
- message: NON_EMPTY
3414
- }).strict();
3415
- const ModelIdentitySchema = z.union([z.object({
3416
- provider: NON_EMPTY,
3417
- snapshot: NON_EMPTY.refine(modelHasSnapshot, "model must include an immutable snapshot")
3418
- }).strict(), z.object({
3419
- provider: NON_EMPTY,
3420
- alias: NON_EMPTY,
3421
- unknown: NON_EMPTY
3422
- }).strict()]);
3423
- const ExecutionIdentitySchema = z.object({
3424
- model: ModelIdentitySchema,
3425
- agent: SourceRefSchema,
3426
- benchmark: SourceRefSchema
3427
- }).strict();
3428
- const SURFACE_KINDS = [
3429
- "prompt",
3430
- "tool-contract",
3431
- "runtime-config",
3432
- "memory",
3433
- "knowledge",
3434
- "agent-profile",
3435
- "code",
3436
- "deployment"
3437
- ];
3438
- const SPLIT = z.enum([
3439
- "train",
3440
- "selection",
3441
- "test"
3442
- ]);
3443
- const ReservationSchema = z.object({
3444
- kind: z.enum(["hard", "estimate"]),
3445
- usd: USD
3446
- }).strict();
3447
- const EventBaseShape = {
3448
- eventId: NON_EMPTY,
3449
- occurredAt: ISO_TIMESTAMP,
3450
- artifacts: z.array(ArtifactRefSchema)
3451
- };
3452
- const OperationKindSchema = z.enum([
3453
- "candidate-generation",
3454
- "analysis",
3455
- "selection",
3456
- "judge",
3457
- "other"
3458
- ]);
3459
- const KnownTokensSchema = z.object({
3460
- status: z.literal("known"),
3461
- inputTokens: NON_NEGATIVE_INT,
3462
- outputTokens: NON_NEGATIVE_INT,
3463
- cachedTokens: NON_NEGATIVE_INT
3464
- }).strict();
3465
- const UnknownTokensSchema = z.object({
3466
- status: z.literal("unknown"),
3467
- reason: NON_EMPTY
3468
- }).strict();
3469
- const KnownCostSchema = z.object({
3470
- status: z.literal("known"),
3471
- usd: USD,
3472
- source: z.enum([
3473
- "provider",
3474
- "pricing-table",
3475
- "free"
3476
- ])
3477
- }).strict().superRefine((cost, ctx) => {
3478
- if (cost.source === "free" && cost.usd !== 0) ctx.addIssue({
3479
- code: "custom",
3480
- message: "free cost source must have usd 0"
3481
- });
3482
- });
3483
- const UnknownCostSchema = z.object({
3484
- status: z.literal("unknown"),
3485
- knownLowerBoundUsd: USD,
3486
- reason: NON_EMPTY
3487
- }).strict();
3488
- const AccountingSchema = z.object({
3489
- tokens: z.discriminatedUnion("status", [KnownTokensSchema, UnknownTokensSchema]),
3490
- cost: z.discriminatedUnion("status", [KnownCostSchema, UnknownCostSchema])
3491
- }).strict();
3492
- const MetricsSchema = z.record(NON_EMPTY, FINITE_NUMBER).superRefine((metrics, ctx) => {
3493
- for (const key of Object.keys(metrics)) if (key === "__proto__" || key === "constructor" || key === "prototype") ctx.addIssue({
3494
- code: "custom",
3495
- message: `unsafe metric key ${key}`
3496
- });
3497
- });
3498
- const OutcomeSchema = z.discriminatedUnion("status", [
3499
- z.object({
3500
- status: z.literal("passed"),
3501
- score: FINITE_NUMBER,
3502
- metrics: MetricsSchema
3503
- }).strict(),
3504
- z.object({
3505
- status: z.literal("failed"),
3506
- score: FINITE_NUMBER,
3507
- metrics: MetricsSchema,
3508
- failure: FailureReasonSchema
3509
- }).strict(),
3510
- z.object({
3511
- status: z.literal("errored"),
3512
- metrics: MetricsSchema,
3513
- error: FailureReasonSchema.extend({ retryable: z.boolean() }).strict()
3514
- }).strict()
3515
- ]);
3516
- const EffectSchema = z.discriminatedUnion("status", [z.object({
3517
- status: z.literal("measured"),
3518
- metric: NON_EMPTY,
3519
- baselineValue: FINITE_NUMBER,
3520
- candidateValue: FINITE_NUMBER,
3521
- delta: FINITE_NUMBER
3522
- }).strict().superRefine((effect, ctx) => {
3523
- const expected = effect.candidateValue - effect.baselineValue;
3524
- const tolerance = Number.EPSILON * Math.max(1, Math.abs(expected), Math.abs(effect.delta)) * 8;
3525
- if (Math.abs(effect.delta - expected) > tolerance) ctx.addIssue({
3526
- code: "custom",
3527
- message: "delta must equal candidateValue - baselineValue"
3528
- });
3529
- }), z.object({
3530
- status: z.literal("not-measured"),
3531
- reason: NON_EMPTY
3532
- }).strict()]);
3533
- const SurfaceEvidenceSchema = z.object({
3534
- surfaceId: NON_EMPTY,
3535
- fired: z.boolean(),
3536
- firingCount: NON_NEGATIVE_INT,
3537
- effect: EffectSchema,
3538
- evidence: z.array(ArtifactRefSchema).min(1)
3539
- }).strict().superRefine((evidence, ctx) => {
3540
- if (evidence.fired !== evidence.firingCount > 0) ctx.addIssue({
3541
- code: "custom",
3542
- message: "fired must equal firingCount > 0"
3543
- });
3544
- if (!evidence.fired && evidence.effect.status === "measured" && evidence.effect.delta !== 0) ctx.addIssue({
3545
- code: "custom",
3546
- message: "a surface that did not fire has no effect"
3547
- });
3548
- });
3549
- const TaskSchema = z.object({
3550
- taskId: NON_EMPTY,
3551
- unitId: NON_EMPTY,
3552
- source: SourceRefSchema
3553
- }).strict();
3554
- const SplitTasksSchema = z.object({
3555
- taskSetDigest: HASH,
3556
- tasks: z.array(TaskSchema)
3557
- }).strict();
3558
- const SearchOpenedSchema = z.object({
3559
- ...EventBaseShape,
3560
- kind: z.literal("search-opened"),
3561
- subject: NON_EMPTY,
3562
- process: z.object({
3563
- name: NON_EMPTY,
3564
- executionRef: SourceRefSchema
3565
- }).strict(),
3566
- artifactKind: z.enum([...SURFACE_KINDS, "output"]),
3567
- objective: z.object({
3568
- metric: NON_EMPTY,
3569
- direction: z.enum(["maximize", "minimize"]),
3570
- judge: z.union([SourceRefSchema, UnknownRefSchema]),
3571
- claim: evaluationClaimSchema
3572
- }).strict(),
3573
- splits: z.object({
3574
- train: SplitTasksSchema,
3575
- selection: SplitTasksSchema,
3576
- test: SplitTasksSchema,
3577
- heldOutUnits: z.boolean()
3578
- }).strict(),
3579
- policy: z.object({
3580
- expansion: NON_EMPTY,
3581
- allocation: NON_EMPTY,
3582
- seed: z.number().int().safe()
3583
- }).strict(),
3584
- budget: z.object({
3585
- maxUsd: USD.nullable(),
3586
- maxCells: POSITIVE_INT.nullable(),
3587
- maxNodes: POSITIVE_INT.nullable(),
3588
- deadline: ISO_TIMESTAMP.nullable(),
3589
- maxConcurrency: POSITIVE_INT.nullable(),
3590
- reservedClaimUsd: USD
3591
- }).strict(),
3592
- containment: z.object({
3593
- searchId: NON_EMPTY,
3594
- cellId: CELL_ID,
3595
- attempt: POSITIVE_INT
3596
- }).strict().nullable(),
3597
- derivedFrom: z.object({
3598
- searchId: NON_EMPTY,
3599
- nodeId: NODE_ID,
3600
- headHash: HASH
3601
- }).strict().nullable(),
3602
- identity: ExecutionIdentitySchema
3603
- }).strict();
3604
- const OperationStartedSchema = z.object({
3605
- ...EventBaseShape,
3606
- kind: z.literal("operation-started"),
3607
- operationId: NON_EMPTY,
3608
- operationKind: OperationKindSchema,
3609
- reservation: ReservationSchema.nullable()
3610
- }).strict();
3611
- const OperationRecordedSchema = z.object({
3612
- ...EventBaseShape,
3613
- kind: z.literal("operation-recorded"),
3614
- operationId: NON_EMPTY,
3615
- operationKind: OperationKindSchema,
3616
- execution: z.discriminatedUnion("kind", [z.object({
3617
- kind: z.literal("model"),
3618
- model: ModelIdentitySchema,
3619
- source: SourceRefSchema
3620
- }).strict(), z.object({
3621
- kind: z.literal("deterministic"),
3622
- source: SourceRefSchema
3623
- }).strict()]),
3624
- outcome: z.discriminatedUnion("status", [
3625
- z.object({ status: z.literal("completed") }).strict(),
3626
- z.object({
3627
- status: z.literal("partial"),
3628
- failure: FailureReasonSchema
3629
- }).strict(),
3630
- z.object({
3631
- status: z.literal("failed"),
3632
- failure: FailureReasonSchema
3633
- }).strict()
3634
- ]),
3635
- accounting: AccountingSchema
3636
- }).strict();
3637
- const NodeRegisteredSchema = z.object({
3638
- ...EventBaseShape,
3639
- kind: z.literal("node-registered"),
3640
- nodeId: NODE_ID,
3641
- artifactDigest: HASH,
3642
- artifact: ArtifactRefSchema,
3643
- surfaces: z.array(z.object({
3644
- surfaceId: NON_EMPTY,
3645
- kind: z.enum(SURFACE_KINDS),
3646
- artifact: ArtifactRefSchema
3647
- }).strict())
3648
- }).strict();
3649
- const NodeRefSchema = z.object({
3650
- searchId: NON_EMPTY,
3651
- nodeId: NODE_ID
3652
- }).strict();
3653
- const ArtifactOrUnknownSchema = z.union([ArtifactRefSchema, UnknownRefSchema]);
3654
- const EdgeRecordedSchema = z.object({
3655
- ...EventBaseShape,
3656
- kind: z.literal("edge-recorded"),
3657
- edgeId: z.string().regex(/^edge_[a-f0-9]{32}$/),
3658
- childNodeId: NODE_ID,
3659
- parents: z.array(NodeRefSchema),
3660
- operator: z.enum([
3661
- "seed",
3662
- "draft",
3663
- "improve",
3664
- "debug",
3665
- "merge",
3666
- "derive"
3667
- ]),
3668
- attribution: z.enum([
3669
- "explicit",
3670
- "correlated",
3671
- "unknown"
3672
- ]),
3673
- proposer: z.object({
3674
- kind: z.enum([
3675
- "trace",
3676
- "frontier-author",
3677
- "human",
3678
- "optimizer",
3679
- "compound"
3680
- ]),
3681
- name: NON_EMPTY,
3682
- operationId: NON_EMPTY.nullable(),
3683
- source: SourceRefSchema
3684
- }).strict().nullable(),
3685
- selection: z.object({
3686
- rule: NON_EMPTY,
3687
- evidence: z.record(NON_EMPTY, FINITE_NUMBER)
3688
- }).strict().nullable(),
3689
- rationale: ArtifactOrUnknownSchema,
3690
- diffs: z.array(ArtifactOrUnknownSchema),
3691
- label: z.string()
3692
- }).strict();
3693
- const CellAllocatedSchema = z.object({
3694
- ...EventBaseShape,
3695
- kind: z.literal("cell-allocated"),
3696
- cellId: CELL_ID,
3697
- nodeId: NODE_ID,
3698
- taskId: NON_EMPTY,
3699
- unitId: NON_EMPTY,
3700
- split: SPLIT,
3701
- rep: NON_NEGATIVE_INT,
3702
- stage: z.enum([
3703
- "root",
3704
- "train",
3705
- "screen",
3706
- "rung",
3707
- "claim",
3708
- "external"
3709
- ]),
3710
- lane: NON_EMPTY.nullable(),
3711
- reservation: ReservationSchema.nullable()
3712
- }).strict();
3713
- const TraceRefSchema = z.union([z.object({
3714
- traceId: NON_EMPTY,
3715
- execRunId: NON_EMPTY.nullable(),
3716
- spansWritten: NON_NEGATIVE_INT.nullable(),
3717
- spansDropped: NON_NEGATIVE_INT.nullable()
3718
- }).strict(), UnknownRefSchema]);
3719
- const NON_NEGATIVE = z.number().finite().nonnegative();
3720
- const CellSettledSchema = z.object({
3721
- ...EventBaseShape,
3722
- kind: z.literal("cell-settled"),
3723
- cellId: CELL_ID,
3724
- attempt: POSITIVE_INT,
3725
- runId: NON_EMPTY,
3726
- outcome: OutcomeSchema,
3727
- accounting: AccountingSchema,
3728
- boxMinutes: NON_NEGATIVE.nullable(),
3729
- wallMs: NON_NEGATIVE.nullable(),
3730
- queueMs: NON_NEGATIVE.nullable(),
3731
- placement: z.object({
3732
- lane: NON_EMPTY,
3733
- boxId: NON_EMPTY.nullable()
3734
- }).strict().nullable(),
3735
- identity: ExecutionIdentitySchema,
3736
- surfaceEvidence: z.array(SurfaceEvidenceSchema),
3737
- traceRef: TraceRefSchema
3738
- }).strict();
3739
- const CellCancelledSchema = z.object({
3740
- ...EventBaseShape,
3741
- kind: z.literal("cell-cancelled"),
3742
- cellId: CELL_ID,
3743
- reason: z.enum([
3744
- "pruned",
3745
- "budget",
3746
- "deadline",
3747
- "aborted"
3748
- ])
3749
- }).strict();
3750
- const NodeEstimateSchema = z.object({
3751
- against: NODE_ID,
3752
- split: SPLIT,
3753
- units: NON_NEGATIVE_INT,
3754
- pairs: NON_NEGATIVE_INT,
3755
- delta: FINITE_NUMBER.nullable(),
3756
- interval: z.tuple([FINITE_NUMBER, FINITE_NUMBER]).nullable(),
3757
- method: z.enum([
3758
- "none",
3759
- "insufficient",
3760
- "descriptive",
3761
- "bootstrap"
3762
- ]),
3763
- exactSignP: z.number().min(0).max(1).nullable(),
3764
- indeterminate: z.boolean(),
3765
- cellSetDigest: HASH,
3766
- estimator: SourceRefSchema
3767
- }).strict();
3768
- const NodeDecidedSchema = z.object({
3769
- ...EventBaseShape,
3770
- kind: z.literal("node-decided"),
3771
- nodeId: NODE_ID,
3772
- decision: z.discriminatedUnion("status", [
3773
- z.object({
3774
- status: z.literal("advanced"),
3775
- rung: NON_NEGATIVE_INT
3776
- }).strict(),
3777
- z.object({ status: z.literal("pruned") }).strict(),
3778
- z.object({ status: z.literal("invalid") }).strict(),
3779
- z.object({ status: z.literal("finalist") }).strict(),
3780
- z.object({ status: z.literal("selected") }).strict(),
3781
- z.object({ status: z.literal("rejected") }).strict()
3782
- ]),
3783
- basis: NodeEstimateSchema.nullable(),
3784
- rule: NON_EMPTY,
3785
- reason: NON_EMPTY
3786
- }).strict();
3787
- const SearchClosedSchema = z.object({
3788
- ...EventBaseShape,
3789
- kind: z.literal("search-closed"),
3790
- reason: z.enum([
3791
- "budget",
3792
- "deadline",
3793
- "max-nodes",
3794
- "patience",
3795
- "converged",
3796
- "aborted"
3797
- ]),
3798
- claim: z.object({
3799
- power: z.union([z.object({
3800
- adequate: z.boolean(),
3801
- minimumEffect: z.number().finite().positive(),
3802
- powerAtMinimumEffect: z.number().min(0).max(1),
3803
- units: NON_NEGATIVE_INT
3804
- }).strict(), UnknownRefSchema]),
3805
- finalists: z.array(z.object({
3806
- nodeId: NODE_ID,
3807
- estimate: NodeEstimateSchema.nullable(),
3808
- promote: z.boolean()
3809
- }).strict()),
3810
- selected: NODE_ID.nullable(),
3811
- decision: z.enum([
3812
- "ship",
3813
- "hold",
3814
- "test-cannot-resolve"
3815
- ])
3816
- }).strict().nullable()
3817
- }).strict();
3818
- const EventSchema = z.discriminatedUnion("kind", [
3819
- SearchOpenedSchema,
3820
- OperationStartedSchema,
3821
- OperationRecordedSchema,
3822
- NodeRegisteredSchema,
3823
- EdgeRecordedSchema,
3824
- CellAllocatedSchema,
3825
- CellSettledSchema,
3826
- CellCancelledSchema,
3827
- NodeDecidedSchema,
3828
- SearchClosedSchema
3829
- ]);
3830
- const EntrySchema = z.object({
3831
- schema: z.literal(SEARCH_LEDGER_SCHEMA),
3832
- searchId: NON_EMPTY,
3833
- sequence: NON_NEGATIVE_INT,
3834
- previousHash: z.union([HASH, z.null()]),
3835
- event: EventSchema,
3836
- entryHash: HASH
3837
- }).strict();
3838
- /** Validate and return a canonical copy. Arrays whose order carries no meaning
3839
- * are sorted, so retries from different processes produce identical bytes. */
3840
- function validateSearchLedgerEvent(input) {
3841
- const parsed = EventSchema.safeParse(input);
3842
- if (!parsed.success) throw new SearchLedgerError(`invalid search ledger event: ${formatZodError(parsed.error)}`);
3843
- return normalizeEvent(parsed.data);
3844
- }
3845
- /** Open a durable filesystem search ledger. Construction performs no I/O; the
3846
- * first `append` or `state` verifies the whole existing file. */
3847
- function openSearchLedger(options) {
3848
- return new FileSearchLedger(options.path, options.searchId, options.trustedHead);
3849
- }
3850
- /** Verify and project immutable search-ledger JSONL through the same codec as
3851
- * `FileSearchLedger`. */
3852
- function replaySearchLedgerText(text, searchId, source) {
3853
- return replayLedgerText(text, source, searchLedgerCodec(searchId));
3854
- }
3855
- function searchLedgerCodec(searchId) {
3856
- return {
3857
- ...SEARCH_LEDGER_FILE_CONTEXT,
3858
- header: {
3859
- schema: SEARCH_LEDGER_SCHEMA,
3860
- searchId
3861
- },
3862
- conflictError: (message) => new SearchLedgerConflictError(message),
3863
- parseEntry: parseSearchLedgerEntry,
3864
- checkEntryHeader: (entry, index) => {
3865
- if (entry.searchId !== searchId) throw new SearchLedgerIntegrityError(`entry ${index} belongs to search ${entry.searchId}, expected ${searchId}`);
3866
- },
3867
- createProjector: () => new SearchState(searchId)
3868
- };
3869
- }
3870
- /** Append-only file-backed search ledger with idempotent writes. */
3871
- var FileSearchLedger = class {
3872
- path;
3873
- searchId;
3874
- trustedHeadPath;
3875
- trustedHeadMode;
3876
- journal;
3877
- constructor(path, searchId, trustedHead = "pin") {
3878
- if (path.trim().length === 0) throw new SearchLedgerError("ledger path is empty");
3879
- if (searchId.length === 0 || searchId.trim() !== searchId) throw new SearchLedgerError("searchId must be non-empty without surrounding whitespace");
3880
- this.searchId = searchId;
3881
- this.trustedHeadMode = trustedHead;
3882
- this.journal = new FileLedgerJournal(path, searchLedgerCodec(searchId), { requireTrustedHead: trustedHead === "require" });
3883
- this.path = this.journal.path;
3884
- this.trustedHeadPath = this.journal.trustedHeadPath;
3885
- }
3886
- async state() {
3887
- return this.journal.replay();
3888
- }
3889
- async append(input) {
3890
- const event = validateSearchLedgerEvent(input);
3891
- const { entry, appended, projection } = await this.journal.append(event, { pinHead: this.trustedHeadMode !== "off" });
3892
- return {
3893
- entry,
3894
- appended,
3895
- state: projection
3896
- };
3897
- }
3898
- async trustedHead() {
3899
- return this.journal.trustedHead();
3900
- }
3901
- async pinTrustedHead() {
3902
- return this.journal.pinTrustedHead();
3903
- }
3904
- async clearTrustedHead() {
3905
- return this.journal.clearTrustedHead();
3906
- }
3907
- };
3908
- function parseSearchLedgerEntry(raw, context) {
3909
- const schema = raw?.schema;
3910
- if (schema !== "tangle.search-ledger.2026-09") throw new SearchLedgerIntegrityError(`search ledger ${context.path} line ${context.line} was written under schema ${JSON.stringify(schema)}; this version reads only ${SEARCH_LEDGER_SCHEMA} and does not translate other formats`);
3911
- const parsed = EntrySchema.safeParse(raw);
3912
- if (!parsed.success) throw new SearchLedgerIntegrityError(`search ledger ${context.path} has a malformed entry at line ${context.line}: ${formatZodError(parsed.error)}`);
3913
- const entry = parsed.data;
3914
- if (canonicalString(validateSearchLedgerEvent(entry.event)) !== canonicalString(entry.event)) throw new SearchLedgerIntegrityError(`search ledger ${context.path} has non-canonical event ordering at line ${context.line}`);
3915
- return entry;
3916
- }
3917
- function normalizeEvent(event) {
3918
- const artifacts = sortArtifacts(event.artifacts);
3919
- switch (event.kind) {
3920
- case "search-opened": return {
3921
- ...event,
3922
- artifacts,
3923
- splits: {
3924
- ...event.splits,
3925
- train: {
3926
- ...event.splits.train,
3927
- tasks: sortTasks(event.splits.train.tasks)
3928
- },
3929
- selection: {
3930
- ...event.splits.selection,
3931
- tasks: sortTasks(event.splits.selection.tasks)
3932
- },
3933
- test: {
3934
- ...event.splits.test,
3935
- tasks: sortTasks(event.splits.test.tasks)
3936
- }
3937
- }
3938
- };
3939
- case "node-registered": return {
3940
- ...event,
3941
- artifacts,
3942
- surfaces: [...event.surfaces].sort((a, b) => compareStrings(a.surfaceId, b.surfaceId))
3943
- };
3944
- case "cell-settled": return {
3945
- ...event,
3946
- artifacts,
3947
- surfaceEvidence: [...event.surfaceEvidence].map((evidence) => ({
3948
- ...evidence,
3949
- evidence: sortArtifacts(evidence.evidence)
3950
- })).sort((a, b) => compareStrings(a.surfaceId, b.surfaceId))
3951
- };
3952
- default: return {
3953
- ...event,
3954
- artifacts
3955
- };
3956
- }
3957
- }
3958
- function sortTasks(tasks) {
3959
- return [...tasks].sort((a, b) => compareStrings(a.taskId, b.taskId));
3960
- }
3961
- function sortArtifacts(artifacts) {
3962
- return [...artifacts].sort((a, b) => compareStrings(artifactKey(a), artifactKey(b)));
3963
- }
3964
- function formatZodError(error) {
3965
- return error.issues.map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`).join("; ");
3966
- }
3967
- //#endregion
3968
2551
  //#region src/campaign/search-history-receipt.ts
3969
2552
  const SEARCH_HISTORY_RECEIPT_SCHEMA_VERSION = "2026-09";
3970
2553
  const SEARCH_HISTORY_RECEIPT_DIGEST_ALGORITHM = "rfc8785-sha256";
@@ -4254,7 +2837,7 @@ var SearchRecorder = class SearchRecorder {
4254
2837
  }
4255
2838
  return {
4256
2839
  role,
4257
- uri: `file://${path}`,
2840
+ uri: pathToFileURL(path).href,
4258
2841
  sha256: `sha256:${hex}`,
4259
2842
  byteLength: bytes.byteLength
4260
2843
  };
@@ -6670,6 +5253,6 @@ function firstString(value) {
6670
5253
  return typeof value === "string" && value.trim() ? value : void 0;
6671
5254
  }
6672
5255
  //#endregion
6673
- export { scoreRedTeamOutput as $, FileSearchLedger as A, SEARCH_LEDGER_SCHEMA as B, assertCompleteSearchHistory as C, searchHistoryCoverageRow as D, createSearchHistoryReceipt as E, SearchStateView as F, paretoFrontierWithCrowding as G, labelTrustRank as H, searchCellId as I, captureJudge as J, runFinalComparison as K, searchNodeId as L, replaySearchLedgerText as M, validateSearchLedgerEvent as N, verifySearchHistoryArtifact as O, SearchState as P, redTeamReport as Q, searchTaskSetDigest as R, SearchHistoryRequiredError as S, assertSearchHistoryMatchesState as T, dominates as U, isProposedCandidate as V, paretoFrontier as W, DEFAULT_RED_TEAM_CORPUS as X, defaultProductionGate as Y, redTeamDataset as Z, SearchRecorder as _, transientDispatchFailure as a, runEval as at, surfaceDiff as b, compareOptimizationMethods as c, resolveRunDir as ct, combineComparisonCosts as d, buildCellSchedule as dt, runCanaries as et, costFromLedgerSummary as f, cellCachePath as ft, runOptimization as g, runImprovementLoop as h, quotaExhaustedUntil as i, reserveFinalEvidence as it, openSearchLedger as j, verifySearchHistoryReceipt as k, optimizationTokenUsageFromSummary as l, tangleTracesRoot as lt, readGepaCandidatePopulationArtifact as m, JudgeParseError as n, captureFinalEvidencePolicy as nt, aggregateRunScore as o, runCampaign as ot, assertGepaCandidatePopulationSummary as p, computeManifestHash as pt, openAutoPr as q, isTransientTransportFailure as r, evaluationUnitMap as rt, clamp01 as s, planCampaignRun as st, llmJudge as t, assertIndependentEvaluationSplit as tt, executeOptimizationMethod as u, readCachedCell as ut, developmentClaim as v, assertSearchHistoryAdmissionOptions as w, surfaceNode as x, searchEdgeId as y, searchUnitScores as z };
5256
+ export { readCachedCell as $, isProposedCandidate as A, redTeamDataset as B, assertCompleteSearchHistory as C, searchHistoryCoverageRow as D, createSearchHistoryReceipt as E, runFinalComparison as F, captureFinalEvidencePolicy as G, scoreRedTeamOutput as H, openAutoPr as I, runEval as J, evaluationUnitMap as K, captureJudge as L, dominates as M, paretoFrontier as N, verifySearchHistoryArtifact as O, paretoFrontierWithCrowding as P, tangleTracesRoot as Q, defaultProductionGate as R, SearchHistoryRequiredError as S, assertSearchHistoryMatchesState as T, runCanaries as U, redTeamReport as V, assertIndependentEvaluationSplit as W, planCampaignRun as X, runCampaign as Y, resolveRunDir as Z, SearchRecorder as _, transientDispatchFailure as a, surfaceDiff as b, compareOptimizationMethods as c, combineComparisonCosts as d, buildCellSchedule as et, costFromLedgerSummary as f, runOptimization as g, runImprovementLoop as h, quotaExhaustedUntil as i, labelTrustRank as j, verifySearchHistoryReceipt as k, optimizationTokenUsageFromSummary as l, readGepaCandidatePopulationArtifact as m, JudgeParseError as n, computeManifestHash as nt, aggregateRunScore as o, assertGepaCandidatePopulationSummary as p, reserveFinalEvidence as q, isTransientTransportFailure as r, clamp01 as s, llmJudge as t, cellCachePath as tt, executeOptimizationMethod as u, developmentClaim as v, assertSearchHistoryAdmissionOptions as w, surfaceNode as x, searchEdgeId as y, DEFAULT_RED_TEAM_CORPUS as z };
6674
5257
 
6675
- //# sourceMappingURL=llm-judge-bwbgDMP0.js.map
5258
+ //# sourceMappingURL=llm-judge-NJOHM0iA.js.map