@tangle-network/agent-eval 0.217.1 → 0.219.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 (258) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/dist/adapters/http.d.ts +3 -3
  3. package/dist/adapters/http.d.ts.map +1 -1
  4. package/dist/adapters/http.js +1 -0
  5. package/dist/adapters/http.js.map +1 -1
  6. package/dist/{agent-profile-DTt8uGP9.d.ts → agent-profile-D01Io2Xw.d.ts} +4 -4
  7. package/dist/{agent-profile-DTt8uGP9.d.ts.map → agent-profile-D01Io2Xw.d.ts.map} +1 -1
  8. package/dist/analyst/index.d.ts +13 -13
  9. package/dist/analyst/index.d.ts.map +1 -1
  10. package/dist/analyst/index.js +10 -10
  11. package/dist/analyst/index.js.map +1 -1
  12. package/dist/{analyze-runs-DyeNcenW.d.ts → analyze-runs-BWAHBDAw.d.ts} +4 -4
  13. package/dist/{analyze-runs-DyeNcenW.d.ts.map → analyze-runs-BWAHBDAw.d.ts.map} +1 -1
  14. package/dist/{benchmark-command-xQK8nOI6.js → benchmark-command-BzmMTnvC.js} +664 -565
  15. package/dist/benchmark-command-BzmMTnvC.js.map +1 -0
  16. package/dist/benchmarks/index.d.ts +5 -5
  17. package/dist/benchmarks/index.js +3 -3
  18. package/dist/benchmarks/index.js.map +1 -1
  19. package/dist/campaign/index.d.ts +8 -8
  20. package/dist/campaign/index.js +11 -11
  21. package/dist/{campaign-CJGkxAQ6.js → campaign-BVPC6ODQ.js} +452 -282
  22. package/dist/campaign-BVPC6ODQ.js.map +1 -0
  23. package/dist/{campaign-evidence-CQYw8_0H.js → campaign-evidence-DunzcJGv.js} +2 -2
  24. package/dist/campaign-evidence-DunzcJGv.js.map +1 -0
  25. package/dist/{chat-client-ldqxYYTN.js → chat-client-CMQ8_h4J.js} +2 -2
  26. package/dist/{chat-client-ldqxYYTN.js.map → chat-client-CMQ8_h4J.js.map} +1 -1
  27. package/dist/{chat-json-call-DavzexSp.js → chat-json-call-BrZKn0L3.js} +2 -2
  28. package/dist/{chat-json-call-DavzexSp.js.map → chat-json-call-BrZKn0L3.js.map} +1 -1
  29. package/dist/cli.js +10 -10
  30. package/dist/{completion-verifier-B_jw6C9p.js → completion-verifier-Cigap8CG.js} +5 -5
  31. package/dist/{completion-verifier-B_jw6C9p.js.map → completion-verifier-Cigap8CG.js.map} +1 -1
  32. package/dist/contract/index.d.ts +11 -11
  33. package/dist/contract/index.js +91 -11
  34. package/dist/contract/index.js.map +1 -1
  35. package/dist/{cost-ledger-D0352Z4d.js → cost-ledger-BGZB6yY2.js} +75 -2
  36. package/dist/cost-ledger-BGZB6yY2.js.map +1 -0
  37. package/dist/{cost-ledger-Jk62OBfF.d.ts → cost-ledger-C1W3ICmP.d.ts} +26 -2
  38. package/dist/cost-ledger-C1W3ICmP.d.ts.map +1 -0
  39. package/dist/{default-registry-ClYjq3QE.js → default-registry-BrKmT01n.js} +310 -278
  40. package/dist/{default-registry-ClYjq3QE.js.map → default-registry-BrKmT01n.js.map} +1 -1
  41. package/dist/{default-registry-DXgLmoDI.d.ts → default-registry-Cwg_QN3d.d.ts} +6 -6
  42. package/dist/{default-registry-DXgLmoDI.d.ts.map → default-registry-Cwg_QN3d.d.ts.map} +1 -1
  43. package/dist/{define-agent-eval-BIkH_gAR.d.ts → define-agent-eval-C2nFhHPu.d.ts} +8 -8
  44. package/dist/{define-agent-eval-BIkH_gAR.d.ts.map → define-agent-eval-C2nFhHPu.d.ts.map} +1 -1
  45. package/dist/{define-agent-eval-BDxNlP3D.js → define-agent-eval-UQY3VbJ2.js} +165 -105
  46. package/dist/define-agent-eval-UQY3VbJ2.js.map +1 -0
  47. package/dist/diagnosis/index.d.ts +2 -2
  48. package/dist/{dspy-rlm-engine-DhdCr1Dc.js → dspy-rlm-engine-Bn_Mt_LW.js} +3 -3
  49. package/dist/{dspy-rlm-engine-DhdCr1Dc.js.map → dspy-rlm-engine-Bn_Mt_LW.js.map} +1 -1
  50. package/dist/{engine-BvZ0R-36.d.ts → engine-BpGGw6cd.d.ts} +3 -3
  51. package/dist/{engine-BvZ0R-36.d.ts.map → engine-BpGGw6cd.d.ts.map} +1 -1
  52. package/dist/eval-campaign-BUMIxKTE.js +393 -0
  53. package/dist/eval-campaign-BUMIxKTE.js.map +1 -0
  54. package/dist/{evaluation-jTjC_QQD.d.ts → evaluation-CBdQt_kr.d.ts} +4 -4
  55. package/dist/{evaluation-jTjC_QQD.d.ts.map → evaluation-CBdQt_kr.d.ts.map} +1 -1
  56. package/dist/evaluation.d.ts +1 -1
  57. package/dist/evaluation.js +1 -1
  58. package/dist/{exact-types-CflbJ9f3.d.ts → exact-types-BYFmYq44.d.ts} +2 -2
  59. package/dist/{exact-types-CflbJ9f3.d.ts.map → exact-types-BYFmYq44.d.ts.map} +1 -1
  60. package/dist/experiment/index.d.ts +24 -1
  61. package/dist/experiment/index.d.ts.map +1 -1
  62. package/dist/experiment/index.js +110 -71
  63. package/dist/experiment/index.js.map +1 -1
  64. package/dist/{exporters-Cl6IeNAu.js → exporters-DWvM16LE.js} +2 -2
  65. package/dist/{exporters-Cl6IeNAu.js.map → exporters-DWvM16LE.js.map} +1 -1
  66. package/dist/{external-optimizer-process-KVFGvYX1.js → external-optimizer-process-wOLfzsCC.js} +2 -2
  67. package/dist/{external-optimizer-process-KVFGvYX1.js.map → external-optimizer-process-wOLfzsCC.js.map} +1 -1
  68. package/dist/{external-optimizer-subprocess-XIHBOSKt.js → external-optimizer-subprocess-D670Oxf2.js} +4 -4
  69. package/dist/{external-optimizer-subprocess-XIHBOSKt.js.map → external-optimizer-subprocess-D670Oxf2.js.map} +1 -1
  70. package/dist/{feedback-trajectory-BWmhRBGu.d.ts → feedback-trajectory-DhB9WzYg.d.ts} +3 -3
  71. package/dist/{feedback-trajectory-BWmhRBGu.d.ts.map → feedback-trajectory-DhB9WzYg.d.ts.map} +1 -1
  72. package/dist/{findings-store-BMVQtEsm.js → findings-store-CvNo712L.js} +6 -6
  73. package/dist/{findings-store-BMVQtEsm.js.map → findings-store-CvNo712L.js.map} +1 -1
  74. package/dist/fuzz.d.ts +1 -1
  75. package/dist/fuzz.js +1 -1
  76. package/dist/{hf-dataset-D9f7-oX7.js → hf-dataset-CKxIJQba.js} +3 -3
  77. package/dist/{hf-dataset-D9f7-oX7.js.map → hf-dataset-CKxIJQba.js.map} +1 -1
  78. package/dist/hosted/index.js +1 -1
  79. package/dist/{index-CX-GAUpw.d.ts → index-CHxwfW5g.d.ts} +2 -2
  80. package/dist/{index-CX-GAUpw.d.ts.map → index-CHxwfW5g.d.ts.map} +1 -1
  81. package/dist/{index-BLGqZ81N.d.ts → index-CVFStrQD.d.ts} +8 -8
  82. package/dist/{index-BLGqZ81N.d.ts.map → index-CVFStrQD.d.ts.map} +1 -1
  83. package/dist/{index-9jJ2fKSX.d.ts → index-CalAsXMR.d.ts} +7 -5
  84. package/dist/index-CalAsXMR.d.ts.map +1 -0
  85. package/dist/{index-CiRwLv2R.d.ts → index-D7fmC-1K.d.ts} +3 -4
  86. package/dist/index-D7fmC-1K.d.ts.map +1 -0
  87. package/dist/{index-BiT6RtNH.d.ts → index-DAXfpVf7.d.ts} +10 -10
  88. package/dist/{index-BiT6RtNH.d.ts.map → index-DAXfpVf7.d.ts.map} +1 -1
  89. package/dist/{index-ZuWx52WG.d.ts → index-Q6DvdcwI.d.ts} +67 -24
  90. package/dist/index-Q6DvdcwI.d.ts.map +1 -0
  91. package/dist/index.d.ts +26 -26
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +615 -692
  94. package/dist/index.js.map +1 -1
  95. package/dist/{integrity-DOd9Q86O.js → integrity-C8oUeB0g.js} +322 -197
  96. package/dist/integrity-C8oUeB0g.js.map +1 -0
  97. package/dist/{integrity-_qgZLA5p.d.ts → integrity-CCwvezWS.d.ts} +2 -2
  98. package/dist/{integrity-_qgZLA5p.d.ts.map → integrity-CCwvezWS.d.ts.map} +1 -1
  99. package/dist/{journal-CR4QikYp.js → journal-C7om8Gum.js} +48 -38
  100. package/dist/journal-C7om8Gum.js.map +1 -0
  101. package/dist/judge-gate-Co5tuh57.js.map +1 -1
  102. package/dist/{judge-gate-DsL0yFcb.d.ts → judge-gate-Dc_mXQsL.d.ts} +2 -2
  103. package/dist/judge-gate-Dc_mXQsL.d.ts.map +1 -0
  104. package/dist/{kind-factory-Gy4fXixd.js → kind-factory-BhxbtUsQ.js} +2 -2
  105. package/dist/{kind-factory-Gy4fXixd.js.map → kind-factory-BhxbtUsQ.js.map} +1 -1
  106. package/dist/ledger-core/index.d.ts +1 -1
  107. package/dist/ledger-core/index.js +2 -2
  108. package/dist/ledger-core/lock-holder.d.ts +2 -0
  109. package/dist/ledger-core/lock-holder.js +181 -0
  110. package/dist/ledger-core/lock-holder.js.map +1 -0
  111. package/dist/{ledger-core-DrJhbms9.js → ledger-core-CAxUdDk0.js} +2 -2
  112. package/dist/{ledger-core-DrJhbms9.js.map → ledger-core-CAxUdDk0.js.map} +1 -1
  113. package/dist/{llm-client-BshCREn6.js → llm-client-DXuOTseU.js} +239 -249
  114. package/dist/llm-client-DXuOTseU.js.map +1 -0
  115. package/dist/{llm-judge-C8jMTNNG.js → llm-judge-Cc8vDJh_.js} +648 -459
  116. package/dist/llm-judge-Cc8vDJh_.js.map +1 -0
  117. package/dist/lock-holder-DaJbfpci.d.ts +86 -0
  118. package/dist/lock-holder-DaJbfpci.d.ts.map +1 -0
  119. package/dist/matrix/index.d.ts +2 -2
  120. package/dist/{matrix-DHe-dwVJ.d.ts → matrix-Cf-AGxGh.d.ts} +4 -4
  121. package/dist/{matrix-DHe-dwVJ.d.ts.map → matrix-Cf-AGxGh.d.ts.map} +1 -1
  122. package/dist/meta-eval/index.d.ts +2 -2
  123. package/dist/{mint-zszyYlpA.js → mint-CbdwjTPW.js} +2 -2
  124. package/dist/{mint-zszyYlpA.js.map → mint-CbdwjTPW.js.map} +1 -1
  125. package/dist/{mint-BRZXuwRi.d.ts → mint-CkzpVPdz.d.ts} +3 -3
  126. package/dist/{mint-BRZXuwRi.d.ts.map → mint-CkzpVPdz.d.ts.map} +1 -1
  127. package/dist/multishot/golden/index.d.ts +1 -1
  128. package/dist/multishot/index.d.ts +2 -2
  129. package/dist/multishot/index.js.map +1 -1
  130. package/dist/openapi.json +1 -1
  131. package/dist/{pareto-BzsxidFD.js → pareto-BiBnQXAE.js} +306 -212
  132. package/dist/pareto-BiBnQXAE.js.map +1 -0
  133. package/dist/pipelines/index.d.ts.map +1 -1
  134. package/dist/pipelines/index.js.map +1 -1
  135. package/dist/{prime-protocol-BWG2DQIk.d.ts → prime-protocol-CckHBxGu.d.ts} +3 -3
  136. package/dist/{prime-protocol-BWG2DQIk.d.ts.map → prime-protocol-CckHBxGu.d.ts.map} +1 -1
  137. package/dist/{promotion-gate-DaY95yU6.d.ts → promotion-gate-CkVZHagC.d.ts} +3 -3
  138. package/dist/{promotion-gate-DaY95yU6.d.ts.map → promotion-gate-CkVZHagC.d.ts.map} +1 -1
  139. package/dist/{proposal-findings-BbWidvUk.js → proposal-findings-E1aSC_cU.js} +2 -2
  140. package/dist/{proposal-findings-BbWidvUk.js.map → proposal-findings-E1aSC_cU.js.map} +1 -1
  141. package/dist/{registry-ssNoHzwD.d.ts → registry-B_yG-1jh.d.ts} +5 -5
  142. package/dist/{registry-ssNoHzwD.d.ts.map → registry-B_yG-1jh.d.ts.map} +1 -1
  143. package/dist/{render-C-w2EZ6p.js → render-Cs34y0iX.js} +404 -208
  144. package/dist/render-Cs34y0iX.js.map +1 -0
  145. package/dist/reporting.d.ts +3 -3
  146. package/dist/{researcher-0ABVIdGa.d.ts → researcher-H0p44OYC.d.ts} +5 -5
  147. package/dist/{researcher-0ABVIdGa.d.ts.map → researcher-H0p44OYC.d.ts.map} +1 -1
  148. package/dist/{reward-DrZ71vnf.d.ts → reward-BeUgVVC_.d.ts} +2 -2
  149. package/dist/{reward-DrZ71vnf.d.ts.map → reward-BeUgVVC_.d.ts.map} +1 -1
  150. package/dist/{reward-hacking-E52wq86n.d.ts → reward-hacking-WTxUbtbb.d.ts} +2 -2
  151. package/dist/{reward-hacking-E52wq86n.d.ts.map → reward-hacking-WTxUbtbb.d.ts.map} +1 -1
  152. package/dist/rl.d.ts +8 -8
  153. package/dist/rl.js +4 -4
  154. package/dist/rollout/index.d.ts +3 -3
  155. package/dist/rollout/index.js +5 -5
  156. package/dist/{rollout-D6C50mfA.js → rollout-Dd1ucT_M.js} +5 -5
  157. package/dist/{rollout-D6C50mfA.js.map → rollout-Dd1ucT_M.js.map} +1 -1
  158. package/dist/{rubric-predictive-validity-DiwT8PbL.d.ts → rubric-predictive-validity-noY7uE03.d.ts} +2 -2
  159. package/dist/{rubric-predictive-validity-DiwT8PbL.d.ts.map → rubric-predictive-validity-noY7uE03.d.ts.map} +1 -1
  160. package/dist/{run-record-CaxbLq6Y.d.ts → run-record-C3awiXPf.d.ts} +2 -2
  161. package/dist/{run-record-CaxbLq6Y.d.ts.map → run-record-C3awiXPf.d.ts.map} +1 -1
  162. package/dist/schema-C-ziyJD7.d.ts.map +1 -1
  163. package/dist/{schema-DxcKTzbi.js → schema-CvhfLjtZ.js} +77 -47
  164. package/dist/schema-CvhfLjtZ.js.map +1 -0
  165. package/dist/search/index.d.ts +2 -2
  166. package/dist/search/index.d.ts.map +1 -1
  167. package/dist/search/index.js +2 -2
  168. package/dist/{search-kernel-DxqjBxA-.d.ts → search-kernel-Dloxd6gs.d.ts} +5 -5
  169. package/dist/{search-kernel-DxqjBxA-.d.ts.map → search-kernel-Dloxd6gs.d.ts.map} +1 -1
  170. package/dist/{search-ledger-TUvB5gWH.js → search-ledger-CZRqtFbW.js} +252 -245
  171. package/dist/search-ledger-CZRqtFbW.js.map +1 -0
  172. package/dist/{search-ledger-file-UKCO2r8a.js → search-ledger-file-Bd5Tioq6.js} +3 -3
  173. package/dist/{search-ledger-file-UKCO2r8a.js.map → search-ledger-file-Bd5Tioq6.js.map} +1 -1
  174. package/dist/{search-shipper-Cw2z3-td.js → search-shipper-Dn3NLsuH.js} +3 -3
  175. package/dist/{search-shipper-Cw2z3-td.js.map → search-shipper-Dn3NLsuH.js.map} +1 -1
  176. package/dist/{search-summary-DQIvJsSB.js → search-summary-D4bwYnAE.js} +3 -3
  177. package/dist/{search-summary-DQIvJsSB.js.map → search-summary-D4bwYnAE.js.map} +1 -1
  178. package/dist/{server-DoVbqqtJ.js → server-8TS8XCvg.js} +3 -3
  179. package/dist/{server-DoVbqqtJ.js.map → server-8TS8XCvg.js.map} +1 -1
  180. package/dist/{single-run-lock-U58yf8N6.js → single-run-lock-Dekd8_Wv.js} +7 -7
  181. package/dist/single-run-lock-Dekd8_Wv.js.map +1 -0
  182. package/dist/{skillopt-optimization-method-kyL94-ri.js → skillopt-optimization-method-DLKqdhcR.js} +1384 -1059
  183. package/dist/skillopt-optimization-method-DLKqdhcR.js.map +1 -0
  184. package/dist/{statistical-heldout-C9AbgREN.d.ts → statistical-heldout-3z3I-kJN.d.ts} +3 -3
  185. package/dist/{statistical-heldout-C9AbgREN.d.ts.map → statistical-heldout-3z3I-kJN.d.ts.map} +1 -1
  186. package/dist/{store-otlp-BteDAbHK.js → store-otlp-dyWE3wAG.js} +2 -2
  187. package/dist/{store-otlp-BteDAbHK.js.map → store-otlp-dyWE3wAG.js.map} +1 -1
  188. package/dist/{store-tool-spans-D5l_OfTJ.js → store-tool-spans-DIUgZbzu.js} +3 -3
  189. package/dist/{store-tool-spans-D5l_OfTJ.js.map → store-tool-spans-DIUgZbzu.js.map} +1 -1
  190. package/dist/{store-tool-spans-DZS0HWVf.d.ts → store-tool-spans-DPwXHQkH.d.ts} +7 -7
  191. package/dist/{store-tool-spans-DZS0HWVf.d.ts.map → store-tool-spans-DPwXHQkH.d.ts.map} +1 -1
  192. package/dist/{summary-report-DM7tlml1.d.ts → summary-report-C8V49Jt3.d.ts} +18 -3
  193. package/dist/summary-report-C8V49Jt3.d.ts.map +1 -0
  194. package/dist/supervisor-run/index.d.ts.map +1 -1
  195. package/dist/supervisor-run/index.js +3 -3
  196. package/dist/{systemone-Bp_Ac0p1.d.ts → systemone-DVA7t76V.d.ts} +6 -6
  197. package/dist/{systemone-Bp_Ac0p1.d.ts.map → systemone-DVA7t76V.d.ts.map} +1 -1
  198. package/dist/{systemone-review-CwE6JGIp.d.ts → systemone-review-CUBMuTLi.d.ts} +2 -2
  199. package/dist/{systemone-review-CwE6JGIp.d.ts.map → systemone-review-CUBMuTLi.d.ts.map} +1 -1
  200. package/dist/systemone.d.ts +3 -3
  201. package/dist/{terminal-record-78g6E4vh.js → terminal-record-D4Rv-j1W.js} +241 -193
  202. package/dist/{terminal-record-78g6E4vh.js.map → terminal-record-D4Rv-j1W.js.map} +1 -1
  203. package/dist/{tool-groups-DyNz2JZ_.d.ts → tool-groups-LISbBWCg.d.ts} +3 -3
  204. package/dist/tool-groups-LISbBWCg.d.ts.map +1 -0
  205. package/dist/{trace-questions-xxwgsuMi.d.ts → trace-questions-C42fYEE4.d.ts} +4 -4
  206. package/dist/{trace-questions-xxwgsuMi.d.ts.map → trace-questions-C42fYEE4.d.ts.map} +1 -1
  207. package/dist/trace-repair/index.d.ts +3 -3
  208. package/dist/traces.d.ts +6 -6
  209. package/dist/traces.js +3 -3
  210. package/dist/trajectory-replay/index.d.ts +4 -1
  211. package/dist/trajectory-replay/index.d.ts.map +1 -1
  212. package/dist/trajectory-replay/index.js +854 -823
  213. package/dist/trajectory-replay/index.js.map +1 -1
  214. package/dist/{tree-BGRglkKd.js → tree-DSqwJpL9.js} +122 -14
  215. package/dist/tree-DSqwJpL9.js.map +1 -0
  216. package/dist/{types-CW8ewATZ.d.ts → types-8yQzNm8u.d.ts} +4 -4
  217. package/dist/{types-CW8ewATZ.d.ts.map → types-8yQzNm8u.d.ts.map} +1 -1
  218. package/dist/{types-D8GhJoHk.d.ts → types-CHfn1zg5.d.ts} +70 -72
  219. package/dist/types-CHfn1zg5.d.ts.map +1 -0
  220. package/dist/{types-DtMbFw6U.d.ts → types-D8GXK9Z5.d.ts} +3 -3
  221. package/dist/{types-DtMbFw6U.d.ts.map → types-D8GXK9Z5.d.ts.map} +1 -1
  222. package/dist/{types-D-mgRzlh.d.ts → types-eMhdacVp.d.ts} +2 -2
  223. package/dist/{types-D-mgRzlh.d.ts.map → types-eMhdacVp.d.ts.map} +1 -1
  224. package/dist/wire/index.d.ts +3 -3
  225. package/dist/wire/index.js +1 -1
  226. package/docs/campaign-proposers.md +16 -0
  227. package/docs/concepts.md +31 -0
  228. package/docs/design/statistics-decisions.md +1 -1
  229. package/docs/eval-surface-map.md +1 -0
  230. package/docs/profile-json-identity.md +1 -2
  231. package/docs/public-api.md +100 -88
  232. package/package.json +8 -6
  233. package/dist/benchmark-command-xQK8nOI6.js.map +0 -1
  234. package/dist/campaign-CJGkxAQ6.js.map +0 -1
  235. package/dist/campaign-evidence-CQYw8_0H.js.map +0 -1
  236. package/dist/cost-ledger-D0352Z4d.js.map +0 -1
  237. package/dist/cost-ledger-Jk62OBfF.d.ts.map +0 -1
  238. package/dist/define-agent-eval-BDxNlP3D.js.map +0 -1
  239. package/dist/eval-campaign-BLEfBGbA.js +0 -343
  240. package/dist/eval-campaign-BLEfBGbA.js.map +0 -1
  241. package/dist/index-9jJ2fKSX.d.ts.map +0 -1
  242. package/dist/index-CiRwLv2R.d.ts.map +0 -1
  243. package/dist/index-ZuWx52WG.d.ts.map +0 -1
  244. package/dist/integrity-DOd9Q86O.js.map +0 -1
  245. package/dist/journal-CR4QikYp.js.map +0 -1
  246. package/dist/judge-gate-DsL0yFcb.d.ts.map +0 -1
  247. package/dist/llm-client-BshCREn6.js.map +0 -1
  248. package/dist/llm-judge-C8jMTNNG.js.map +0 -1
  249. package/dist/pareto-BzsxidFD.js.map +0 -1
  250. package/dist/render-C-w2EZ6p.js.map +0 -1
  251. package/dist/schema-DxcKTzbi.js.map +0 -1
  252. package/dist/search-ledger-TUvB5gWH.js.map +0 -1
  253. package/dist/single-run-lock-U58yf8N6.js.map +0 -1
  254. package/dist/skillopt-optimization-method-kyL94-ri.js.map +0 -1
  255. package/dist/summary-report-DM7tlml1.d.ts.map +0 -1
  256. package/dist/tool-groups-DyNz2JZ_.d.ts.map +0 -1
  257. package/dist/tree-BGRglkKd.js.map +0 -1
  258. package/dist/types-D8GhJoHk.d.ts.map +0 -1
@@ -1,3 +1,3 @@
1
- import { A as AtomicFileLock, C as LedgerTrustedHead, D as LedgerFileContext, E as FileLockResult, F as tryAcquireAtomicFileLock, M as AtomicFileLockOptions, N as AtomicFileLockOwner, O as tryWithLedgerFileLock, P as AtomicFileLockUnavailable, S as LedgerAnchoredEntry, T as LedgerTrustedHeadSubject, _ as LedgerJournalCodec, a as merkleInclusionProof, b as LedgerProjectorSnapshotCodec, c as merkleSalt, d as FileLedgerJournalOptions, f as LedgerAppendOptions, g as LedgerEventBase, h as LedgerEntryOf, i as MerkleVerification, j as AtomicFileLockAcquisition, k as writeLedgerFileAtomically, l as verifyMerkleInclusion, m as LedgerChainFields, n as MerkleConsistencyProof, o as merkleLeafHash, p as LedgerAppendResult, r as MerkleInclusionProof, s as merkleRoot, t as LedgerProjectorSnapshot, u as FileLedgerJournal, v as LedgerLineContext, w as LedgerTrustedHeadRemoval, x as LedgerTextStore, y as LedgerProjector } from "../index-9jJ2fKSX.js";
1
+ import { A as AtomicFileLock, C as LedgerTrustedHead, D as LedgerFileContext, E as FileLockResult, F as tryAcquireAtomicFileLock, M as AtomicFileLockOptions, N as AtomicFileLockOwner, O as tryWithLedgerFileLock, P as AtomicFileLockUnavailable, S as LedgerAnchoredEntry, T as LedgerTrustedHeadSubject, _ as LedgerJournalCodec, a as merkleInclusionProof, b as LedgerProjectorSnapshotCodec, c as merkleSalt, d as FileLedgerJournalOptions, f as LedgerAppendOptions, g as LedgerEventBase, h as LedgerEntryOf, i as MerkleVerification, j as AtomicFileLockAcquisition, k as writeLedgerFileAtomically, l as verifyMerkleInclusion, m as LedgerChainFields, n as MerkleConsistencyProof, o as merkleLeafHash, p as LedgerAppendResult, r as MerkleInclusionProof, s as merkleRoot, t as LedgerProjectorSnapshot, u as FileLedgerJournal, v as LedgerLineContext, w as LedgerTrustedHeadRemoval, x as LedgerTextStore, y as LedgerProjector } from "../index-CalAsXMR.js";
2
2
  import { a as hashCanonical, i as canonicalString, n as LedgerCanonicalizationError, o as jsonDocument, r as LedgerHash, t as LEDGER_HASH_PATTERN } from "../canonical-CFpojCN5.js";
3
3
  export { type AtomicFileLock, type AtomicFileLockAcquisition, type AtomicFileLockOptions, type AtomicFileLockOwner, type AtomicFileLockUnavailable, FileLedgerJournal, type FileLedgerJournalOptions, type FileLockResult, LEDGER_HASH_PATTERN, type LedgerAnchoredEntry, type LedgerAppendOptions, type LedgerAppendResult, LedgerCanonicalizationError, type LedgerChainFields, type LedgerEntryOf, type LedgerEventBase, type LedgerFileContext, type LedgerHash, type LedgerJournalCodec, type LedgerLineContext, type LedgerProjector, type LedgerProjectorSnapshot, type LedgerProjectorSnapshotCodec, type LedgerTextStore, type LedgerTrustedHead, type LedgerTrustedHeadRemoval, type LedgerTrustedHeadSubject, type MerkleConsistencyProof, type MerkleInclusionProof, type MerkleVerification, canonicalString, hashCanonical, jsonDocument, merkleInclusionProof, merkleLeafHash, merkleRoot, merkleSalt, tryAcquireAtomicFileLock, tryWithLedgerFileLock, verifyMerkleInclusion, writeLedgerFileAtomically };
@@ -1,4 +1,4 @@
1
1
  import { a as hashCanonical, n as LedgerCanonicalizationError, o as jsonDocument, r as canonicalString, t as LEDGER_HASH_PATTERN } from "../canonical-Dq2hOQ8L.js";
2
- import { c as tryWithLedgerFileLock, f as tryAcquireAtomicFileLock, t as FileLedgerJournal, u as writeLedgerFileAtomically } from "../journal-CR4QikYp.js";
3
- import { a as verifyMerkleInclusion, i as merkleSalt, n as merkleLeafHash, r as merkleRoot, t as merkleInclusionProof } from "../ledger-core-DrJhbms9.js";
2
+ import { c as tryWithLedgerFileLock, f as tryAcquireAtomicFileLock, t as FileLedgerJournal, u as writeLedgerFileAtomically } from "../journal-C7om8Gum.js";
3
+ import { a as verifyMerkleInclusion, i as merkleSalt, n as merkleLeafHash, r as merkleRoot, t as merkleInclusionProof } from "../ledger-core-CAxUdDk0.js";
4
4
  export { FileLedgerJournal, LEDGER_HASH_PATTERN, LedgerCanonicalizationError, canonicalString, hashCanonical, jsonDocument, merkleInclusionProof, merkleLeafHash, merkleRoot, merkleSalt, tryAcquireAtomicFileLock, tryWithLedgerFileLock, verifyMerkleInclusion, writeLedgerFileAtomically };
@@ -0,0 +1,2 @@
1
+ import { a as LockHolderVerdict, c as lockHolderVerdict, d as readLockHolderIdentity, i as LockHolderUnknownReason, l as lockIdentity, n as LockHolderIdentity, o as LockIdentity, r as LockHolderRecord, s as LockIdentityStats, t as LockHolderDeathReason, u as parseLockHolderRecord } from "../lock-holder-DaJbfpci.js";
2
+ export { LockHolderDeathReason, LockHolderIdentity, LockHolderRecord, LockHolderUnknownReason, LockHolderVerdict, LockIdentity, LockIdentityStats, lockHolderVerdict, lockIdentity, parseLockHolderRecord, readLockHolderIdentity };
@@ -0,0 +1,181 @@
1
+ import { readFileSync, readlinkSync } from "node:fs";
2
+ import { hostname } from "node:os";
3
+ //#region src/ledger-core/lock-holder.ts
4
+ /**
5
+ * The one dead-owner rule: whether a lock's recorded holder is provably dead.
6
+ *
7
+ * A lock is safe to take over only when its holder is proved dead. A pid alone
8
+ * proves nothing: the OS hands a dead holder's pid to a later process, and a
9
+ * filesystem hands a removed lock's inode to the next lock. So a holder record
10
+ * carries the pid's OS start token, the boot id, the pid namespace, the host,
11
+ * and the identity of the lock it was written for, and the verdict is `dead`
12
+ * only when those facts prove it. Anything the record or this host cannot
13
+ * settle is `unknown`, and a caller keeps treating the lock as held.
14
+ *
15
+ * This module imports only Node built-ins, so lock owners in other packages can
16
+ * import `@tangle-network/agent-eval/lock-holder` without loading the rest of
17
+ * the package.
18
+ */
19
+ function lockIdentity(stats) {
20
+ return {
21
+ dev: stats.dev.toString(),
22
+ ino: stats.ino.toString(),
23
+ birthtimeNs: stats.birthtimeNs.toString()
24
+ };
25
+ }
26
+ /**
27
+ * The identity to record for `pid` on this host. The start token is read for
28
+ * `pid` itself, so a lock taken on behalf of another live process records that
29
+ * process. Fields the host cannot report are omitted, which leaves a later
30
+ * verdict on the record `unknown` rather than wrong.
31
+ */
32
+ function readLockHolderIdentity(pid = process.pid) {
33
+ const processStart = readProcessStart(pid);
34
+ const { bootId, pidNamespace } = ownHostIdentity();
35
+ return {
36
+ pid,
37
+ host: hostname(),
38
+ ...processStart ? { processStart } : {},
39
+ ...bootId ? { bootId } : {},
40
+ ...pidNamespace ? { pidNamespace } : {}
41
+ };
42
+ }
43
+ /**
44
+ * Decide whether `record`'s holder is dead, alive, or unknown.
45
+ *
46
+ * `currentLock` is the identity of the lock as it is now. `dead` needs a record
47
+ * with a start token and a lock identity, written for this very lock (equal dev,
48
+ * ino and a nonzero birthtime), on this host and pid namespace, and then a
49
+ * rebooted host, a gone pid, or a pid whose start token changed. `alive` needs
50
+ * the pid present with the recorded start token. Everything else is `unknown`,
51
+ * so a live holder's lock is never taken.
52
+ */
53
+ function lockHolderVerdict(record, currentLock) {
54
+ if (!record || !Number.isSafeInteger(record.pid) || record.pid <= 0) return unknown("unreadable record");
55
+ if (record.host !== hostname()) return unknown("other host");
56
+ if (!record.processStart || !record.lock) return unknown("incomplete record");
57
+ if (!currentLock || currentLock.birthtimeNs === "0" || currentLock.dev !== record.lock.dev || currentLock.ino !== record.lock.ino || currentLock.birthtimeNs !== record.lock.birthtimeNs) return unknown("lock changed");
58
+ const own = ownHostIdentity();
59
+ if (record.pidNamespace !== own.pidNamespace) return unknown("other pid namespace");
60
+ if (record.bootId === void 0 !== (own.bootId === void 0)) return unknown("boot id unavailable");
61
+ if (record.bootId !== own.bootId) return {
62
+ liveness: "dead",
63
+ reason: "host rebooted"
64
+ };
65
+ if (pidIsGone(record.pid)) return {
66
+ liveness: "dead",
67
+ reason: "pid gone"
68
+ };
69
+ const start = readProcessStart(record.pid);
70
+ if (start === void 0) return unknown("start token unavailable");
71
+ if (start !== record.processStart) return {
72
+ liveness: "dead",
73
+ reason: "pid reused"
74
+ };
75
+ return { liveness: "alive" };
76
+ }
77
+ /**
78
+ * Read a holder record from parsed JSON. The required fields are `pid` and
79
+ * `host`; an identity field that is missing or malformed is dropped, which
80
+ * leaves the holder named but never provably dead.
81
+ */
82
+ function parseLockHolderRecord(value) {
83
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
84
+ const record = value;
85
+ if (!Number.isSafeInteger(record.pid) || record.pid <= 0) return void 0;
86
+ if (typeof record.host !== "string" || record.host.length === 0) return void 0;
87
+ const processStart = text(record.processStart);
88
+ const bootId = text(record.bootId);
89
+ const pidNamespace = text(record.pidNamespace);
90
+ const lock = parseLockIdentity(record.lock);
91
+ return {
92
+ pid: record.pid,
93
+ host: record.host,
94
+ ...processStart ? { processStart } : {},
95
+ ...bootId ? { bootId } : {},
96
+ ...pidNamespace ? { pidNamespace } : {},
97
+ ...lock ? { lock } : {}
98
+ };
99
+ }
100
+ function parseLockIdentity(value) {
101
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
102
+ const lock = value;
103
+ if (!decimal(lock.dev) || !decimal(lock.ino) || !decimal(lock.birthtimeNs)) return void 0;
104
+ return {
105
+ dev: lock.dev,
106
+ ino: lock.ino,
107
+ birthtimeNs: lock.birthtimeNs
108
+ };
109
+ }
110
+ function unknown(reason) {
111
+ return {
112
+ liveness: "unknown",
113
+ reason
114
+ };
115
+ }
116
+ function text(field) {
117
+ return typeof field === "string" && field.length > 0 ? field : void 0;
118
+ }
119
+ function decimal(field) {
120
+ return typeof field === "string" && /^\d+$/u.test(field);
121
+ }
122
+ /** Only ESRCH proves a pid gone; EPERM means it exists under another user. */
123
+ function pidIsGone(pid) {
124
+ try {
125
+ process.kill(pid, 0);
126
+ return false;
127
+ } catch (error) {
128
+ return error instanceof Error && "code" in error && error.code === "ESRCH";
129
+ }
130
+ }
131
+ let hostIdentity;
132
+ function ownHostIdentity() {
133
+ if (hostIdentity) return hostIdentity;
134
+ const bootId = readOptional(() => readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim());
135
+ const pidNamespace = readOptional(() => readlinkSync("/proc/self/ns/pid"));
136
+ hostIdentity = {
137
+ ...bootId ? { bootId } : {},
138
+ ...pidNamespace ? { pidNamespace } : {}
139
+ };
140
+ return hostIdentity;
141
+ }
142
+ /**
143
+ * The OS start token of a live pid: the same for a process's whole life and
144
+ * different for every later holder of its pid. `undefined` when the host cannot
145
+ * report one.
146
+ */
147
+ function readProcessStart(pid) {
148
+ if (!Number.isSafeInteger(pid) || pid <= 0 || process.platform === "win32") return void 0;
149
+ if (process.platform === "linux") {
150
+ const stat = readOptional(() => readFileSync(`/proc/${pid}/stat`, "utf8"));
151
+ if (stat === void 0) return void 0;
152
+ const startTime = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u)[19];
153
+ return startTime !== void 0 && /^\d+$/u.test(startTime) ? startTime : void 0;
154
+ }
155
+ const childProcess = process.getBuiltinModule?.("node:child_process");
156
+ if (!childProcess) return void 0;
157
+ return readOptional(() => childProcess.execFileSync("ps", [
158
+ "-o",
159
+ "lstart=",
160
+ "-p",
161
+ String(pid)
162
+ ], {
163
+ encoding: "utf8",
164
+ stdio: [
165
+ "ignore",
166
+ "pipe",
167
+ "ignore"
168
+ ]
169
+ }).trim());
170
+ }
171
+ function readOptional(read) {
172
+ try {
173
+ return read() || void 0;
174
+ } catch {
175
+ return;
176
+ }
177
+ }
178
+ //#endregion
179
+ export { lockHolderVerdict, lockIdentity, parseLockHolderRecord, readLockHolderIdentity };
180
+
181
+ //# sourceMappingURL=lock-holder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock-holder.js","names":[],"sources":["../../src/ledger-core/lock-holder.ts"],"sourcesContent":["/**\n * The one dead-owner rule: whether a lock's recorded holder is provably dead.\n *\n * A lock is safe to take over only when its holder is proved dead. A pid alone\n * proves nothing: the OS hands a dead holder's pid to a later process, and a\n * filesystem hands a removed lock's inode to the next lock. So a holder record\n * carries the pid's OS start token, the boot id, the pid namespace, the host,\n * and the identity of the lock it was written for, and the verdict is `dead`\n * only when those facts prove it. Anything the record or this host cannot\n * settle is `unknown`, and a caller keeps treating the lock as held.\n *\n * This module imports only Node built-ins, so lock owners in other packages can\n * import `@tangle-network/agent-eval/lock-holder` without loading the rest of\n * the package.\n */\n\nimport { readFileSync, readlinkSync } from 'node:fs'\nimport { hostname } from 'node:os'\n\n/**\n * Identity of one lock path's inode, as decimal strings from a bigint `stat`.\n * ext4 hands a removed directory's inode to the next one at once (two\n * directories created 1.4 ms apart got the same inode on drew-gtr-pro), so dev\n * and ino alone can match a stale record to a live holder's new lock; the\n * nanosecond birthtime tells them apart.\n */\nexport interface LockIdentity {\n readonly dev: string\n readonly ino: string\n readonly birthtimeNs: string\n}\n\n/** Who holds a lock: the process and the facts that tell it from a later holder of its pid. */\nexport interface LockHolderIdentity {\n readonly pid: number\n readonly host: string\n /** OS start token of `pid`: Linux `/proc/<pid>/stat` starttime, elsewhere `ps` lstart. */\n readonly processStart?: string\n readonly bootId?: string\n readonly pidNamespace?: string\n}\n\n/** A holder record as a lock owner writes it: the holder and the lock it was written for. */\nexport interface LockHolderRecord extends LockHolderIdentity {\n readonly lock?: LockIdentity\n}\n\nexport type LockHolderDeathReason = 'pid gone' | 'pid reused' | 'host rebooted'\n\nexport type LockHolderUnknownReason =\n | 'unreadable record'\n | 'other host'\n | 'incomplete record'\n | 'lock changed'\n | 'other pid namespace'\n | 'boot id unavailable'\n | 'start token unavailable'\n\nexport type LockHolderVerdict =\n | { readonly liveness: 'dead'; readonly reason: LockHolderDeathReason }\n | { readonly liveness: 'alive' }\n | { readonly liveness: 'unknown'; readonly reason: LockHolderUnknownReason }\n\n/** Stat fields `lockIdentity` reads; pass `statSync(path, { bigint: true })` or its fstat/lstat. */\nexport interface LockIdentityStats {\n readonly dev: bigint\n readonly ino: bigint\n readonly birthtimeNs: bigint\n}\n\nexport function lockIdentity(stats: LockIdentityStats): LockIdentity {\n return {\n dev: stats.dev.toString(),\n ino: stats.ino.toString(),\n birthtimeNs: stats.birthtimeNs.toString(),\n }\n}\n\n/**\n * The identity to record for `pid` on this host. The start token is read for\n * `pid` itself, so a lock taken on behalf of another live process records that\n * process. Fields the host cannot report are omitted, which leaves a later\n * verdict on the record `unknown` rather than wrong.\n */\nexport function readLockHolderIdentity(pid: number = process.pid): LockHolderIdentity {\n const processStart = readProcessStart(pid)\n const { bootId, pidNamespace } = ownHostIdentity()\n return {\n pid,\n host: hostname(),\n ...(processStart ? { processStart } : {}),\n ...(bootId ? { bootId } : {}),\n ...(pidNamespace ? { pidNamespace } : {}),\n }\n}\n\n/**\n * Decide whether `record`'s holder is dead, alive, or unknown.\n *\n * `currentLock` is the identity of the lock as it is now. `dead` needs a record\n * with a start token and a lock identity, written for this very lock (equal dev,\n * ino and a nonzero birthtime), on this host and pid namespace, and then a\n * rebooted host, a gone pid, or a pid whose start token changed. `alive` needs\n * the pid present with the recorded start token. Everything else is `unknown`,\n * so a live holder's lock is never taken.\n */\nexport function lockHolderVerdict(\n record: LockHolderRecord | undefined,\n currentLock: LockIdentity | undefined,\n): LockHolderVerdict {\n if (!record || !Number.isSafeInteger(record.pid) || record.pid <= 0) {\n return unknown('unreadable record')\n }\n if (record.host !== hostname()) return unknown('other host')\n if (!record.processStart || !record.lock) return unknown('incomplete record')\n if (\n !currentLock ||\n currentLock.birthtimeNs === '0' ||\n currentLock.dev !== record.lock.dev ||\n currentLock.ino !== record.lock.ino ||\n currentLock.birthtimeNs !== record.lock.birthtimeNs\n ) {\n return unknown('lock changed')\n }\n const own = ownHostIdentity()\n if (record.pidNamespace !== own.pidNamespace) return unknown('other pid namespace')\n if ((record.bootId === undefined) !== (own.bootId === undefined)) {\n return unknown('boot id unavailable')\n }\n if (record.bootId !== own.bootId) return { liveness: 'dead', reason: 'host rebooted' }\n if (pidIsGone(record.pid)) return { liveness: 'dead', reason: 'pid gone' }\n const start = readProcessStart(record.pid)\n if (start === undefined) return unknown('start token unavailable')\n if (start !== record.processStart) return { liveness: 'dead', reason: 'pid reused' }\n return { liveness: 'alive' }\n}\n\n/**\n * Read a holder record from parsed JSON. The required fields are `pid` and\n * `host`; an identity field that is missing or malformed is dropped, which\n * leaves the holder named but never provably dead.\n */\nexport function parseLockHolderRecord(value: unknown): LockHolderRecord | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const record = value as Record<string, unknown>\n if (!Number.isSafeInteger(record.pid) || (record.pid as number) <= 0) return undefined\n if (typeof record.host !== 'string' || record.host.length === 0) return undefined\n const processStart = text(record.processStart)\n const bootId = text(record.bootId)\n const pidNamespace = text(record.pidNamespace)\n const lock = parseLockIdentity(record.lock)\n return {\n pid: record.pid as number,\n host: record.host,\n ...(processStart ? { processStart } : {}),\n ...(bootId ? { bootId } : {}),\n ...(pidNamespace ? { pidNamespace } : {}),\n ...(lock ? { lock } : {}),\n }\n}\n\nfunction parseLockIdentity(value: unknown): LockIdentity | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const lock = value as Record<string, unknown>\n if (!decimal(lock.dev) || !decimal(lock.ino) || !decimal(lock.birthtimeNs)) return undefined\n return { dev: lock.dev, ino: lock.ino, birthtimeNs: lock.birthtimeNs }\n}\n\nfunction unknown(reason: LockHolderUnknownReason): LockHolderVerdict {\n return { liveness: 'unknown', reason }\n}\n\nfunction text(field: unknown): string | undefined {\n return typeof field === 'string' && field.length > 0 ? field : undefined\n}\n\nfunction decimal(field: unknown): field is string {\n return typeof field === 'string' && /^\\d+$/u.test(field)\n}\n\n/** Only ESRCH proves a pid gone; EPERM means it exists under another user. */\nfunction pidIsGone(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return false\n } catch (error) {\n return error instanceof Error && 'code' in error && error.code === 'ESRCH'\n }\n}\n\ninterface HostIdentity {\n readonly bootId?: string\n readonly pidNamespace?: string\n}\n\nlet hostIdentity: HostIdentity | undefined\n\nfunction ownHostIdentity(): HostIdentity {\n if (hostIdentity) return hostIdentity\n const bootId = readOptional(() => readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim())\n const pidNamespace = readOptional(() => readlinkSync('/proc/self/ns/pid'))\n hostIdentity = {\n ...(bootId ? { bootId } : {}),\n ...(pidNamespace ? { pidNamespace } : {}),\n }\n return hostIdentity\n}\n\n/**\n * The OS start token of a live pid: the same for a process's whole life and\n * different for every later holder of its pid. `undefined` when the host cannot\n * report one.\n */\nfunction readProcessStart(pid: number): string | undefined {\n if (!Number.isSafeInteger(pid) || pid <= 0 || process.platform === 'win32') return undefined\n if (process.platform === 'linux') {\n const stat = readOptional(() => readFileSync(`/proc/${pid}/stat`, 'utf8'))\n if (stat === undefined) return undefined\n // The comm field is parenthesized and may hold spaces, so fields are counted after its close.\n const startTime = stat\n .slice(stat.lastIndexOf(')') + 1)\n .trim()\n .split(/\\s+/u)[19]\n return startTime !== undefined && /^\\d+$/u.test(startTime) ? startTime : undefined\n }\n // `ps` lstart has 1 s resolution, so a pid reused within the same second reads\n // as alive and keeps the lock: the safe direction. child_process is resolved\n // on use so bundles that import this module never load it at startup.\n const childProcess = process.getBuiltinModule?.('node:child_process') as\n | typeof import('node:child_process')\n | undefined\n if (!childProcess) return undefined\n return readOptional(() =>\n childProcess\n .execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n .trim(),\n )\n}\n\nfunction readOptional(read: () => string): string | undefined {\n try {\n return read() || undefined\n } catch {\n return undefined\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { s as ValidationError } from "./errors-BcOs5MKW.js";
2
2
  import { t as LEDGER_HASH_PATTERN } from "./canonical-Dq2hOQ8L.js";
3
- import "./journal-CR4QikYp.js";
3
+ import "./journal-C7om8Gum.js";
4
4
  import { sha256Bytes } from "@tangle-network/agent-interface";
5
5
  //#region src/ledger-core/merkle.ts
6
6
  /**
@@ -166,4 +166,4 @@ function fromHex(hex) {
166
166
  //#endregion
167
167
  export { verifyMerkleInclusion as a, merkleSalt as i, merkleLeafHash as n, merkleRoot as r, merkleInclusionProof as t };
168
168
 
169
- //# sourceMappingURL=ledger-core-DrJhbms9.js.map
169
+ //# sourceMappingURL=ledger-core-CAxUdDk0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ledger-core-DrJhbms9.js","names":[],"sources":["../src/ledger-core/merkle.ts"],"sourcesContent":["/**\n * Merkle proofs over an append-only list of leaves (RFC 9162 §2.1, the\n * Certificate Transparency tree).\n *\n * A hash chain proves a whole log against its head, but proving one entry means\n * replaying everything before it. This tree proves any one leaf against a root\n * with ⌈log₂ n⌉ hashes (inclusion), and proves that a larger tree only appended\n * to a smaller one (consistency). A verifier holding a root can therefore check\n * a single event, or that a later checkpoint extends an earlier one, without\n * reading the rest of the log.\n *\n * Leaves and interior nodes are domain-separated (0x00 and 0x01 prefixes), so a\n * leaf can never be presented as an interior node. Content that may later be\n * redacted takes a random 32-byte salt: a verifier then needs only the leaf's\n * hash, and short content cannot be guessed back from that hash. The salt must\n * be stored apart from anything that is shared after redaction.\n *\n * Builders refuse malformed input by throwing; verifiers never throw and return\n * a typed outcome, because a proof is external evidence and a bad one is a\n * finding, not a crash.\n */\nimport { sha256Bytes } from '@tangle-network/agent-interface'\nimport { ValidationError } from '../errors'\nimport { LEDGER_HASH_PATTERN, type LedgerHash } from './canonical'\n\n/** Proof that one leaf is at `leafIndex` in a tree of `treeSize` leaves. */\nexport interface MerkleInclusionProof {\n readonly leafIndex: number\n readonly treeSize: number\n readonly path: readonly LedgerHash[]\n}\n\n/** Proof that the first `oldSize` leaves of a `newSize` tree are unchanged. */\nexport interface MerkleConsistencyProof {\n readonly oldSize: number\n readonly newSize: number\n readonly path: readonly LedgerHash[]\n}\n\nexport type MerkleVerification =\n | { readonly verified: true }\n | { readonly verified: false; readonly reason: string }\n\nconst SALT_PATTERN = /^[a-f0-9]{64}$/\nconst LEAF_PREFIX = 0x00\nconst NODE_PREFIX = 0x01\nconst encoder = new TextEncoder()\n\n/** Root of the empty tree: SHA-256 of no bytes. */\nconst MERKLE_EMPTY_ROOT: LedgerHash = sha256Bytes(new Uint8Array(0)) as LedgerHash\n\n/** A fresh random salt for {@link merkleLeafHash}: 32 bytes as 64 lowercase hex characters. */\nexport function merkleSalt(): string {\n return toHex(globalThis.crypto.getRandomValues(new Uint8Array(32)))\n}\n\n/**\n * Leaf hash of `content`: SHA-256(0x00 ‖ salt ‖ content). Without a salt this is\n * exactly the RFC 9162 leaf hash. Strings are hashed as UTF-8.\n */\nexport function merkleLeafHash(content: Uint8Array | string, salt?: string): LedgerHash {\n const bytes = typeof content === 'string' ? encoder.encode(content) : content\n if (salt === undefined) return digest(LEAF_PREFIX, bytes)\n if (!SALT_PATTERN.test(salt)) {\n throw new ValidationError('merkle salt must be 32 bytes as 64 lowercase hex characters')\n }\n return digest(LEAF_PREFIX, fromHex(salt), bytes)\n}\n\n/** Root over leaf hashes, in order. The empty list has {@link MERKLE_EMPTY_ROOT}. */\nexport function merkleRoot(leaves: readonly LedgerHash[]): LedgerHash {\n const nodes = decodeLeaves(leaves)\n return nodes.length === 0 ? MERKLE_EMPTY_ROOT : toLedgerHash(subtreeRoot(nodes, 0, nodes.length))\n}\n\n/** Inclusion proof for the leaf at `leafIndex` (RFC 9162 §2.1.3.1). */\nexport function merkleInclusionProof(\n leaves: readonly LedgerHash[],\n leafIndex: number,\n): MerkleInclusionProof {\n const nodes = decodeLeaves(leaves)\n if (!Number.isSafeInteger(leafIndex) || leafIndex < 0 || leafIndex >= nodes.length) {\n throw new ValidationError(\n `merkle leaf index ${leafIndex} is outside a tree of ${nodes.length} leaves`,\n )\n }\n const path: Uint8Array[] = []\n inclusionPath(nodes, leafIndex, 0, nodes.length, path)\n return { leafIndex, treeSize: nodes.length, path: path.map(toLedgerHash) }\n}\n\n\n\n/** Check that `leaf` is in the tree with `root` at the proof's index (RFC 9162 §2.1.3.2). */\nexport function verifyMerkleInclusion(\n leaf: LedgerHash,\n proof: MerkleInclusionProof,\n root: LedgerHash,\n): MerkleVerification {\n const { leafIndex, treeSize } = proof\n if (!isSize(treeSize) || !isSize(leafIndex) || leafIndex >= treeSize) {\n return refused(`leaf index ${leafIndex} is outside a tree of ${treeSize} leaves`)\n }\n const decoded = decodeAll([leaf, root, ...proof.path])\n if (decoded === undefined) return refused('proof carries a malformed hash')\n const [leafBytes, rootBytes, ...path] = decoded as [Uint8Array, Uint8Array, ...Uint8Array[]]\n let fn = leafIndex\n let sn = treeSize - 1\n let r = leafBytes\n for (const p of path) {\n if (sn === 0) return refused('proof path is longer than the tree is deep')\n if (fn % 2 === 1 || fn === sn) {\n r = node(p, r)\n if (fn % 2 === 0) {\n while (fn % 2 === 0 && fn !== 0) {\n fn = Math.floor(fn / 2)\n sn = Math.floor(sn / 2)\n }\n }\n } else {\n r = node(r, p)\n }\n fn = Math.floor(fn / 2)\n sn = Math.floor(sn / 2)\n }\n if (sn !== 0) return refused('proof path is shorter than the tree is deep')\n return equal(r, rootBytes) ? { verified: true } : refused('leaf does not hash to the root')\n}\n\n\n\nfunction subtreeRoot(nodes: readonly Uint8Array[], start: number, end: number): Uint8Array {\n if (end - start === 1) return nodes[start] as Uint8Array\n const k = largestPowerOfTwoBelow(end - start)\n return node(subtreeRoot(nodes, start, start + k), subtreeRoot(nodes, start + k, end))\n}\n\nfunction inclusionPath(\n nodes: readonly Uint8Array[],\n index: number,\n start: number,\n end: number,\n path: Uint8Array[],\n): void {\n if (end - start === 1) return\n const k = largestPowerOfTwoBelow(end - start)\n if (index < start + k) {\n inclusionPath(nodes, index, start, start + k, path)\n path.push(subtreeRoot(nodes, start + k, end))\n } else {\n inclusionPath(nodes, index, start + k, end, path)\n path.push(subtreeRoot(nodes, start, start + k))\n }\n}\n\n\n\nfunction node(left: Uint8Array, right: Uint8Array): Uint8Array {\n return fromHex(digest(NODE_PREFIX, left, right).slice('sha256:'.length))\n}\n\nfunction digest(prefix: number, ...parts: Uint8Array[]): LedgerHash {\n const length = parts.reduce((total, part) => total + part.length, 1)\n const bytes = new Uint8Array(length)\n bytes[0] = prefix\n let offset = 1\n for (const part of parts) {\n bytes.set(part, offset)\n offset += part.length\n }\n return sha256Bytes(bytes) as LedgerHash\n}\n\nfunction decodeLeaves(leaves: readonly LedgerHash[]): Uint8Array[] {\n const decoded = decodeAll(leaves)\n if (decoded === undefined) {\n throw new ValidationError('merkle leaves must be sha256:<64 lowercase hex> hashes')\n }\n return decoded\n}\n\nfunction decodeAll(hashes: readonly string[]): Uint8Array[] | undefined {\n const out: Uint8Array[] = []\n for (const hash of hashes) {\n if (typeof hash !== 'string' || !LEDGER_HASH_PATTERN.test(hash)) return undefined\n out.push(fromHex(hash.slice('sha256:'.length)))\n }\n return out\n}\n\nfunction toLedgerHash(bytes: Uint8Array): LedgerHash {\n return `sha256:${toHex(bytes)}`\n}\n\nfunction largestPowerOfTwoBelow(n: number): number {\n let k = 1\n while (k * 2 < n) k *= 2\n return k\n}\n\n\n\nfunction isSize(n: number): boolean {\n return Number.isSafeInteger(n) && n >= 0\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false\n return true\n}\n\nfunction refused(reason: string): MerkleVerification {\n return { verified: false, reason }\n}\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nfunction fromHex(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2)\n for (let i = 0; i < bytes.length; i++) bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16)\n return bytes\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ledger-core-CAxUdDk0.js","names":[],"sources":["../src/ledger-core/merkle.ts"],"sourcesContent":["/**\n * Merkle proofs over an append-only list of leaves (RFC 9162 §2.1, the\n * Certificate Transparency tree).\n *\n * A hash chain proves a whole log against its head, but proving one entry means\n * replaying everything before it. This tree proves any one leaf against a root\n * with ⌈log₂ n⌉ hashes (inclusion), and proves that a larger tree only appended\n * to a smaller one (consistency). A verifier holding a root can therefore check\n * a single event, or that a later checkpoint extends an earlier one, without\n * reading the rest of the log.\n *\n * Leaves and interior nodes are domain-separated (0x00 and 0x01 prefixes), so a\n * leaf can never be presented as an interior node. Content that may later be\n * redacted takes a random 32-byte salt: a verifier then needs only the leaf's\n * hash, and short content cannot be guessed back from that hash. The salt must\n * be stored apart from anything that is shared after redaction.\n *\n * Builders refuse malformed input by throwing; verifiers never throw and return\n * a typed outcome, because a proof is external evidence and a bad one is a\n * finding, not a crash.\n */\nimport { sha256Bytes } from '@tangle-network/agent-interface'\nimport { ValidationError } from '../errors'\nimport { LEDGER_HASH_PATTERN, type LedgerHash } from './canonical'\n\n/** Proof that one leaf is at `leafIndex` in a tree of `treeSize` leaves. */\nexport interface MerkleInclusionProof {\n readonly leafIndex: number\n readonly treeSize: number\n readonly path: readonly LedgerHash[]\n}\n\n/** Proof that the first `oldSize` leaves of a `newSize` tree are unchanged. */\nexport interface MerkleConsistencyProof {\n readonly oldSize: number\n readonly newSize: number\n readonly path: readonly LedgerHash[]\n}\n\nexport type MerkleVerification =\n | { readonly verified: true }\n | { readonly verified: false; readonly reason: string }\n\nconst SALT_PATTERN = /^[a-f0-9]{64}$/\nconst LEAF_PREFIX = 0x00\nconst NODE_PREFIX = 0x01\nconst encoder = new TextEncoder()\n\n/** Root of the empty tree: SHA-256 of no bytes. */\nconst MERKLE_EMPTY_ROOT: LedgerHash = sha256Bytes(new Uint8Array(0)) as LedgerHash\n\n/** A fresh random salt for {@link merkleLeafHash}: 32 bytes as 64 lowercase hex characters. */\nexport function merkleSalt(): string {\n return toHex(globalThis.crypto.getRandomValues(new Uint8Array(32)))\n}\n\n/**\n * Leaf hash of `content`: SHA-256(0x00 ‖ salt ‖ content). Without a salt this is\n * exactly the RFC 9162 leaf hash. Strings are hashed as UTF-8.\n */\nexport function merkleLeafHash(content: Uint8Array | string, salt?: string): LedgerHash {\n const bytes = typeof content === 'string' ? encoder.encode(content) : content\n if (salt === undefined) return digest(LEAF_PREFIX, bytes)\n if (!SALT_PATTERN.test(salt)) {\n throw new ValidationError('merkle salt must be 32 bytes as 64 lowercase hex characters')\n }\n return digest(LEAF_PREFIX, fromHex(salt), bytes)\n}\n\n/** Root over leaf hashes, in order. The empty list has {@link MERKLE_EMPTY_ROOT}. */\nexport function merkleRoot(leaves: readonly LedgerHash[]): LedgerHash {\n const nodes = decodeLeaves(leaves)\n return nodes.length === 0 ? MERKLE_EMPTY_ROOT : toLedgerHash(subtreeRoot(nodes, 0, nodes.length))\n}\n\n/** Inclusion proof for the leaf at `leafIndex` (RFC 9162 §2.1.3.1). */\nexport function merkleInclusionProof(\n leaves: readonly LedgerHash[],\n leafIndex: number,\n): MerkleInclusionProof {\n const nodes = decodeLeaves(leaves)\n if (!Number.isSafeInteger(leafIndex) || leafIndex < 0 || leafIndex >= nodes.length) {\n throw new ValidationError(\n `merkle leaf index ${leafIndex} is outside a tree of ${nodes.length} leaves`,\n )\n }\n const path: Uint8Array[] = []\n inclusionPath(nodes, leafIndex, 0, nodes.length, path)\n return { leafIndex, treeSize: nodes.length, path: path.map(toLedgerHash) }\n}\n\n\n\n/** Check that `leaf` is in the tree with `root` at the proof's index (RFC 9162 §2.1.3.2). */\nexport function verifyMerkleInclusion(\n leaf: LedgerHash,\n proof: MerkleInclusionProof,\n root: LedgerHash,\n): MerkleVerification {\n const { leafIndex, treeSize } = proof\n if (!isSize(treeSize) || !isSize(leafIndex) || leafIndex >= treeSize) {\n return refused(`leaf index ${leafIndex} is outside a tree of ${treeSize} leaves`)\n }\n const decoded = decodeAll([leaf, root, ...proof.path])\n if (decoded === undefined) return refused('proof carries a malformed hash')\n const [leafBytes, rootBytes, ...path] = decoded as [Uint8Array, Uint8Array, ...Uint8Array[]]\n let fn = leafIndex\n let sn = treeSize - 1\n let r = leafBytes\n for (const p of path) {\n if (sn === 0) return refused('proof path is longer than the tree is deep')\n if (fn % 2 === 1 || fn === sn) {\n r = node(p, r)\n if (fn % 2 === 0) {\n while (fn % 2 === 0 && fn !== 0) {\n fn = Math.floor(fn / 2)\n sn = Math.floor(sn / 2)\n }\n }\n } else {\n r = node(r, p)\n }\n fn = Math.floor(fn / 2)\n sn = Math.floor(sn / 2)\n }\n if (sn !== 0) return refused('proof path is shorter than the tree is deep')\n return equal(r, rootBytes) ? { verified: true } : refused('leaf does not hash to the root')\n}\n\n\n\nfunction subtreeRoot(nodes: readonly Uint8Array[], start: number, end: number): Uint8Array {\n if (end - start === 1) return nodes[start] as Uint8Array\n const k = largestPowerOfTwoBelow(end - start)\n return node(subtreeRoot(nodes, start, start + k), subtreeRoot(nodes, start + k, end))\n}\n\nfunction inclusionPath(\n nodes: readonly Uint8Array[],\n index: number,\n start: number,\n end: number,\n path: Uint8Array[],\n): void {\n if (end - start === 1) return\n const k = largestPowerOfTwoBelow(end - start)\n if (index < start + k) {\n inclusionPath(nodes, index, start, start + k, path)\n path.push(subtreeRoot(nodes, start + k, end))\n } else {\n inclusionPath(nodes, index, start + k, end, path)\n path.push(subtreeRoot(nodes, start, start + k))\n }\n}\n\n\n\nfunction node(left: Uint8Array, right: Uint8Array): Uint8Array {\n return fromHex(digest(NODE_PREFIX, left, right).slice('sha256:'.length))\n}\n\nfunction digest(prefix: number, ...parts: Uint8Array[]): LedgerHash {\n const length = parts.reduce((total, part) => total + part.length, 1)\n const bytes = new Uint8Array(length)\n bytes[0] = prefix\n let offset = 1\n for (const part of parts) {\n bytes.set(part, offset)\n offset += part.length\n }\n return sha256Bytes(bytes) as LedgerHash\n}\n\nfunction decodeLeaves(leaves: readonly LedgerHash[]): Uint8Array[] {\n const decoded = decodeAll(leaves)\n if (decoded === undefined) {\n throw new ValidationError('merkle leaves must be sha256:<64 lowercase hex> hashes')\n }\n return decoded\n}\n\nfunction decodeAll(hashes: readonly string[]): Uint8Array[] | undefined {\n const out: Uint8Array[] = []\n for (const hash of hashes) {\n if (typeof hash !== 'string' || !LEDGER_HASH_PATTERN.test(hash)) return undefined\n out.push(fromHex(hash.slice('sha256:'.length)))\n }\n return out\n}\n\nfunction toLedgerHash(bytes: Uint8Array): LedgerHash {\n return `sha256:${toHex(bytes)}`\n}\n\nfunction largestPowerOfTwoBelow(n: number): number {\n let k = 1\n while (k * 2 < n) k *= 2\n return k\n}\n\n\n\nfunction isSize(n: number): boolean {\n return Number.isSafeInteger(n) && n >= 0\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false\n return true\n}\n\nfunction refused(reason: string): MerkleVerification {\n return { verified: false, reason }\n}\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nfunction fromHex(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2)\n for (let i = 0; i < bytes.length; i++) bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16)\n return bytes\n}\n"],"mappings":"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"}