chainlesschain 0.166.59 → 0.166.63

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 (182) hide show
  1. package/README.md +38 -8
  2. package/package.json +4 -1
  3. package/src/assets/web-panel/assets/{AIOps-B9i3kk5f.js → AIOps-CfPrpABR.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DGMs1wBm.js → ActionButton-Bkv1erki.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D-JGeynM.js → Analytics-fY_7epoU.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-DLECnXlP.js → AppLayout-DegaN-aa.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-CwaTiXN4.js → Artifacts-90-UNTVE.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BCb7s5Ky.js → Audit-BRQ1F4sA.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-D4IOzvKs.js → BackgroundAgents-Cb85uP7O.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-Cknunk10.js → Backup-CrLBSWQK.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DnU8pbUh.js → BaseInput-DditUW5B.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-DOouYIhz.js → Chat-0XozleDQ.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-8QXBJvgy.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-BrumNw6V.js → Checkbox-C2Ck_3ju.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-B4E_uI_N.js → Codegen-Chjw-MS7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-C7H2sdaL.js → Col-B_w8_Oka.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BFdzcMSl.js → Community-XAqxPnXq.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BzVXohrg.js → Compact-BX_3GJ3m.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-B_4QcuSH.js → Compliance-DE3kIC9z.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DjuQzJx8.js → Cowork-DPBYp1ey.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-Bf2iY-1-.js → Cron-D9cknqzn.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CY9QW7IT.js → Crosschain-BzHrGWY9.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-kDZBvaKr.js → DID-BuD8TkZl.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-DoYboS3g.js → Dashboard-BbxMuZVK.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-LLEzI6l1.js → Dropdown-jq0ki-tE.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-D2kmSvkg.js → EmailListRenderer-RiMvINxT.js} +1 -1
  27. package/src/assets/web-panel/assets/{EvolutionSettings-DHj2yUGZ.js → EvolutionSettings-DE-URi9i.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-B7Hg7fR0.js → FamilyGuardDashboard-DV3ao62-.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-CUdwU6aH.js → Federation-BF6BmBPg.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-D1KrwjwY.js → FormItemContext-CKTX59j2.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-CXGLoHfw.js → GenericCardRenderer-DZkH-CTs.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-TG3Q9JWG.js → Git-B5JYb-w-.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BJD7h_fv.js → Governance-D3WfDZ6W.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-Dky4l_bZ.js → Inference-DoSvfDUk.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-CCx9aXBV.js → KnowledgeGraph-DUDIzN97.js} +1 -1
  36. package/src/assets/web-panel/assets/Logs-JfJerfFD.js +2 -0
  37. package/src/assets/web-panel/assets/MarkdownRenderer-DXgA7cZm.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-BzL6KJMX.js → Marketplace-BpVrOM_V.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-BReSRzEU.js → McpTools-CFnQdiSv.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-BhmkkCxd.js → Memory-Dxv81cNl.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BeQMHr_n.js → MobileBridge-C92eX7PB.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-CphEwj_l.js → MobileProjects-BUHw7Wox.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-CFk1ibuN.js → Mtc-D-G9H4A1.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-CU9qrmbH.js → MtcAudit-CAEaEtAz.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-CKR-Gh0Y.js → Multisig-Cx_-X9HD.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-D1qWY6Mx.js → NLProgramming-DRIKG4Xy.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-B4CM0C65.js → Notes-CmL0vKUv.js} +4 -4
  48. package/src/assets/web-panel/assets/{NotificationSettings-BTQYWveR.js → NotificationSettings-D2cQ5aQn.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-DxN6fAn8.js → OrderTableRenderer-CPfd7PNy.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-scgboNfd.js → Organization-EKqO46hz.js} +2 -2
  51. package/src/assets/web-panel/assets/{Overflow-BP4aQhid.js → Overflow-BOHjBwJo.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-65jIo6MY.js → P2P-Dx4LdCE0.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-Bfi4-tDQ.js → PdhVaultBrowser-CgCt2xdT.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-DWtxT7bE.js → Permissions-DWjDeO7O.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-Bilmr8BR.js → PersonalDataHub-Bx4Od8pG.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-IPIMM-1y.js → Pipeline-oKxws_Ch.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-DFB8RiVK.js → Privacy-Df1HVRKR.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-DxZksvu1.js → ProjectInit-BraLwZT4.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-DsjPsnYN.js → ProjectSettings-CKru54M0.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-CC5FBLLq.js → Projects-BEr7cJcS.js} +1 -1
  61. package/src/assets/web-panel/assets/{Providers-Dk3ViPuF.js → Providers-C8v30DU3.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-CJ8R6-bF.js → QrScannerModal-CPyNV-O5.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-DJfCPORc.js → QuickAsk-BLIew7A5.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-DjDygXeb.js → Recommend-DVjWmsPs.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-BJiJ1YHw.js → RemoteSession-B4PNTaEf.js} +3 -3
  66. package/src/assets/web-panel/assets/{Reputation-fYE8jPcc.js → Reputation-D5HOV6oI.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-vcvsjMm4.js → Row-DgCQom2M.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-CZnKliwn.js → RssFeed-zvIcGHgz.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-DEStiFGI.js → Search-C-KbJP_z.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-BPb_szxS.js → Security-CasnI-Ld.js} +3 -3
  71. package/src/assets/web-panel/assets/{Services-TR0xZhSF.js → Services-CR-pSlFv.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-BSPu9boC.js → Skeleton-BB5On1b5.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-CXEj9pC6.js → Skills-CC-wdQi-.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-jlOlDGMA.js → Sla-CPX5QKEu.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-C8oPE_HQ.js → SpeechSettings-Bifkl6Zz.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-DZNUx8zt.js → SyncSettings-CdUVeB-S.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-B4T6aoOl.js → Tasks-BttwN3fs.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-DeRgtwZ5.js → Templates-CBHNbpQ7.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-DDVoXGxa.js → Tenant-B90lEwSQ.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-DGAUoJMz.js → Terminal-u8KqitsA.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-Co4Nkpjm.js → TimelineRenderer-CnEJMkJo.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-DaMLa0Fm.js → Tokens-CTM2OOJ_.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-C7iLr-Ik.js → Trigger-Ca8NmmgU.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CxX_tQqi.js → Trust-CI9GpUj2.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-ClrdckEx.js → UkeySign-BlMLGqKK.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-DgTVhaoK.js → VideoEditing-C8yCZrH0.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-SIbwES0O.js → Wallet-BpuYrz8o.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-YNqVnhZF.js → WebAuthn-DFpNfLG_.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-BvynT9mj.js → WorkflowEditor-BWhLoeU4.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-X79b2tVy.js → chat-Dwo4LC7E.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-DioWDCbu.js → colors-DkdGvKBf.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-DpAXXaqu.js → compact-item-1gI0lfs3.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-BYq8bCQX.js → createContext-O9iHirtr.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-axBqv361.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-CDJNMJ_n.js → hasIn-DY1jo9BQ.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DUe-hFGb.js → index-1AnBwAoM.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CS3QdYDW.js → index-B-kbagPi.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DZysaS5T.js → index-B0TX-bLV.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Cx0_WiSe.js → index-B5l7eb6E.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CJEFd0QJ.js → index-BDwV_V5g.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-D88MWTOx.js → index-BgHG4f2K.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BK53HyEP.js → index-BgVO1aXv.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-COqkDiRU.js → index-Bl6GfsQZ.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CUbuCFWb.js → index-BmAK4o9I.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C7cXBJcM.js → index-BsQkwBu2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Byt1ny7l.js → index-BumRAO-7.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Bh9la-GL.js → index-Bx4MNNMY.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-B8_grEFP.js → index-C4c0XaiT.js} +1 -1
  109. package/src/assets/web-panel/assets/index-CAsOttsq.js +1 -0
  110. package/src/assets/web-panel/assets/{index-YviHYMA2.js → index-CBqSTwY9.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-00kVj4me.js → index-D8fqsTHW.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Wl55a61D.js → index-DCqPIE3G.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CLSt7mOy.js → index-DNnaEzC5.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C4xggKQp.js → index-DTppQua6.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CbxqdIzD.js → index-DfFzjnA0.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BwHEGjR7.js → index-DskEFn8M.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D3J9FKFr.js → index-DvRvwzc-.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BGEXGr9g.js → index-DwBcFhcc.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B6wxVEIZ.js → index-DwJBbK3Z.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-mHAPEcPi.js → index-DwhJqZqM.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C1-NqghD.js → index-Dx51Am-0.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DP9ZLjra.js → index-E5Ar6dNV.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DSFkmRvK.js → index-ETHEhWvI.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DmNspbVU.js → index-KUrBWzIM.js} +1 -1
  125. package/src/assets/web-panel/assets/index-MgEKheCh.js +1 -0
  126. package/src/assets/web-panel/assets/{index-TqLyy6IR.js → index-YnGvCu0P.js} +3 -3
  127. package/src/assets/web-panel/assets/{index-Q3WQ5Zhr.js → index-hRtVittm.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DAnXSg0r.js → index-nXoV4OCZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BBvA7Hxj.js → index-qUbrqzvO.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BIO8EVHt.js → index-rIJqtLz-.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-B8ChecWd.js → index-rkkMl4Lb.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DwG9khVs.js → index-tXjOuLZm.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-V6l3ia83.js → index-zLOzCcxM.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Bt0zcD5R.js → index-zPpssHXA.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-18rmGkik.js → initDefaultProps-Du5HHTVt.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-3kvGzSgV.js → motion-D9mAVPKP.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Dx3DiVHc.js → move-DPO_sFtt.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-VX1dFJEI.js → mtc-parser-CnezVcXi.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-CniSeCOA.js → omit-DNpYMbet.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-RPggmcOd.js → pickAttrs-BUFm_slL.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-B45YBykr.js → placementArrow-DvwJtnzY.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-D0nciAEn.js → responsiveObserve-CUWOh_KI.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-UxLNWqjI.js → slide-bVHCUsdj.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-CukpV_uI.js → statusUtils-FlOzOrxf.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-BIcEZk6Y.js → styleChecker-C6CFXutA.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-Zah-xvV3.js → useFlexGapSupport-BNGqO_E0.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-BA7ihKFN.js → useFs-DyKOrA27.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-C64CsyY3.js → usePersonalDataHub-DZAqeMAJ.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-Datcekgj.js → vnode-Do7fVasi.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-CaFQv1KF.js → zoom-DYkEmOT2.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/data/changelog.json +52 -0
  153. package/src/lib/background-agent-supervisor.js +10 -1
  154. package/src/lib/evolution/evidence-backed-wiki-maintainer.js +119 -12
  155. package/src/lib/evolution/evolution-artifact-ports.js +6 -0
  156. package/src/lib/evolution/evolution-deployment-loader.js +139 -0
  157. package/src/lib/evolution/evolution-eval-gate.js +5 -0
  158. package/src/lib/evolution/evolution-ledger-ports.js +41 -17
  159. package/src/lib/evolution/pm-exploration-benchmark.js +253 -0
  160. package/src/lib/evolution/pm-exploration-budget-executor.js +346 -0
  161. package/src/lib/evolution/pm-exploration-business-grader.js +581 -0
  162. package/src/lib/evolution/pm-exploration-evidence-bundle.js +613 -0
  163. package/src/lib/evolution/pm-exploration-execution-host.js +946 -0
  164. package/src/lib/evolution/pm-exploration-ledger-adapter.js +860 -0
  165. package/src/lib/evolution/pm-exploration-provider-settlement-adapter.js +420 -0
  166. package/src/lib/evolution/pm-exploration-receipts.js +626 -0
  167. package/src/lib/evolution/pm-exploration-recovery-snapshot-store.js +521 -0
  168. package/src/lib/evolution/pm-exploration-rounds.js +842 -0
  169. package/src/lib/evolution/pm-exploration-transition-committer.js +541 -0
  170. package/src/lib/evolution/pm-exploration-volcengine-provider.js +724 -0
  171. package/src/lib/evolution/pm-result-grader.cjs +287 -0
  172. package/src/lib/read-file-loop-guard.js +36 -5
  173. package/src/lib/secure-fs.js +51 -4
  174. package/src/lib/task-progress-tracker.js +29 -7
  175. package/src/lib/text-file-search.js +1 -0
  176. package/src/runtime/agent-core.js +46 -4
  177. package/src/assets/web-panel/assets/ChatBubbleRenderer-C4tdSms8.js +0 -1
  178. package/src/assets/web-panel/assets/Logs-BtesccPB.js +0 -2
  179. package/src/assets/web-panel/assets/MarkdownRenderer-DoN7oE2J.js +0 -1
  180. package/src/assets/web-panel/assets/devWarning-ONeWC5dH.js +0 -1
  181. package/src/assets/web-panel/assets/index--QLnQuO9.js +0 -1
  182. package/src/assets/web-panel/assets/index-CkgeII0e.js +0 -1
@@ -0,0 +1,860 @@
1
+ import { createHash } from "node:crypto";
2
+ import { isPromise, isProxy } from "node:util/types";
3
+
4
+ import {
5
+ EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
6
+ EvolutionArtifactPorts,
7
+ } from "./evolution-artifact-ports.js";
8
+ import {
9
+ EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
10
+ EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
11
+ EvolutionLedger,
12
+ } from "./evolution-ledger.js";
13
+ import {
14
+ EVOLUTION_ARTIFACT_DURABILITY_BINDING_SCHEMA,
15
+ EVOLUTION_ARTIFACT_DURABILITY_RECEIPT_SCHEMA,
16
+ EVOLUTION_ARTIFACT_DURABILITY_RETAIN_REQUEST_SCHEMA,
17
+ captureEvolutionLedgerDurableArtifactResolver,
18
+ } from "./evolution-ledger-ports.js";
19
+ import {
20
+ exportPmExplorationRecoverySnapshot,
21
+ restorePmExplorationJournal,
22
+ verifyPmExplorationPlan,
23
+ } from "./pm-exploration-rounds.js";
24
+ import { verifyPmExplorationEvidenceBundle } from "./pm-exploration-evidence-bundle.js";
25
+ import { verifyPmExplorationExecutionManifest } from "./pm-exploration-execution-host.js";
26
+ import { inspectPmExplorationReceiptAuthority } from "./pm-exploration-receipts.js";
27
+
28
+ export const PM_EXPLORATION_LEDGER_RECORD_SCHEMA =
29
+ "chainlesschain.pm-exploration-ledger-record/v1";
30
+ export const PM_EXPLORATION_AUTHENTICATED_LEDGER_RECORD_SCHEMA =
31
+ "chainlesschain.pm-exploration-ledger-record/v2";
32
+ export const PM_EXPLORATION_LEDGER_EVENT_TYPE =
33
+ "pm.exploration.snapshot-committed";
34
+ export const PM_EXPLORATION_LEDGER_RESTORE_SCHEMA =
35
+ "chainlesschain.pm-exploration-ledger-restore/v1";
36
+ export const PM_EXPLORATION_LEDGER_ACK_SCHEMA =
37
+ "chainlesschain.pm-exploration-ledger-ack/v1";
38
+ export const PM_EXPLORATION_LEDGER_CORRUPT_CODE =
39
+ "CC_PM_EXPLORATION_LEDGER_CORRUPT";
40
+ export const PM_EXPLORATION_LEDGER_CONFLICT_CODE =
41
+ "CC_PM_EXPLORATION_LEDGER_CONFLICT";
42
+
43
+ const ARTIFACT_TYPE = "pm-exploration-recovery-snapshot";
44
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
45
+ const ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
46
+ const DESCRIPTOR_KEYS = new Set([
47
+ "tenantId",
48
+ "artifactTenantId",
49
+ "audience",
50
+ "purpose",
51
+ "planDigest",
52
+ "durabilityAuthorityId",
53
+ ]);
54
+ const RECORD_KEYS = new Set([
55
+ "schema",
56
+ "descriptorDigest",
57
+ "revision",
58
+ "priorSnapshotDigest",
59
+ "snapshotDigest",
60
+ "snapshot",
61
+ "committedAt",
62
+ ]);
63
+ const AUTHENTICATED_RECORD_KEYS = new Set([
64
+ ...RECORD_KEYS,
65
+ "evidenceBundle",
66
+ "evidenceDigest",
67
+ "executionManifestDigest",
68
+ ]);
69
+ const DURABILITY_AUTHORITY_KEYS = new Set(["id", "retain", "resolve"]);
70
+ const DURABILITY_RECEIPT_KEYS = new Set([
71
+ "schema",
72
+ "authenticated",
73
+ "durable",
74
+ "authorityId",
75
+ "artifactTenantId",
76
+ "digest",
77
+ "purpose",
78
+ "ref",
79
+ "retention",
80
+ "type",
81
+ "receiptDigest",
82
+ ]);
83
+ const STORE_PORTS = new WeakMap();
84
+
85
+ function canonical(value) {
86
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
87
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
88
+ return `{${Object.keys(value)
89
+ .sort()
90
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
91
+ .join(",")}}`;
92
+ }
93
+
94
+ function hash(domain, value) {
95
+ return `sha256:${createHash("sha256")
96
+ .update(domain)
97
+ .update("\0")
98
+ .update(canonical(value))
99
+ .digest("hex")}`;
100
+ }
101
+
102
+ function sha256Bytes(value) {
103
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
104
+ }
105
+
106
+ function same(left, right) {
107
+ return canonical(left) === canonical(right);
108
+ }
109
+
110
+ function deepFreeze(value, seen = new WeakSet()) {
111
+ if (!value || typeof value !== "object" || seen.has(value)) return value;
112
+ seen.add(value);
113
+ for (const key of Reflect.ownKeys(value)) {
114
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
115
+ if (descriptor && "value" in descriptor) deepFreeze(descriptor.value, seen);
116
+ }
117
+ return Object.freeze(value);
118
+ }
119
+
120
+ function exact(value, keys, label) {
121
+ if (
122
+ !value ||
123
+ typeof value !== "object" ||
124
+ Array.isArray(value) ||
125
+ isProxy(value) ||
126
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value))
127
+ ) {
128
+ throw new TypeError(`${label} must be a plain record`);
129
+ }
130
+ const ownKeys = Reflect.ownKeys(value);
131
+ if (
132
+ ownKeys.length !== keys.size ||
133
+ ownKeys.some((key) => typeof key !== "string" || !keys.has(key))
134
+ ) {
135
+ throw new TypeError(`${label} has an invalid shape`);
136
+ }
137
+ for (const key of ownKeys) {
138
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
139
+ if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
140
+ throw new TypeError(`${label}.${String(key)} must be an own data field`);
141
+ }
142
+ }
143
+
144
+ function identifier(value, label) {
145
+ if (typeof value !== "string" || !ID.test(value))
146
+ throw new TypeError(`${label} is invalid`);
147
+ return value;
148
+ }
149
+
150
+ function digest(value, label) {
151
+ if (typeof value !== "string" || !DIGEST.test(value))
152
+ throw new TypeError(`${label} must be a sha256 digest`);
153
+ return value;
154
+ }
155
+
156
+ function fail(code, message, options) {
157
+ const error = new Error(message, options);
158
+ error.code = code;
159
+ throw error;
160
+ }
161
+
162
+ function corrupt(message, options) {
163
+ fail(PM_EXPLORATION_LEDGER_CORRUPT_CODE, message, options);
164
+ }
165
+
166
+ function conflict(message, options) {
167
+ fail(PM_EXPLORATION_LEDGER_CONFLICT_CODE, message, options);
168
+ }
169
+
170
+ function requireExactInstance(value, prototype, label) {
171
+ if (
172
+ !value ||
173
+ typeof value !== "object" ||
174
+ isProxy(value) ||
175
+ Object.getPrototypeOf(value) !== prototype
176
+ ) {
177
+ throw new TypeError(`${label} exact instance is required`);
178
+ }
179
+ return value;
180
+ }
181
+
182
+ function normalizeDescriptor(input) {
183
+ exact(input, DESCRIPTOR_KEYS, "PM exploration ledger descriptor");
184
+ const core = {
185
+ tenantId: identifier(input.tenantId, "tenantId"),
186
+ artifactTenantId: identifier(input.artifactTenantId, "artifactTenantId"),
187
+ audience: identifier(input.audience, "audience"),
188
+ purpose: identifier(input.purpose, "purpose"),
189
+ planDigest: digest(input.planDigest, "planDigest"),
190
+ durabilityAuthorityId: identifier(
191
+ input.durabilityAuthorityId,
192
+ "durabilityAuthorityId",
193
+ ),
194
+ };
195
+ return deepFreeze({
196
+ ...core,
197
+ descriptorDigest: hash(
198
+ "chainlesschain.pm-exploration-ledger-descriptor/v1",
199
+ core,
200
+ ),
201
+ });
202
+ }
203
+
204
+ function captureDurabilityAuthority(value) {
205
+ exact(value, DURABILITY_AUTHORITY_KEYS, "artifact durability authority");
206
+ const retain = Object.getOwnPropertyDescriptor(value, "retain").value;
207
+ const resolve = Object.getOwnPropertyDescriptor(value, "resolve").value;
208
+ if (
209
+ typeof retain !== "function" ||
210
+ typeof resolve !== "function" ||
211
+ isProxy(retain) ||
212
+ isProxy(resolve)
213
+ ) {
214
+ throw new TypeError(
215
+ "artifact durability authority requires direct retain and resolve methods",
216
+ );
217
+ }
218
+ return Object.freeze({
219
+ id: identifier(value.id, "artifact durability authority id"),
220
+ retain: retain.bind(value),
221
+ });
222
+ }
223
+
224
+ function snapshotPlan(plan) {
225
+ verifyPmExplorationPlan(plan);
226
+ return deepFreeze(structuredClone(plan));
227
+ }
228
+
229
+ function normalizeSnapshot(plan, snapshot) {
230
+ const restored = restorePmExplorationJournal(plan, snapshot);
231
+ return exportPmExplorationRecoverySnapshot(restored);
232
+ }
233
+
234
+ function normalizeEvidence(context, plan, snapshot, bundle) {
235
+ if (!context)
236
+ corrupt("PM exploration signed evidence verifier is unavailable");
237
+ return verifyPmExplorationEvidenceBundle({
238
+ plan,
239
+ manifest: context.manifest,
240
+ authorities: context.authorities,
241
+ snapshot,
242
+ bundle,
243
+ });
244
+ }
245
+
246
+ function parseRecord(resolution, descriptor, plan, evidenceContext) {
247
+ if (
248
+ resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
249
+ resolution.authenticated !== true ||
250
+ resolution.found !== true ||
251
+ !DIGEST.test(resolution.digest ?? "") ||
252
+ !DIGEST.test(resolution.receiptDigest ?? "") ||
253
+ !Buffer.isBuffer(resolution.bytes)
254
+ ) {
255
+ corrupt("PM exploration artifact resolution is unauthenticated");
256
+ }
257
+ let durable;
258
+ const encoded = resolution.bytes.toString("utf8");
259
+ try {
260
+ durable = JSON.parse(encoded);
261
+ } catch (cause) {
262
+ corrupt("PM exploration artifact is not JSON", { cause });
263
+ }
264
+ if (
265
+ durable?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
266
+ durable.tenantId !== descriptor.artifactTenantId ||
267
+ durable.audience !== descriptor.audience ||
268
+ durable.purpose !== descriptor.purpose ||
269
+ durable.retention !== "ledger" ||
270
+ durable.type !== ARTIFACT_TYPE
271
+ ) {
272
+ corrupt("PM exploration durable artifact binding is invalid");
273
+ }
274
+ const record = durable.value;
275
+ const authenticatedRecord =
276
+ record?.schema === PM_EXPLORATION_AUTHENTICATED_LEDGER_RECORD_SCHEMA;
277
+ try {
278
+ exact(
279
+ record,
280
+ authenticatedRecord ? AUTHENTICATED_RECORD_KEYS : RECORD_KEYS,
281
+ "PM exploration ledger record",
282
+ );
283
+ } catch (cause) {
284
+ corrupt("PM exploration ledger record shape is invalid", { cause });
285
+ }
286
+ if (
287
+ ![
288
+ PM_EXPLORATION_LEDGER_RECORD_SCHEMA,
289
+ PM_EXPLORATION_AUTHENTICATED_LEDGER_RECORD_SCHEMA,
290
+ ].includes(record.schema) ||
291
+ record.descriptorDigest !== descriptor.descriptorDigest ||
292
+ !Number.isSafeInteger(record.revision) ||
293
+ record.revision < 1 ||
294
+ (record.priorSnapshotDigest !== null &&
295
+ !DIGEST.test(record.priorSnapshotDigest ?? "")) ||
296
+ !DIGEST.test(record.snapshotDigest ?? "") ||
297
+ !Number.isSafeInteger(record.committedAt) ||
298
+ record.committedAt < 0
299
+ ) {
300
+ corrupt("PM exploration ledger record fields are invalid");
301
+ }
302
+ let snapshot;
303
+ try {
304
+ snapshot = normalizeSnapshot(plan, record.snapshot);
305
+ } catch (cause) {
306
+ corrupt("PM exploration recovery snapshot is invalid", { cause });
307
+ }
308
+ if (
309
+ snapshot.snapshotDigest !== record.snapshotDigest ||
310
+ !same(snapshot, record.snapshot)
311
+ ) {
312
+ corrupt("PM exploration recovery snapshot readback differs");
313
+ }
314
+ let evidenceBundle = null;
315
+ if (authenticatedRecord) {
316
+ if (
317
+ !DIGEST.test(record.evidenceDigest ?? "") ||
318
+ !DIGEST.test(record.executionManifestDigest ?? "")
319
+ ) {
320
+ corrupt("PM exploration signed evidence fields are invalid");
321
+ }
322
+ try {
323
+ evidenceBundle = normalizeEvidence(
324
+ evidenceContext,
325
+ plan,
326
+ snapshot,
327
+ record.evidenceBundle,
328
+ );
329
+ } catch (cause) {
330
+ corrupt("PM exploration signed evidence is invalid", { cause });
331
+ }
332
+ if (
333
+ evidenceBundle.evidenceDigest !== record.evidenceDigest ||
334
+ evidenceBundle.executionManifestDigest !==
335
+ record.executionManifestDigest ||
336
+ evidenceBundle.snapshotDigest !== snapshot.snapshotDigest ||
337
+ !same(evidenceBundle, record.evidenceBundle)
338
+ ) {
339
+ corrupt("PM exploration signed evidence readback differs");
340
+ }
341
+ }
342
+ return deepFreeze({ ...record, snapshot, evidenceBundle });
343
+ }
344
+
345
+ function assertSnapshotExtension(previous, next) {
346
+ if (!previous) return;
347
+ if (previous.frozen !== null)
348
+ conflict("frozen PM exploration state cannot be extended");
349
+ if (next.checkpoints.length < previous.checkpoints.length)
350
+ conflict("PM exploration snapshot would roll back checkpoints");
351
+ if (
352
+ !same(
353
+ next.checkpoints.slice(0, previous.checkpoints.length),
354
+ previous.checkpoints,
355
+ )
356
+ ) {
357
+ conflict("PM exploration checkpoint history is not append-only");
358
+ }
359
+ const rank = { broad: 0, "broad-complete": 1, deep: 2, frozen: 3 };
360
+ if (rank[next.stage] < rank[previous.stage])
361
+ conflict("PM exploration stage would move backwards");
362
+ if (previous.merge !== null && !same(previous.merge, next.merge))
363
+ conflict("PM exploration merge evidence changed after commit");
364
+ }
365
+
366
+ function sameHead(left, right) {
367
+ return [
368
+ "epoch",
369
+ "ledgerId",
370
+ "identityDigest",
371
+ "sequence",
372
+ "headDigest",
373
+ ].every((key) => left?.[key] === right?.[key]);
374
+ }
375
+
376
+ function recordIsAuthenticated(record) {
377
+ return record.schema === PM_EXPLORATION_AUTHENTICATED_LEDGER_RECORD_SCHEMA;
378
+ }
379
+
380
+ function recordEventId(record) {
381
+ const suffix = recordIsAuthenticated(record)
382
+ ? hash("chainlesschain.pm-exploration-ledger-event-id/v2", {
383
+ snapshotDigest: record.snapshotDigest,
384
+ evidenceDigest: record.evidenceDigest,
385
+ }).slice(7)
386
+ : record.snapshotDigest.slice(7);
387
+ return `${PM_EXPLORATION_LEDGER_EVENT_TYPE}.${suffix}`;
388
+ }
389
+
390
+ function recordReason(record) {
391
+ return recordIsAuthenticated(record)
392
+ ? `PM exploration authenticated recovery snapshot revision ${record.revision} committed`
393
+ : `PM exploration recovery snapshot revision ${record.revision} committed`;
394
+ }
395
+
396
+ function acknowledgement(descriptor, entry, recovered) {
397
+ const authenticated = recordIsAuthenticated(entry.record);
398
+ const result = {
399
+ schema: PM_EXPLORATION_LEDGER_ACK_SCHEMA,
400
+ authenticated: true,
401
+ durable: true,
402
+ ledgerAuthenticated: true,
403
+ ledgerDurable: true,
404
+ artifactPersisted: true,
405
+ artifactReadbackVerified: true,
406
+ durabilityAuthorityId: descriptor.durabilityAuthorityId,
407
+ authorityDurable: true,
408
+ powerLossDurabilityTested: false,
409
+ descriptorDigest: descriptor.descriptorDigest,
410
+ revision: entry.record.revision,
411
+ snapshotDigest: entry.record.snapshotDigest,
412
+ ledgerEventDigest: entry.event.eventDigest,
413
+ recovered,
414
+ snapshotAuthenticated: authenticated,
415
+ qualifiesForPromotion: false,
416
+ };
417
+ if (authenticated) {
418
+ result.evidenceDigest = entry.record.evidenceDigest;
419
+ result.executionManifestDigest = entry.record.executionManifestDigest;
420
+ }
421
+ return deepFreeze(result);
422
+ }
423
+
424
+ function normalizeEvidenceContext(executionManifest, receiptAuthorities, plan) {
425
+ if (executionManifest === null && receiptAuthorities === null) return null;
426
+ if (executionManifest === null || receiptAuthorities === null)
427
+ throw new TypeError(
428
+ "executionManifest and receiptAuthorities must be configured together",
429
+ );
430
+ const manifest = verifyPmExplorationExecutionManifest(executionManifest);
431
+ if (
432
+ manifest.planDigest !== plan.planDigest ||
433
+ manifest.environmentDigest !== plan.environmentDigest
434
+ ) {
435
+ throw new TypeError("PM signed evidence manifest differs from the plan");
436
+ }
437
+ exact(
438
+ receiptAuthorities,
439
+ new Set(["execution", "grader", "merge", "evaluator"]),
440
+ "PM exploration receipt authorities",
441
+ );
442
+ for (const [role, expected] of [
443
+ ["execution", manifest.runner],
444
+ ["grader", manifest.grader],
445
+ ["merge", manifest.merger],
446
+ ["evaluator", manifest.evaluator],
447
+ ]) {
448
+ if (
449
+ !same(
450
+ inspectPmExplorationReceiptAuthority(receiptAuthorities[role]),
451
+ expected,
452
+ )
453
+ ) {
454
+ throw new TypeError(`PM ${role} receipt authority differs from manifest`);
455
+ }
456
+ }
457
+ return Object.freeze({
458
+ manifest,
459
+ authorities: Object.freeze({
460
+ execution: receiptAuthorities.execution,
461
+ grader: receiptAuthorities.grader,
462
+ merge: receiptAuthorities.merge,
463
+ evaluator: receiptAuthorities.evaluator,
464
+ }),
465
+ });
466
+ }
467
+
468
+ export class PmExplorationLedgerAdapter {
469
+ #append;
470
+ #clock;
471
+ #evidenceContext;
472
+ #plan;
473
+ #put;
474
+ #read;
475
+ #resolve;
476
+ #retain;
477
+ #verify;
478
+
479
+ constructor({
480
+ descriptor: input,
481
+ plan,
482
+ artifactPorts,
483
+ artifactDurabilityAuthority,
484
+ ledger,
485
+ ledgerArtifactResolver,
486
+ executionManifest = null,
487
+ receiptAuthorities = null,
488
+ now = Date.now,
489
+ } = {}) {
490
+ this.descriptor = normalizeDescriptor(input);
491
+ this.#plan = snapshotPlan(plan);
492
+ if (this.#plan.planDigest !== this.descriptor.planDigest)
493
+ throw new TypeError("PM exploration plan differs from ledger descriptor");
494
+ this.#evidenceContext = normalizeEvidenceContext(
495
+ executionManifest,
496
+ receiptAuthorities,
497
+ this.#plan,
498
+ );
499
+ const trustedArtifactPorts = requireExactInstance(
500
+ artifactPorts,
501
+ EvolutionArtifactPorts.prototype,
502
+ "EvolutionArtifactPorts",
503
+ );
504
+ const trustedLedger = requireExactInstance(
505
+ ledger,
506
+ EvolutionLedger.prototype,
507
+ "EvolutionLedger",
508
+ );
509
+ this.#put =
510
+ EvolutionArtifactPorts.prototype.putCanonical.bind(trustedArtifactPorts);
511
+ this.#read = EvolutionLedger.prototype.read.bind(trustedLedger);
512
+ this.#verify = EvolutionLedger.prototype.verify.bind(trustedLedger);
513
+ this.#append =
514
+ EvolutionLedger.prototype.appendDomainEvent.bind(trustedLedger);
515
+ const durabilityAuthority = captureDurabilityAuthority(
516
+ artifactDurabilityAuthority,
517
+ );
518
+ if (durabilityAuthority.id !== this.descriptor.durabilityAuthorityId)
519
+ throw new TypeError(
520
+ "artifact durability authority differs from ledger descriptor",
521
+ );
522
+ const resolverBinding = captureEvolutionLedgerDurableArtifactResolver(
523
+ ledgerArtifactResolver,
524
+ );
525
+ if (
526
+ resolverBinding.authorityId !== durabilityAuthority.id ||
527
+ resolverBinding.artifactTenantId !== this.descriptor.artifactTenantId ||
528
+ resolverBinding.purpose !== this.descriptor.purpose ||
529
+ !resolverBinding.matchesArtifactPorts(trustedArtifactPorts) ||
530
+ !resolverBinding.matchesDurabilityAuthority(artifactDurabilityAuthority)
531
+ ) {
532
+ throw new TypeError(
533
+ "durable artifact resolver differs from PM ledger authorities",
534
+ );
535
+ }
536
+ if (typeof now !== "function" || isProxy(now))
537
+ throw new TypeError("now must be a direct function");
538
+ this.#resolve = ledgerArtifactResolver;
539
+ this.#retain = durabilityAuthority.retain;
540
+ this.#clock = now;
541
+ STORE_PORTS.set(
542
+ this,
543
+ Object.freeze({
544
+ load: () => this.load(),
545
+ commitJournal: (journal, evidenceBundle = null) =>
546
+ this.commitJournal(journal, evidenceBundle),
547
+ restoreLatestJournal: () => this.restoreLatestJournal(),
548
+ }),
549
+ );
550
+ Object.freeze(this);
551
+ }
552
+
553
+ #events() {
554
+ const events = this.#read();
555
+ if (!Array.isArray(events))
556
+ corrupt("EvolutionLedger did not return an event array");
557
+ return events.filter(
558
+ (event) =>
559
+ event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
560
+ event.type === PM_EXPLORATION_LEDGER_EVENT_TYPE &&
561
+ event.tenantId === this.descriptor.tenantId &&
562
+ event.correlationId === this.descriptor.planDigest,
563
+ );
564
+ }
565
+
566
+ #resolveEvent(event, identity) {
567
+ const resolution = this.#resolve({
568
+ epoch: identity.epoch,
569
+ ledgerId: identity.ledgerId,
570
+ ref: event.subjectRef,
571
+ tenantId: this.descriptor.artifactTenantId,
572
+ });
573
+ if (
574
+ resolution?.ref !== event.subjectRef?.ref ||
575
+ resolution?.digest !== event.subjectRef?.digest
576
+ ) {
577
+ corrupt("PM exploration ledger subject was substituted");
578
+ }
579
+ return parseRecord(
580
+ resolution,
581
+ this.descriptor,
582
+ this.#plan,
583
+ this.#evidenceContext,
584
+ );
585
+ }
586
+
587
+ #historyWithIdentity() {
588
+ const before = this.#verify();
589
+ const events = this.#events();
590
+ const history = [];
591
+ for (const [index, event] of events.entries()) {
592
+ const previous = history.at(-1) ?? null;
593
+ const record = this.#resolveEvent(event, before);
594
+ if (
595
+ record.revision !== index + 1 ||
596
+ record.priorSnapshotDigest !==
597
+ (previous?.record.snapshotDigest ?? null) ||
598
+ event.artifactTenantId !== this.descriptor.artifactTenantId ||
599
+ event.decision !== "committed" ||
600
+ event.skillName !== null ||
601
+ event.eventId !== recordEventId(record) ||
602
+ event.reason !== recordReason(record) ||
603
+ event.timestamp !== new Date(record.committedAt).toISOString() ||
604
+ !DIGEST.test(event.eventDigest ?? "") ||
605
+ !Array.isArray(event.sourceRefs) ||
606
+ event.sourceRefs.length !== (previous ? 1 : 0) ||
607
+ (previous && !same(event.sourceRefs[0], previous.event.subjectRef))
608
+ ) {
609
+ corrupt("PM exploration ledger history is invalid");
610
+ }
611
+ try {
612
+ assertSnapshotExtension(
613
+ previous?.record.snapshot ?? null,
614
+ record.snapshot,
615
+ );
616
+ } catch (cause) {
617
+ corrupt("PM exploration ledger snapshot history is discontinuous", {
618
+ cause,
619
+ });
620
+ }
621
+ history.push(deepFreeze({ event, record }));
622
+ }
623
+ const after = this.#verify();
624
+ if (!sameHead(before, after))
625
+ conflict("PM exploration ledger changed during authenticated read");
626
+ return deepFreeze({ history, identity: after });
627
+ }
628
+
629
+ load() {
630
+ const latest = this.#historyWithIdentity().history.at(-1) ?? null;
631
+ if (!latest) return null;
632
+ const authenticated = recordIsAuthenticated(latest.record);
633
+ const result = {
634
+ schema: PM_EXPLORATION_LEDGER_RESTORE_SCHEMA,
635
+ authenticated: true,
636
+ durable: true,
637
+ ledgerAuthenticated: true,
638
+ ledgerDurable: true,
639
+ artifactPersisted: true,
640
+ artifactReadbackVerified: true,
641
+ durabilityAuthorityId: this.descriptor.durabilityAuthorityId,
642
+ authorityDurable: true,
643
+ powerLossDurabilityTested: false,
644
+ descriptorDigest: this.descriptor.descriptorDigest,
645
+ revision: latest.record.revision,
646
+ snapshotDigest: latest.record.snapshotDigest,
647
+ ledgerEventDigest: latest.event.eventDigest,
648
+ snapshot: latest.record.snapshot,
649
+ snapshotAuthenticated: authenticated,
650
+ qualifiesForPromotion: false,
651
+ };
652
+ if (authenticated) {
653
+ result.evidenceBundle = latest.record.evidenceBundle;
654
+ result.evidenceDigest = latest.record.evidenceDigest;
655
+ result.executionManifestDigest = latest.record.executionManifestDigest;
656
+ }
657
+ return deepFreeze(result);
658
+ }
659
+
660
+ restoreLatestJournal() {
661
+ const evidence = this.load();
662
+ if (evidence === null) return null;
663
+ const journal = restorePmExplorationJournal(this.#plan, evidence.snapshot);
664
+ return Object.freeze({ journal, evidence });
665
+ }
666
+
667
+ commitJournal(journal, evidenceBundle = null) {
668
+ let snapshot;
669
+ try {
670
+ snapshot = exportPmExplorationRecoverySnapshot(journal);
671
+ } catch (cause) {
672
+ if (cause?.message?.includes("Active rounds")) throw cause;
673
+ corrupt("PM exploration journal cannot produce a recovery snapshot", {
674
+ cause,
675
+ });
676
+ }
677
+ if (snapshot.planDigest !== this.descriptor.planDigest)
678
+ conflict("PM exploration journal belongs to another plan");
679
+ let authenticatedEvidence = null;
680
+ if (this.#evidenceContext) {
681
+ if (evidenceBundle === null)
682
+ throw new TypeError(
683
+ "signed PM exploration evidence is required for this adapter",
684
+ );
685
+ authenticatedEvidence = normalizeEvidence(
686
+ this.#evidenceContext,
687
+ this.#plan,
688
+ snapshot,
689
+ evidenceBundle,
690
+ );
691
+ } else if (evidenceBundle !== null) {
692
+ throw new TypeError(
693
+ "signed PM exploration evidence is not configured for this adapter",
694
+ );
695
+ }
696
+ const { history, identity } = this.#historyWithIdentity();
697
+ const latest = history.at(-1) ?? null;
698
+ if (latest?.record.snapshotDigest === snapshot.snapshotDigest) {
699
+ if (
700
+ (authenticatedEvidence === null &&
701
+ !recordIsAuthenticated(latest.record)) ||
702
+ (authenticatedEvidence !== null &&
703
+ recordIsAuthenticated(latest.record) &&
704
+ latest.record.evidenceDigest === authenticatedEvidence.evidenceDigest)
705
+ ) {
706
+ return acknowledgement(this.descriptor, latest, true);
707
+ }
708
+ if (recordIsAuthenticated(latest.record))
709
+ conflict("PM exploration snapshot evidence cannot be replaced");
710
+ }
711
+ assertSnapshotExtension(latest?.record.snapshot ?? null, snapshot);
712
+
713
+ const revision = history.length + 1;
714
+ const committedAt = Number(this.#clock());
715
+ if (!Number.isSafeInteger(committedAt) || committedAt < 0)
716
+ throw new TypeError("PM exploration ledger clock is invalid");
717
+ const record = deepFreeze({
718
+ schema:
719
+ authenticatedEvidence === null
720
+ ? PM_EXPLORATION_LEDGER_RECORD_SCHEMA
721
+ : PM_EXPLORATION_AUTHENTICATED_LEDGER_RECORD_SCHEMA,
722
+ descriptorDigest: this.descriptor.descriptorDigest,
723
+ revision,
724
+ priorSnapshotDigest: latest?.record.snapshotDigest ?? null,
725
+ snapshotDigest: snapshot.snapshotDigest,
726
+ snapshot,
727
+ committedAt,
728
+ ...(authenticatedEvidence === null
729
+ ? {}
730
+ : {
731
+ evidenceBundle: authenticatedEvidence,
732
+ evidenceDigest: authenticatedEvidence.evidenceDigest,
733
+ executionManifestDigest:
734
+ authenticatedEvidence.executionManifestDigest,
735
+ }),
736
+ });
737
+ const published = this.#put(ARTIFACT_TYPE, record, {
738
+ audience: this.descriptor.audience,
739
+ purpose: this.descriptor.purpose,
740
+ retention: "ledger",
741
+ });
742
+ if (
743
+ !published?.ref ||
744
+ published.digest !== published.ref.digest ||
745
+ published.receipt?.persisted !== true ||
746
+ published.receipt.readbackVerified !== true ||
747
+ published.receipt.integrityVerified !== true ||
748
+ published.receipt.retention !== "ledger"
749
+ ) {
750
+ corrupt("PM exploration snapshot persistence was not confirmed");
751
+ }
752
+ const durableRecord = deepFreeze({
753
+ audience: this.descriptor.audience,
754
+ purpose: this.descriptor.purpose,
755
+ retention: "ledger",
756
+ schema: EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
757
+ tenantId: this.descriptor.artifactTenantId,
758
+ type: ARTIFACT_TYPE,
759
+ value: record,
760
+ });
761
+ const durableBytes = Buffer.from(canonical(durableRecord), "utf8");
762
+ if (sha256Bytes(durableBytes) !== published.digest)
763
+ corrupt("PM exploration canonical artifact bytes differ after publish");
764
+ const durabilityBinding = deepFreeze({
765
+ artifactTenantId: this.descriptor.artifactTenantId,
766
+ digest: published.digest,
767
+ purpose: this.descriptor.purpose,
768
+ ref: published.ref.ref,
769
+ retention: "ledger",
770
+ schema: EVOLUTION_ARTIFACT_DURABILITY_BINDING_SCHEMA,
771
+ type: ARTIFACT_TYPE,
772
+ });
773
+ const durabilityReceipt = this.#retain(
774
+ Object.freeze({
775
+ binding: durabilityBinding,
776
+ bytes: Buffer.from(durableBytes),
777
+ schema: EVOLUTION_ARTIFACT_DURABILITY_RETAIN_REQUEST_SCHEMA,
778
+ }),
779
+ );
780
+ if (isPromise(durabilityReceipt))
781
+ corrupt("PM exploration durability retain must be synchronous");
782
+ try {
783
+ exact(
784
+ durabilityReceipt,
785
+ DURABILITY_RECEIPT_KEYS,
786
+ "PM exploration durability receipt",
787
+ );
788
+ } catch (cause) {
789
+ corrupt("PM exploration durability receipt shape is invalid", { cause });
790
+ }
791
+ if (
792
+ durabilityReceipt.schema !==
793
+ EVOLUTION_ARTIFACT_DURABILITY_RECEIPT_SCHEMA ||
794
+ durabilityReceipt.authenticated !== true ||
795
+ durabilityReceipt.durable !== true ||
796
+ durabilityReceipt.authorityId !== this.descriptor.durabilityAuthorityId ||
797
+ durabilityReceipt.artifactTenantId !==
798
+ durabilityBinding.artifactTenantId ||
799
+ durabilityReceipt.digest !== durabilityBinding.digest ||
800
+ durabilityReceipt.purpose !== durabilityBinding.purpose ||
801
+ durabilityReceipt.ref !== durabilityBinding.ref ||
802
+ durabilityReceipt.retention !== durabilityBinding.retention ||
803
+ durabilityReceipt.type !== durabilityBinding.type ||
804
+ !DIGEST.test(durabilityReceipt.receiptDigest ?? "")
805
+ ) {
806
+ corrupt("PM exploration artifact was not durably retained");
807
+ }
808
+ const eventId = recordEventId(record);
809
+ try {
810
+ const receipt = this.#append(
811
+ {
812
+ artifactTenantId: this.descriptor.artifactTenantId,
813
+ correlationId: this.descriptor.planDigest,
814
+ decision: "committed",
815
+ eventId,
816
+ reason: recordReason(record),
817
+ skillName: null,
818
+ sourceRefs: latest ? [latest.event.subjectRef] : [],
819
+ subjectRef: published.ref,
820
+ tenantId: this.descriptor.tenantId,
821
+ timestamp: new Date(committedAt).toISOString(),
822
+ type: PM_EXPLORATION_LEDGER_EVENT_TYPE,
823
+ },
824
+ {
825
+ expectedHeadDigest: identity.headDigest,
826
+ expectedSequence: identity.sequence,
827
+ },
828
+ );
829
+ if (
830
+ receipt?.authenticated !== true ||
831
+ receipt.committed !== true ||
832
+ receipt.durable !== true ||
833
+ receipt.eventId !== eventId ||
834
+ !DIGEST.test(receipt.receiptDigest ?? "")
835
+ ) {
836
+ corrupt("PM exploration ledger append was not durably authenticated");
837
+ }
838
+ } catch (cause) {
839
+ const recovered = this.#historyWithIdentity().history.at(-1) ?? null;
840
+ if (recovered?.record.snapshotDigest !== snapshot.snapshotDigest)
841
+ throw cause;
842
+ return acknowledgement(this.descriptor, recovered, true);
843
+ }
844
+ const stored = this.#historyWithIdentity().history.at(-1) ?? null;
845
+ if (
846
+ stored?.record.revision !== revision ||
847
+ stored.record.snapshotDigest !== snapshot.snapshotDigest
848
+ ) {
849
+ corrupt("PM exploration snapshot readback differs after commit");
850
+ }
851
+ return acknowledgement(this.descriptor, stored, false);
852
+ }
853
+ }
854
+
855
+ export function capturePmExplorationLedgerStore(adapter) {
856
+ const ports = STORE_PORTS.get(adapter);
857
+ if (!ports)
858
+ throw new TypeError("a real PmExplorationLedgerAdapter is required");
859
+ return ports;
860
+ }