chainlesschain 0.166.22 → 0.166.25

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 (298) hide show
  1. package/README.md +46 -3
  2. package/package.json +4 -3
  3. package/src/assets/web-panel/assets/{AIOps-oJ7USzMC.js → AIOps-RaxL_QQD.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BlgnZe_C.js → ActionButton-DD3ieFO-.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D2rRbTLu.js → Analytics-CATDJukS.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-FwS3f0B2.js → AppLayout-BHGsnRDS.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-iF-_08Hi.js → Artifacts-BL6NunjN.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-D24p0zQw.js → Audit-D0nEWfbA.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-Cg3mRVi9.js → BackgroundAgents-BAP1MUol.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-EOqht3H-.js → Backup-R4y2OeSi.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-9XWYq2hj.js → BaseInput-ByQZ2z6S.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-Dq5yardA.js → Chat-32uV--xF.js} +4 -4
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-t1enanwz.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-CuyCBoBf.js → Checkbox-D1CB-7bq.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-DjWtYHNe.js → Codegen-BPx3dQ2q.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CrVr_iuG.js → Col-DkPTQ2Gl.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-C6QxpfGc.js → Community-ZriaxRlr.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-B-v5r6Pa.js → Compact-C_qJ0P7F.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-zNiLiFgD.js → Compliance-Bgoy-saS.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-D9K7lMOu.js → Cowork-B5i9y6XK.js} +2 -2
  21. package/src/assets/web-panel/assets/{Cron-DAjO36z4.js → Cron-D7vBJ5-J.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-Bxqn0aqB.js → Crosschain-D4kvoGI_.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DfRmLUe-.js → DID-BLOeBd-r.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-Cz8KF3fr.js → Dashboard-mecJaonC.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-C4oVfkP0.js → Dropdown-GPKwaFer.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-ivyZKN8k.js → EmailListRenderer-BML9m7Dd.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DoxY1CPW.js → FamilyGuardDashboard-DN5bAtJC.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-C93gZxnb.js → Federation-DmD6Gecd.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-D_lEjYJE.js → FormItemContext-6wwplN_K.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-BNFN9YjN.js → GenericCardRenderer-DUhpLkDL.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-mUu2HcLI.js → Git-eJfyXkwf.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CNuosrge.js → Governance-swAUW59x.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-DwY5pbCB.js → Inference-CbdwJPDJ.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-aRUxhACD.js → KnowledgeGraph-UuYpg1nm.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DFfsWYy_.js → Logs-CS0G057y.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-BxIIB4k3.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-COI-ciM-.js → Marketplace-CZRjuvvI.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-BJJwaIpe.js → McpTools-BOJ9A_Rf.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-CDO6SGDZ.js → Memory-BnkrR-Ok.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-BlZ5tFf4.js → MobileBridge-Do4mPi13.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-DuoxbgWz.js → MobileProjects-2JxWa6-p.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-6ec9j70b.js → Mtc-CS_mnpGd.js} +2 -2
  43. package/src/assets/web-panel/assets/{MtcAudit-BuL7HkC7.js → MtcAudit-DZ4J_351.js} +5 -5
  44. package/src/assets/web-panel/assets/{Multisig-CJxR85lk.js → Multisig-Jh74zKXu.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-B71O1S4l.js → NLProgramming-_4n2BfnS.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-Bsw5zbpV.js → Notes-CtENcKHv.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-BnAhXuK_.js → NotificationSettings-dgDCvpK9.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-BJ0R5GGz.js → OrderTableRenderer-D5VxCrmG.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-B7wwNxoP.js → Organization-CpIF8Xkd.js} +2 -2
  50. package/src/assets/web-panel/assets/{Overflow-CfAGr0gM.js → Overflow-aHnBZaez.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-KhMg22Fz.js → P2P-8ppzog2V.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-NdAXI9ft.js → PdhVaultBrowser-D3p1BXkp.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-CIYjqyT7.js → Permissions-D7vflD5q.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-D2ht3P_R.js → PersonalDataHub-D2hY-Ek2.js} +4 -4
  55. package/src/assets/web-panel/assets/{Pipeline-i6flZW1m.js → Pipeline-qK2VqhJC.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-DE0lhYVc.js → Privacy-DHJr4uu0.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BL3YbyxS.js → ProjectInit-DMBS6trm.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-CEtdg7ni.js → ProjectSettings-D3Ng74BT.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-CvtU5peJ.js → Projects-BfJFZiIW.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-DKt_Cg-j.js → Providers-DlNA95G0.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-DA61jNSx.js → QrScannerModal-CMOIYxIm.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-fS9ryUmq.js → QuickAsk-D6MyGp5I.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-CR9dZU5Y.js → Recommend-W6WcShtf.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-BV0BR2Dz.js → RemoteSession-Dm_MjlV_.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-BIeGUvYD.js → Reputation-Ctvij6eX.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DHDT1aro.js → Row-DivbeDE-.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Cq6YKb1h.js → RssFeed-D4famoAw.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DEF6vsy6.js → Search-6gOAh3zG.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-CHtYiKY9.js → Security-DApb9kK8.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-u16lvBJN.js → Services-B8OomyE2.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CGbizyDj.js → Skeleton-BTJ2g2E3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-BZMQcAa7.js → Skills-NIRr4DD1.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-Bm-CycVi.js → Sla-BQHP_6px.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-BudpA5kr.js → SpeechSettings-BVQTDSVS.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-B8q1C1eC.js → SyncSettings-BOD4Mar6.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-SU1pBWc-.js → Tasks-Ciu7H2-y.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CyOfJzmt.js → Templates-CtlwavRU.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-xqWSm2GP.js → Tenant-QLWYJdL6.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-D1Ttgjsi.js → Terminal-B3q10mjm.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-Da2lYs5D.js → TimelineRenderer-CqltBA_8.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-B34-SduO.js → Tokens-CJOKrj4y.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-C8zyYm4R.js → Trigger-CPMGgfdM.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-D1Pvqems.js → Trust-DiJms7Bl.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-Do3VVnAy.js → UkeySign-rakR8eel.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-Dz7egVIA.js → VideoEditing-DAWZUM5o.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-Dcuw-OxR.js → Wallet-DqUPnl7K.js} +3 -3
  87. package/src/assets/web-panel/assets/{WebAuthn-DPlw-QsB.js → WebAuthn-BnVUwvMm.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-h4OsnU5q.js → WorkflowEditor-B1CAwxgs.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-eO9wEwrW.js → chat-k2-0Jzfy.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-34lSmOXw.js → colors-BAu8xBmW.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-CK4kEWJ4.js → compact-item-DMlqcdfI.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-E0A57xed.js → createContext-BU9kfiSw.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DuGrUMAS.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-BD9ZMGAl.js → hasIn-2vacgdcl.js} +1 -1
  95. package/src/assets/web-panel/assets/{index--N0u6kTG.js → index-B-C-Ruft.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DzXjP44T.js → index-B7wDjYUd.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CZBaqe3d.js → index-BMq0frKK.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DrOalGut.js → index-BUX4W-2v.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CT1_eRL-.js → index-BZz2eB33.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DrsDA_md.js → index-BblNQlaA.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DP-UZAQN.js → index-BdfKoqsK.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DiT_REby.js → index-Bf8YofPE.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Cx3Jn1r0.js → index-Bn8tARil.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B0rkHxKK.js → index-Bpe2CJd-.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B_G_ElKO.js → index-BxctzdYQ.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-MIg5Z8qe.js → index-C24NoPpy.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BmNbU2Z6.js → index-C5C4kSi8.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BsGmo6v1.js → index-C6ICn9Y6.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CsrKJJcX.js → index-C8ldqZi6.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BbX_Dted.js → index-C9WsM29I.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Ch175NUw.js → index-CONPVaxw.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DONOUtlz.js → index-CPyYXKFB.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DFLE2qO9.js → index-CSvSf9px.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-o8pYehRq.js → index-CXmpR6N3.js} +3 -3
  115. package/src/assets/web-panel/assets/{index-Cz3unNfL.js → index-Chybe7Ge.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-yAGBu2E0.js → index-CyXmP3PW.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CuSau5ya.js → index-DCusBOqR.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DcE1BspQ.js → index-DH01oIaj.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DrSAAuJj.js → index-DHg3LMNP.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CZkFMeWL.js → index-DWLTSIka.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DvKcroix.js → index-DaUGdvtU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Bjs90Eh9.js → index-DcA-tEQd.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DGRxt5wj.js → index-DfWvcu4p.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DCn-ECvK.js → index-DmZNnZz7.js} +1 -1
  125. package/src/assets/web-panel/assets/index-DvFfMAux.js +1 -0
  126. package/src/assets/web-panel/assets/{index-8qMA1DWQ.js → index-JsyGqKmD.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-D4bB_x_v.js → index-TtrpHmYx.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Brqc9Emx.js → index-Ygh0wmKz.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Da5fmOHB.js → index-dIYqw3f0.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DpfisY1g.js → index-hDHHJYno.js} +1 -1
  131. package/src/assets/web-panel/assets/index-n6p-1A77.js +1 -0
  132. package/src/assets/web-panel/assets/{index-DeXNCyQJ.js → index-oElehY4F.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DcbgVLOH.js → index-z4_YwZDW.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-DMTkAomF.js → initDefaultProps-B9OXWu2e.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-Cnti1F5g.js → motion-IQ47MCDQ.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-CGxmHUga.js → move-CLCU4kjV.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-CuwwLoq7.js → mtc-parser-CXnVlSPq.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BpdlTkPM.js → omit-BJjLXB0f.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-D7nWrThp.js → pickAttrs-BHdtvdy6.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-Bhx0TV8F.js → placementArrow-oq8X_Bwc.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-CZ1KesZh.js → responsiveObserve-DTD02LAO.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-CnldF8J6.js → slide-DbEeq8to.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-CZfo_GOA.js → statusUtils-Do2fy1CJ.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-B2QCcAv5.js → styleChecker-CFWD63T-.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DzzjIS4J.js → useFlexGapSupport-BeozAWOo.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-B_atg9M0.js → useFs-0-rIgnBL.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-DhZs3QYN.js → usePersonalDataHub-CeiNoI31.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DcePTYAm.js → vnode-Dj0ReRNg.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-BYmlnjRk.js → zoom-DD7MC4Dy.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +3 -3
  152. package/src/commands/agent.js +18 -1
  153. package/src/commands/evolution-benchmark.js +72 -0
  154. package/src/commands/evolution-knowledge.js +40 -1
  155. package/src/commands/evolution.js +2 -0
  156. package/src/commands/governed-skill-marketplace.js +142 -0
  157. package/src/commands/marketplace.js +4 -1
  158. package/src/commands/serve.js +21 -0
  159. package/src/commands/skill.js +3 -0
  160. package/src/data/changelog.json +39 -0
  161. package/src/gateways/ws/ws-agent-handler.js +59 -2
  162. package/src/gateways/ws/ws-server.js +2 -0
  163. package/src/generated/cc-agent-protocol.schema.json +3 -1
  164. package/src/harness/golden-transcript.js +1 -0
  165. package/src/harness/prompt-compressor.js +51 -5
  166. package/src/harness/provider-backed-compaction.js +28 -1
  167. package/src/harness/remote-session-registry.js +15 -3
  168. package/src/index.js +20 -2
  169. package/src/lazy-dispatch.js +6 -0
  170. package/src/lib/advisor-runtime.js +55 -2
  171. package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
  172. package/src/lib/app-server/graph-runtime.js +32 -0
  173. package/src/lib/app-server/server.js +94 -1
  174. package/src/lib/app-server/websocket-transport.js +15 -0
  175. package/src/lib/autonomous-agent.js +63 -13
  176. package/src/lib/cowork/ab-comparator-cli.js +4 -3
  177. package/src/lib/cowork/debate-review-cli.js +4 -3
  178. package/src/lib/cowork/decision-kb-cli.js +5 -0
  179. package/src/lib/cowork-adapter.js +38 -16
  180. package/src/lib/evolution/agent-evolution-ingress.js +95 -15
  181. package/src/lib/evolution/agent-evolution-runtime-composition.js +82 -0
  182. package/src/lib/evolution/agent-evolution-session-lifecycle.js +46 -0
  183. package/src/lib/evolution/agent-model-projection.js +437 -0
  184. package/src/lib/evolution/bounded-descriptor-read.js +29 -0
  185. package/src/lib/evolution/controlled-skill-pilot-ledger-adapter.js +551 -0
  186. package/src/lib/evolution/controlled-skill-production-pilot.js +308 -18
  187. package/src/lib/evolution/evidence-backed-wiki-maintainer.js +32 -10
  188. package/src/lib/evolution/evidence-json-text.js +236 -0
  189. package/src/lib/evolution/evolution-artifact-ports.js +196 -21
  190. package/src/lib/evolution/evolution-deployment-loader.js +240 -2
  191. package/src/lib/evolution/evolution-eval-child-evidence-ledger-adapter.js +373 -0
  192. package/src/lib/evolution/evolution-eval-gate.js +14 -1
  193. package/src/lib/evolution/evolution-eval-process-supervisor-worker.mjs +14 -0
  194. package/src/lib/evolution/evolution-eval-process-supervisor.js +607 -0
  195. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +14 -1
  196. package/src/lib/evolution/evolution-evidence-projector.js +271 -37
  197. package/src/lib/evolution/evolution-file-witness.js +153 -30
  198. package/src/lib/evolution/evolution-ledger-ports.js +1219 -66
  199. package/src/lib/evolution/evolution-ledger.js +66 -2
  200. package/src/lib/evolution/evolution-raw-crypto-shred.js +29 -15
  201. package/src/lib/evolution/evolution-raw-deletion-ledger-adapter.js +865 -0
  202. package/src/lib/evolution/evolution-release-train-domain-stages.js +769 -0
  203. package/src/lib/evolution/evolution-release-train-stage-output-ledger-adapter.js +333 -0
  204. package/src/lib/evolution/evolution-release-train.js +54 -6
  205. package/src/lib/evolution/evolution-workbench-batch-executor.js +101 -144
  206. package/src/lib/evolution/evolution-workbench-control-ports.js +203 -0
  207. package/src/lib/evolution/evolution-workbench-file-resources.js +403 -0
  208. package/src/lib/evolution/evolution-workbench-projection.js +134 -26
  209. package/src/lib/evolution/evolution-workbench-registry-source.js +482 -0
  210. package/src/lib/evolution/evolution-workbench-review-ledger-adapter.js +823 -0
  211. package/src/lib/evolution/evolution-workbench-review-protocol.js +157 -0
  212. package/src/lib/evolution/evolution-workbench-rollback-authorization.js +57 -0
  213. package/src/lib/evolution/evolution-workbench-rollback-ledger-adapter.js +1016 -0
  214. package/src/lib/evolution/evolution-workbench-runtime.js +133 -0
  215. package/src/lib/evolution/evolution-workbench-version-control.js +70 -36
  216. package/src/lib/evolution/evolvable-artifact-ledger-adapter.js +48 -0
  217. package/src/lib/evolution/governed-knowledge-candidate-rejection.js +343 -0
  218. package/src/lib/evolution/governed-knowledge-dependency-authority.js +227 -44
  219. package/src/lib/evolution/governed-knowledge-dependency-inventory.js +392 -0
  220. package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +217 -82
  221. package/src/lib/evolution/governed-knowledge-quarantine-release.js +1013 -0
  222. package/src/lib/evolution/governed-knowledge-record.js +148 -0
  223. package/src/lib/evolution/governed-knowledge-revocation-host.js +59 -0
  224. package/src/lib/evolution/governed-knowledge-revocation-record.js +135 -0
  225. package/src/lib/evolution/governed-knowledge-skill-rollback.js +510 -0
  226. package/src/lib/evolution/governed-knowledge-sync.js +181 -95
  227. package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +516 -0
  228. package/src/lib/evolution/governed-skill-marketplace-badge.js +208 -0
  229. package/src/lib/evolution/governed-skill-marketplace-candidate.js +330 -0
  230. package/src/lib/evolution/governed-skill-marketplace-cli-host.js +308 -0
  231. package/src/lib/evolution/governed-skill-marketplace-ledger-adapter.js +420 -0
  232. package/src/lib/evolution/governed-skill-marketplace.js +288 -5
  233. package/src/lib/evolution/governed-wiki-pruning-journal.js +302 -0
  234. package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +459 -0
  235. package/src/lib/evolution/governed-wiki-pruning-maintenance.js +576 -0
  236. package/src/lib/evolution/governed-wiki-pruning-plan-authority.js +169 -0
  237. package/src/lib/evolution/governed-wiki-pruning-raw-shred.js +207 -0
  238. package/src/lib/evolution/governed-wiki-pruning-retrieval.js +587 -0
  239. package/src/lib/evolution/governed-wiki-pruning-runtime.js +153 -0
  240. package/src/lib/evolution/governed-wiki-pruning-skill-rollback.js +360 -0
  241. package/src/lib/evolution/governed-wiki-pruning.js +322 -143
  242. package/src/lib/evolution/independent-skill-revocation-source.js +231 -0
  243. package/src/lib/evolution/knowledge-wiki-source-admission.js +283 -0
  244. package/src/lib/evolution/knowledge-wiki-source-provenance.js +360 -0
  245. package/src/lib/evolution/progressive-canary-external-watchdog.js +578 -0
  246. package/src/lib/evolution/progressive-canary-traffic-worker.js +628 -0
  247. package/src/lib/evolution/progressive-canary-watchdog-file-store.js +285 -0
  248. package/src/lib/evolution/progressive-canary-watchdog-node-pki.js +265 -0
  249. package/src/lib/evolution/skill-candidate-registry.js +43 -3
  250. package/src/lib/evolution/skill-promotion-controller.js +25 -0
  251. package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +100 -0
  252. package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +131 -2
  253. package/src/lib/evolution/skill-release-registry.js +168 -4
  254. package/src/lib/evolution/skill-retrieval-revocation-authority.js +361 -0
  255. package/src/lib/evolution/skill-retrieval-revocation-ledger-adapter.js +346 -0
  256. package/src/lib/evolution/skill-revocation-propagation.js +467 -0
  257. package/src/lib/evolution/skill-target-matrix-eval.js +162 -11
  258. package/src/lib/evolution/skill-wiki-reconciliation.js +985 -0
  259. package/src/lib/evolution/skill-writer-inventory-manifest.js +8 -6
  260. package/src/lib/evolution/statistical-progressive-canary.js +165 -3
  261. package/src/lib/evolution/structured-memory-agent-control-plane.js +120 -0
  262. package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +5 -1
  263. package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +126 -0
  264. package/src/lib/evolution/wiki-informed-skill-proposer.js +127 -21
  265. package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +822 -101
  266. package/src/lib/evolution/wiki-revision-protocol.js +120 -0
  267. package/src/lib/evolution/wiki-skill-proposal-ledger-adapter.js +307 -0
  268. package/src/lib/evolution/wiki-target-tombstone-revision.js +109 -0
  269. package/src/lib/evolution/wikiskill-benchmark-cli-host.js +178 -0
  270. package/src/lib/evolution/wikiskill-benchmark-execution-host.js +702 -0
  271. package/src/lib/evolution/wikiskill-benchmark-ledger-adapter.js +613 -0
  272. package/src/lib/evolution/wikiskill-benchmark.js +80 -16
  273. package/src/lib/goal-assess.js +17 -10
  274. package/src/lib/interactive-planner.js +9 -1
  275. package/src/lib/iteration-budget.js +16 -2
  276. package/src/lib/micro-compact.js +4 -1
  277. package/src/lib/model-failure-policy.js +21 -0
  278. package/src/lib/process-execution-broker/index.js +1 -0
  279. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  280. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  281. package/src/lib/process-execution-broker/windows-sandbox.cs +33 -15
  282. package/src/lib/read-file-loop-guard.js +113 -0
  283. package/src/lib/read-file-page.js +191 -0
  284. package/src/lib/runnable-provider.js +2 -1
  285. package/src/lib/skill-retrieval-router.js +22 -1
  286. package/src/repl/agent-repl.js +133 -34
  287. package/src/runtime/agent-core.js +196 -74
  288. package/src/runtime/agent-runtime.js +43 -0
  289. package/src/runtime/coding-agent-contract-shared.cjs +7 -1
  290. package/src/runtime/fallback-model.js +143 -62
  291. package/src/runtime/headless-runner.js +54 -10
  292. package/src/runtime/headless-stream.js +50 -6
  293. package/src/runtime/runtime-factory.js +41 -2
  294. package/src/assets/web-panel/assets/ChatBubbleRenderer-Ds3pA-ET.js +0 -1
  295. package/src/assets/web-panel/assets/MarkdownRenderer-DqTx7_u1.js +0 -1
  296. package/src/assets/web-panel/assets/devWarning-CF3xafX2.js +0 -1
  297. package/src/assets/web-panel/assets/index-C907rPwd.js +0 -1
  298. package/src/assets/web-panel/assets/index-wueRSK2d.js +0 -1
@@ -12,6 +12,7 @@ import {
12
12
  EVOLUTION_ARTIFACT_STORE_FAILED_CODE,
13
13
  EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
14
14
  EvolutionArtifactPorts,
15
+ captureEvolutionLedgerBatchResolver,
15
16
  } from "./evolution-artifact-ports.js";
16
17
  import {
17
18
  EVOLUTION_ARTIFACT_REF_SCHEMA,
@@ -35,18 +36,47 @@ import {
35
36
  SKILL_RELEASE_LEDGER_PROJECTION_SCHEMA,
36
37
  SKILL_RELEASE_STATE_LEDGER_MIGRATION_SCHEMA,
37
38
  SKILL_RELEASE_STATE_MIGRATION_RECEIPT_SCHEMA,
39
+ verifySkillRelease,
38
40
  verifySkillReleaseState,
39
41
  verifySkillReleaseStateMigrationPlan,
40
42
  } from "./skill-release-registry.js";
43
+ import {
44
+ GOVERNED_KNOWLEDGE_DEPENDENCY_PREPARED_EVENT_TYPE,
45
+ verifyGovernedKnowledgeDependencyPrepared,
46
+ } from "./governed-knowledge-dependency-ledger-executor.js";
47
+ import {
48
+ GOVERNED_KNOWLEDGE_QUARANTINE_RELEASE_EVENT_TYPE,
49
+ verifyGovernedKnowledgeQuarantineReleaseRecord,
50
+ } from "./governed-knowledge-quarantine-release.js";
51
+ import {
52
+ WIKI_LEDGER_EVENT_TYPE,
53
+ WikiMaintainerLedgerAdapter,
54
+ captureWikiRevisionReader,
55
+ } from "./wiki-maintainer-ledger-adapter.js";
41
56
 
42
57
  export const EVOLUTION_LEDGER_PORTS_INVALID_CODE =
43
58
  "CC_EVOLUTION_LEDGER_PORTS_INVALID";
59
+ const RELEASE_OPERATION_READERS = new WeakMap();
60
+
61
+ // This read-only recovery surface is minted only alongside real Ledger ports.
62
+ // Matching JSON, inherited methods or a caller-supplied query function cannot
63
+ // establish that a release operation actually committed.
64
+ export function captureSkillReleaseOperationReader(transactionLedger) {
65
+ const reader = RELEASE_OPERATION_READERS.get(transactionLedger);
66
+ if (!reader)
67
+ throw new TypeError("a branded release transaction ledger is required");
68
+ return reader;
69
+ }
44
70
  export const EVOLUTION_LEDGER_PORTS_COLLISION_CODE =
45
71
  "CC_EVOLUTION_LEDGER_PORTS_COLLISION";
46
72
  export const EVOLUTION_LEDGER_PORTS_CORRUPT_CODE =
47
73
  "CC_EVOLUTION_LEDGER_PORTS_CORRUPT";
48
74
  export const EVOLUTION_LEDGER_PORTS_UNAVAILABLE_CODE =
49
75
  "CC_EVOLUTION_LEDGER_PORTS_UNAVAILABLE";
76
+ export const EVOLUTION_LEDGER_CANDIDATE_REVOKED_CODE =
77
+ "CC_EVOLUTION_LEDGER_CANDIDATE_REVOKED";
78
+ export const EVOLUTION_LEDGER_SOURCE_REVOKED_CODE =
79
+ "CC_EVOLUTION_LEDGER_SOURCE_REVOKED";
50
80
  export const EVOLUTION_ARTIFACT_DURABILITY_BINDING_SCHEMA =
51
81
  "chainlesschain.evolution-artifact-durability-binding/v1";
52
82
  export const EVOLUTION_ARTIFACT_DURABILITY_RETAIN_REQUEST_SCHEMA =
@@ -1127,6 +1157,7 @@ class EvolutionLedgerDomainPorts {
1127
1157
  #appendDomainEvent;
1128
1158
  #artifactPut;
1129
1159
  #artifactResolve;
1160
+ #artifactResolveBatch;
1130
1161
  #artifactTenantId;
1131
1162
  #audience;
1132
1163
  #durabilityAuthority;
@@ -1134,6 +1165,7 @@ class EvolutionLedgerDomainPorts {
1134
1165
  #durabilityRetain;
1135
1166
  #ledgerQuery;
1136
1167
  #ledgerRead;
1168
+ #ledgerVerify;
1137
1169
  #ledgerVerifyReceipt;
1138
1170
  #purpose;
1139
1171
 
@@ -1161,6 +1193,9 @@ class EvolutionLedgerDomainPorts {
1161
1193
  this.#ledgerRead = Object.freeze(
1162
1194
  EvolutionLedger.prototype.read.bind(ledger),
1163
1195
  );
1196
+ this.#ledgerVerify = Object.freeze(
1197
+ EvolutionLedger.prototype.verify.bind(ledger),
1198
+ );
1164
1199
  this.#ledgerVerifyReceipt = Object.freeze(
1165
1200
  EvolutionLedger.prototype.verifyReceipt.bind(ledger),
1166
1201
  );
@@ -1172,6 +1207,9 @@ class EvolutionLedgerDomainPorts {
1172
1207
  artifactPorts,
1173
1208
  Object.freeze({ purpose: this.#purpose }),
1174
1209
  );
1210
+ this.#artifactResolveBatch = captureEvolutionLedgerBatchResolver(
1211
+ this.#artifactResolve,
1212
+ );
1175
1213
  Object.freeze(this);
1176
1214
  }
1177
1215
 
@@ -1452,26 +1490,32 @@ class EvolutionLedgerDomainPorts {
1452
1490
  return ref;
1453
1491
  }
1454
1492
 
1455
- #resolveSubject(event, expectedType, expectedAudience = null) {
1493
+ #resolveSubject(
1494
+ event,
1495
+ expectedType,
1496
+ expectedAudience = null,
1497
+ capturedResolution = null,
1498
+ ) {
1456
1499
  const ref = normalizeArtifactRef(
1457
1500
  event.subjectRef,
1458
1501
  "domain event subjectRef",
1459
1502
  EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
1460
1503
  );
1461
1504
  const durable = this.#resolveDurably(ref, expectedType);
1462
- let resolution = null;
1505
+ let resolution = capturedResolution;
1463
1506
  try {
1464
- resolution = assertSynchronous(
1465
- this.#artifactResolve(
1466
- deepFreeze({
1467
- epoch: event.epoch,
1468
- ledgerId: event.ledgerId,
1469
- ref,
1470
- tenantId: this.#artifactTenantId,
1471
- }),
1472
- ),
1473
- "artifact resolver result",
1474
- );
1507
+ if (resolution === null)
1508
+ resolution = assertSynchronous(
1509
+ this.#artifactResolve(
1510
+ deepFreeze({
1511
+ epoch: event.epoch,
1512
+ ledgerId: event.ledgerId,
1513
+ ref,
1514
+ tenantId: this.#artifactTenantId,
1515
+ }),
1516
+ ),
1517
+ "artifact resolver result",
1518
+ );
1475
1519
  } catch {
1476
1520
  // A removed/corrupt local cache is recoverable only through the trusted
1477
1521
  // durability authority's exact canonical-byte replica above.
@@ -1698,7 +1742,40 @@ class EvolutionLedgerDomainPorts {
1698
1742
  }
1699
1743
 
1700
1744
  #snapshot() {
1701
- return this.#indexSnapshot(this.#events());
1745
+ const snapshot = this.#indexSnapshot(this.#events());
1746
+ const types = new Set([
1747
+ EVENT_TYPES.prepare,
1748
+ EVENT_TYPES.finalize,
1749
+ EVENT_TYPES.migration,
1750
+ EVENT_TYPES.audit,
1751
+ ]);
1752
+ const subjects = new Map();
1753
+ for (const event of snapshot.events) {
1754
+ if (types.has(event.type)) subjects.set(event.subjectRef.ref, event);
1755
+ // Bound retained byte buffers independently of total ledger size. Larger
1756
+ // histories keep the existing individually verified streaming path.
1757
+ if (subjects.size > 16) return snapshot;
1758
+ }
1759
+ if (subjects.size) {
1760
+ const events = [...subjects.values()];
1761
+ try {
1762
+ const results = this.#artifactResolveBatch(
1763
+ events.map((event) => ({
1764
+ epoch: event.epoch,
1765
+ ledgerId: event.ledgerId,
1766
+ ref: event.subjectRef,
1767
+ tenantId: this.#artifactTenantId,
1768
+ })),
1769
+ );
1770
+ snapshot.localResolutions = new Map(
1771
+ events.map((event, index) => [event.subjectRef.ref, results[index]]),
1772
+ );
1773
+ } catch {
1774
+ // As on individual reads, a missing local cache may recover only from
1775
+ // the independently authenticated exact-byte durability authority.
1776
+ }
1777
+ }
1778
+ return snapshot;
1702
1779
  }
1703
1780
 
1704
1781
  #snapshotWithVerifiedEvent(snapshot, verification) {
@@ -1743,7 +1820,12 @@ class EvolutionLedgerDomainPorts {
1743
1820
  const cacheKey = `${expectedType}\0${expectedAudience ?? ""}\0${ref.ref}\0${ref.digest}`;
1744
1821
  let record = snapshot.subjects.get(cacheKey);
1745
1822
  if (!record) {
1746
- record = this.#resolveSubject(event, expectedType, expectedAudience);
1823
+ record = this.#resolveSubject(
1824
+ event,
1825
+ expectedType,
1826
+ expectedAudience,
1827
+ snapshot.localResolutions?.get(ref.ref) ?? null,
1828
+ );
1747
1829
  snapshot.subjects.set(cacheKey, record);
1748
1830
  }
1749
1831
  return record;
@@ -2274,7 +2356,7 @@ class EvolutionLedgerDomainPorts {
2274
2356
  return { existing: null, lineages, prepared };
2275
2357
  }
2276
2358
 
2277
- migrate(input) {
2359
+ migrate(input, releases) {
2278
2360
  const migration = normalizeStateMigration(input);
2279
2361
  const transactionId = migration.plan.stateMigrationDigest;
2280
2362
  const eventId = deterministicEventId("migration", { transactionId });
@@ -2310,6 +2392,29 @@ class EvolutionLedgerDomainPorts {
2310
2392
  "release state migration requires an empty Skill ledger lineage",
2311
2393
  );
2312
2394
  }
2395
+ if (releases !== undefined) {
2396
+ assertAllExactRecord(
2397
+ releases,
2398
+ new Set(["active", "lastKnownGood"]),
2399
+ "migration release evidence",
2400
+ );
2401
+ }
2402
+ for (const [key, releaseDigest] of [
2403
+ ["active", migration.plan.activeReleaseDigest],
2404
+ ["lastKnownGood", migration.plan.lastKnownGoodReleaseDigest],
2405
+ ]) {
2406
+ this.#assertReleaseNotRevoked(
2407
+ snapshot,
2408
+ {
2409
+ tenantId: migration.plan.tenantId,
2410
+ skillName: migration.plan.skillName,
2411
+ audience: this.#audience,
2412
+ releaseDigest,
2413
+ candidateId: null,
2414
+ },
2415
+ releases?.[key],
2416
+ );
2417
+ }
2313
2418
  const subjectRef = this.#putSubject(
2314
2419
  ARTIFACT_TYPES.migration,
2315
2420
  migration,
@@ -2367,65 +2472,553 @@ class EvolutionLedgerDomainPorts {
2367
2472
  );
2368
2473
  }
2369
2474
 
2370
- prepare(input) {
2475
+ *#knowledgeRevocations(snapshot, tenantId, audience) {
2476
+ // A prepared revocation is already a durable admission fence. Waiting for
2477
+ // every dependency effect to settle would allow promotion while offline
2478
+ // recovery, active rollback or another dependency is still outstanding.
2479
+ // Scan all streams/devices in this tenant; a new controller cannot opt out.
2480
+ for (const event of snapshot.events) {
2481
+ if (
2482
+ event.type !== GOVERNED_KNOWLEDGE_DEPENDENCY_PREPARED_EVENT_TYPE ||
2483
+ event.tenantId !== tenantId
2484
+ )
2485
+ continue;
2486
+ if (
2487
+ event.schema !== EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA ||
2488
+ event.artifactTenantId !== this.#artifactTenantId ||
2489
+ event.decision !== "prepared" ||
2490
+ !Array.isArray(event.sourceRefs) ||
2491
+ event.sourceRefs.length !== 0
2492
+ ) {
2493
+ throw portsError(
2494
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2495
+ "candidate revocation event binding is invalid",
2496
+ );
2497
+ }
2498
+ const ref = normalizeArtifactRef(
2499
+ event.subjectRef,
2500
+ "candidate revocation subjectRef",
2501
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2502
+ );
2503
+ // Knowledge records use their own durable ArtifactStore, not the release
2504
+ // replica. Missing or corrupt retained bytes must fail closed, never be
2505
+ // interpreted as the absence of a revocation.
2506
+ const resolution = assertSynchronous(
2507
+ this.#artifactResolve(
2508
+ deepFreeze({
2509
+ epoch: event.epoch,
2510
+ ledgerId: event.ledgerId,
2511
+ ref,
2512
+ tenantId: this.#artifactTenantId,
2513
+ }),
2514
+ ),
2515
+ "candidate revocation artifact resolution",
2516
+ );
2517
+ assertAllExactRecord(
2518
+ resolution,
2519
+ LEDGER_RESOLUTION_KEYS,
2520
+ "candidate revocation artifact resolution",
2521
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2522
+ );
2523
+ if (
2524
+ resolution.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
2525
+ resolution.authenticated !== true ||
2526
+ resolution.found !== true ||
2527
+ resolution.ref !== ref.ref ||
2528
+ resolution.digest !== ref.digest
2529
+ ) {
2530
+ throw portsError(
2531
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2532
+ "candidate revocation artifact is not authenticated and exactly bound",
2533
+ );
2534
+ }
2535
+ digest(
2536
+ resolution.receiptDigest,
2537
+ "candidate revocation artifact receiptDigest",
2538
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2539
+ );
2540
+ const bytes = copyBytes(resolution.bytes);
2541
+ if (sha256(bytes) !== ref.digest) {
2542
+ throw portsError(
2543
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2544
+ "candidate revocation artifact digest mismatch",
2545
+ );
2546
+ }
2547
+ const json = bufferToString(bytes, "utf8");
2548
+ let record;
2549
+ try {
2550
+ record = JSON.parse(json);
2551
+ } catch (cause) {
2552
+ throw portsError(
2553
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2554
+ "candidate revocation artifact is not JSON",
2555
+ { cause },
2556
+ );
2557
+ }
2558
+ assertAllExactRecord(
2559
+ record,
2560
+ ARTIFACT_RECORD_KEYS,
2561
+ "candidate revocation artifact",
2562
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2563
+ );
2564
+ if (
2565
+ canonicalJson(record) !== json ||
2566
+ record.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
2567
+ record.tenantId !== this.#artifactTenantId ||
2568
+ record.type !== "governed-knowledge-dependency-operation" ||
2569
+ record.retention !== "ledger" ||
2570
+ record.purpose !== this.#purpose ||
2571
+ record.audience !== audience
2572
+ ) {
2573
+ throw portsError(
2574
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2575
+ "candidate revocation artifact boundary is invalid",
2576
+ );
2577
+ }
2578
+ const prepared = verifyGovernedKnowledgeDependencyPrepared(record.value, {
2579
+ tenantId: event.tenantId,
2580
+ deviceId: record.value?.deviceId,
2581
+ });
2582
+ if (
2583
+ event.eventId !==
2584
+ `${GOVERNED_KNOWLEDGE_DEPENDENCY_PREPARED_EVENT_TYPE}.${prepared.operationDigest.slice(7)}`
2585
+ ) {
2586
+ throw portsError(
2587
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2588
+ "candidate revocation event does not bind its prepared operation",
2589
+ );
2590
+ }
2591
+ yield { event, prepared };
2592
+ }
2593
+ }
2594
+
2595
+ *#knowledgeQuarantineReleases(snapshot, tenantId, audience) {
2596
+ const operations = new Set();
2597
+ for (const event of snapshot.events) {
2598
+ if (
2599
+ event.type !== GOVERNED_KNOWLEDGE_QUARANTINE_RELEASE_EVENT_TYPE ||
2600
+ event.tenantId !== tenantId
2601
+ ) {
2602
+ continue;
2603
+ }
2604
+ if (
2605
+ event.schema !== EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA ||
2606
+ event.artifactTenantId !== this.#artifactTenantId ||
2607
+ event.decision !== "committed" ||
2608
+ !Array.isArray(event.sourceRefs) ||
2609
+ event.sourceRefs.length !== 0
2610
+ ) {
2611
+ throw portsError(
2612
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2613
+ "quarantine release event binding is invalid",
2614
+ );
2615
+ }
2616
+ const ref = normalizeArtifactRef(
2617
+ event.subjectRef,
2618
+ "quarantine release subjectRef",
2619
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2620
+ );
2621
+ const resolution = assertSynchronous(
2622
+ this.#artifactResolve(
2623
+ deepFreeze({
2624
+ epoch: event.epoch,
2625
+ ledgerId: event.ledgerId,
2626
+ ref,
2627
+ tenantId: this.#artifactTenantId,
2628
+ }),
2629
+ ),
2630
+ "quarantine release artifact resolution",
2631
+ );
2632
+ assertAllExactRecord(
2633
+ resolution,
2634
+ LEDGER_RESOLUTION_KEYS,
2635
+ "quarantine release artifact resolution",
2636
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2637
+ );
2638
+ if (
2639
+ resolution.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
2640
+ resolution.authenticated !== true ||
2641
+ resolution.found !== true ||
2642
+ resolution.ref !== ref.ref ||
2643
+ resolution.digest !== ref.digest
2644
+ ) {
2645
+ throw portsError(
2646
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2647
+ "quarantine release artifact is not authenticated and exactly bound",
2648
+ );
2649
+ }
2650
+ const bytes = copyBytes(resolution.bytes);
2651
+ if (sha256(bytes) !== ref.digest) {
2652
+ throw portsError(
2653
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2654
+ "quarantine release artifact digest mismatch",
2655
+ );
2656
+ }
2657
+ let artifact;
2658
+ try {
2659
+ artifact = JSON.parse(bufferToString(bytes, "utf8"));
2660
+ } catch (cause) {
2661
+ throw portsError(
2662
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2663
+ "quarantine release artifact is not JSON",
2664
+ { cause },
2665
+ );
2666
+ }
2667
+ assertAllExactRecord(
2668
+ artifact,
2669
+ ARTIFACT_RECORD_KEYS,
2670
+ "quarantine release artifact",
2671
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2672
+ );
2673
+ if (
2674
+ canonicalJson(artifact) !== bufferToString(bytes, "utf8") ||
2675
+ artifact.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
2676
+ artifact.tenantId !== this.#artifactTenantId ||
2677
+ artifact.type !== "governed-knowledge-quarantine-release" ||
2678
+ artifact.retention !== "ledger" ||
2679
+ artifact.purpose !== this.#purpose ||
2680
+ artifact.audience !== audience
2681
+ ) {
2682
+ throw portsError(
2683
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2684
+ "quarantine release artifact boundary is invalid",
2685
+ );
2686
+ }
2687
+ let release;
2688
+ try {
2689
+ release = verifyGovernedKnowledgeQuarantineReleaseRecord(
2690
+ artifact.value,
2691
+ { tenantId },
2692
+ );
2693
+ } catch (cause) {
2694
+ throw portsError(
2695
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2696
+ "quarantine release record is invalid",
2697
+ { cause },
2698
+ );
2699
+ }
2700
+ if (
2701
+ event.eventId !==
2702
+ `${GOVERNED_KNOWLEDGE_QUARANTINE_RELEASE_EVENT_TYPE}.${release.operationDigest.slice(7)}` ||
2703
+ event.timestamp !== release.committedAt ||
2704
+ operations.has(release.operationDigest)
2705
+ ) {
2706
+ throw portsError(
2707
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2708
+ "quarantine release event identity is invalid or ambiguous",
2709
+ );
2710
+ }
2711
+ operations.add(release.operationDigest);
2712
+ yield release;
2713
+ }
2714
+ }
2715
+
2716
+ #assertReleaseNotRevoked(snapshot, binding, targetInput) {
2717
+ const releases = new Map(
2718
+ [
2719
+ ...this.#knowledgeQuarantineReleases(
2720
+ snapshot,
2721
+ binding.tenantId,
2722
+ binding.audience,
2723
+ ),
2724
+ ].map((release) => [release.operationDigest, release]),
2725
+ );
2726
+ const seenOperations = new Set();
2727
+ const releaseFor = (prepared) => {
2728
+ const release = releases.get(prepared.operationDigest) ?? null;
2729
+ if (!release) return null;
2730
+ seenOperations.add(prepared.operationDigest);
2731
+ const quarantines = prepared.knowledge.dependencies.filter(
2732
+ (dependency) => dependency.disposition === "quarantine",
2733
+ );
2734
+ if (
2735
+ release.knowledgeId !== prepared.knowledge.knowledgeId ||
2736
+ release.contentDigest !== prepared.knowledge.contentDigest ||
2737
+ release.preparedRecordDigest !== prepared.recordDigest ||
2738
+ canonicalJson(release.dependencies) !== canonicalJson(quarantines)
2739
+ ) {
2740
+ throw portsError(
2741
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2742
+ "quarantine release does not bind its prepared revocation",
2743
+ );
2744
+ }
2745
+ return release;
2746
+ };
2747
+ const assertCandidate = (prepared, candidateId) => {
2748
+ const blocked = prepared.knowledge.dependencies.find(
2749
+ (dependency) =>
2750
+ dependency.kind === "candidate" &&
2751
+ dependency.digest === candidateId &&
2752
+ ["reject-candidate", "quarantine"].includes(dependency.disposition),
2753
+ );
2754
+ if (blocked) {
2755
+ throw portsError(
2756
+ EVOLUTION_LEDGER_CANDIDATE_REVOKED_CODE,
2757
+ "candidate activation is blocked by a durable knowledge revocation",
2758
+ {
2759
+ candidateId,
2760
+ operationDigest: prepared.operationDigest,
2761
+ },
2762
+ );
2763
+ }
2764
+ };
2765
+ let target = null;
2766
+ const readTarget = () => {
2767
+ if (target) return target;
2768
+ let verified;
2769
+ try {
2770
+ verified = verifySkillRelease(targetInput);
2771
+ } catch (cause) {
2772
+ throw portsError(
2773
+ EVOLUTION_LEDGER_PORTS_INVALID_CODE,
2774
+ "release admission requires verified immutable target evidence",
2775
+ { cause },
2776
+ );
2777
+ }
2778
+ if (
2779
+ verified.releaseDigest !== binding.releaseDigest ||
2780
+ verified.tenantId !== binding.tenantId ||
2781
+ verified.skillName !== binding.skillName ||
2782
+ (binding.candidateId !== null &&
2783
+ verified.candidateId !== binding.candidateId)
2784
+ ) {
2785
+ throw portsError(
2786
+ EVOLUTION_LEDGER_PORTS_INVALID_CODE,
2787
+ "release admission evidence differs from the intended target",
2788
+ );
2789
+ }
2790
+ target = verified;
2791
+ return target;
2792
+ };
2793
+ // Stream authenticated revocations: do not retain every full Knowledge
2794
+ // artifact in memory or reuse authorization evidence across attempts.
2795
+ for (const { prepared } of this.#knowledgeRevocations(
2796
+ snapshot,
2797
+ binding.tenantId,
2798
+ binding.audience,
2799
+ )) {
2800
+ const release = releaseFor(prepared);
2801
+ assertCandidate(prepared, binding.candidateId);
2802
+ readTarget();
2803
+ assertCandidate(prepared, target.candidateId);
2804
+ const knowledge = prepared.knowledge;
2805
+ const wiki = this.#releaseWikiProvenance(
2806
+ snapshot,
2807
+ binding,
2808
+ target,
2809
+ knowledge,
2810
+ release,
2811
+ );
2812
+ const sourceRef = `knowledge://${encodeURIComponent(binding.tenantId)}/${encodeURIComponent(knowledge.knowledgeId)}`;
2813
+ const targetDependencies = knowledge.dependencies.filter(
2814
+ (dependency) =>
2815
+ (dependency.kind === "active-skill" &&
2816
+ dependency.digest === target.releaseDigest) ||
2817
+ (dependency.kind === "candidate" &&
2818
+ dependency.digest === target.candidateId),
2819
+ );
2820
+ // Immutable candidate/release identities named by the quarantine remain
2821
+ // fenced forever. A release restores only the reviewed Wiki source so a
2822
+ // newly evaluated successor can traverse the ordinary promotion gates.
2823
+ const revokedRelease = targetDependencies.length > 0;
2824
+ const supersedingTarget = release !== null && !revokedRelease;
2825
+ if (
2826
+ revokedRelease ||
2827
+ wiki?.unsafePatternIds.length ||
2828
+ (!supersedingTarget &&
2829
+ target.candidate.sourceEvidenceRefs.some(
2830
+ (item) =>
2831
+ item.ref === sourceRef || item.digest === knowledge.contentDigest,
2832
+ ))
2833
+ ) {
2834
+ throw portsError(
2835
+ EVOLUTION_LEDGER_SOURCE_REVOKED_CODE,
2836
+ "release activation references a durably revoked Knowledge source or release",
2837
+ {
2838
+ candidateId: target.candidateId,
2839
+ releaseDigest: target.releaseDigest,
2840
+ operationDigest: prepared.operationDigest,
2841
+ },
2842
+ );
2843
+ }
2844
+ }
2845
+ if (seenOperations.size !== releases.size) {
2846
+ throw portsError(
2847
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2848
+ "quarantine release has no authenticated prepared revocation",
2849
+ );
2850
+ }
2851
+ // Bare legacy calls remain compatible only before any Knowledge revocation.
2852
+ // Once a fence exists, missing provenance must not mean unrelated/safe.
2853
+ if (targetInput !== undefined) readTarget();
2854
+ }
2855
+
2856
+ #releaseWikiProvenance(snapshot, binding, target, knowledge, release = null) {
2857
+ if (target.candidate.derivationMode === "wiki") {
2858
+ // Discover the original run on the same authenticated ledger. Neither a
2859
+ // configurable reader nor a self-reported safe subset establishes origin.
2860
+ const event = snapshot.byEventId.get(
2861
+ `wiki.revision.${target.candidate.wikiRevision.slice(5)}`,
2862
+ );
2863
+ if (
2864
+ !event ||
2865
+ event.type !== WIKI_LEDGER_EVENT_TYPE ||
2866
+ event.tenantId !== binding.tenantId ||
2867
+ event.artifactTenantId !== this.#artifactTenantId
2868
+ ) {
2869
+ throw portsError(
2870
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
2871
+ "release admission cannot authenticate its original Wiki revision",
2872
+ );
2873
+ }
2874
+ const readOnly = () => {
2875
+ throw new TypeError("admission Wiki reader is read-only");
2876
+ };
2877
+ const adapter = new WikiMaintainerLedgerAdapter({
2878
+ descriptor: {
2879
+ tenantId: binding.tenantId,
2880
+ artifactTenantId: this.#artifactTenantId,
2881
+ evolutionRunId: event.correlationId,
2882
+ audience: binding.audience,
2883
+ purpose: this.#purpose,
2884
+ },
2885
+ artifactPorts: { putCanonical: readOnly },
2886
+ ledger: {
2887
+ read: this.#ledgerRead,
2888
+ verify: this.#ledgerVerify,
2889
+ appendDomainEvent: readOnly,
2890
+ },
2891
+ ledgerArtifactResolver: this.#artifactResolve,
2892
+ });
2893
+ const reader = captureWikiRevisionReader(adapter);
2894
+ const revision = reader.readKnowledgeProvenance({
2895
+ tenantId: binding.tenantId,
2896
+ revisionId: target.candidate.wikiRevision,
2897
+ knowledgeId: knowledge.knowledgeId,
2898
+ contentDigest: knowledge.contentDigest,
2899
+ });
2900
+ const tail = snapshot.events.at(-1);
2901
+ if (
2902
+ revision.ledgerHead.sequence !== tail.sequence ||
2903
+ revision.ledgerHead.headDigest !== tail.eventDigest ||
2904
+ ["epoch", "ledgerId", "identityDigest"].some(
2905
+ (key) => revision.ledgerHead[key] !== tail[key],
2906
+ )
2907
+ ) {
2908
+ throw portsError(
2909
+ EVOLUTION_LEDGER_PORTS_UNAVAILABLE_CODE,
2910
+ "ledger changed while checking immutable Wiki provenance",
2911
+ );
2912
+ }
2913
+ const releasedDependency = release?.dependencies.find(
2914
+ (dependency) =>
2915
+ dependency.kind === "wiki" &&
2916
+ dependency.disposition === "quarantine" &&
2917
+ dependency.digest === revision.stateDigest,
2918
+ );
2919
+ if (releasedDependency) {
2920
+ const current = reader.loadWiki();
2921
+ const restored = revision.affectedPatternIds.every(
2922
+ (patternId) =>
2923
+ current.state.patterns[patternId]?.status !== "quarantined" &&
2924
+ current.state.evolutionLog.some(
2925
+ (entry) =>
2926
+ entry.type === "pattern-quarantine-released" &&
2927
+ entry.subjectId === patternId &&
2928
+ entry.details?.operationDigest === release.operationDigest &&
2929
+ entry.details?.releaseRecordDigest === release.recordDigest,
2930
+ ),
2931
+ );
2932
+ if (restored) {
2933
+ return deepFreeze({ ...revision, unsafePatternIds: [] });
2934
+ }
2935
+ }
2936
+ return revision;
2937
+ }
2938
+ return null;
2939
+ }
2940
+
2941
+ prepare(input, targetRelease) {
2371
2942
  const intent = normalizeIntent(input);
2372
2943
  this.#assertAudience(intent.mutationRequest.audience, "intent audience");
2373
2944
  const eventId = deterministicEventId("prepare", {
2374
2945
  transactionId: intent.transactionId,
2375
2946
  });
2376
- const snapshot = this.#snapshot();
2377
- const existing = snapshot.byEventId.get(eventId);
2378
- if (existing) {
2947
+ for (let attempt = 0; attempt < MAX_FINALIZE_RETRIES; attempt += 1) {
2948
+ const snapshot = this.#snapshot();
2949
+ const existing = snapshot.byEventId.get(eventId);
2950
+ if (existing) {
2951
+ return this.#prepareProjection(
2952
+ this.#prepareFromSnapshot(snapshot, existing, {
2953
+ authorityReceiptDigest: intent.authorityReceiptDigest,
2954
+ intentDigest: intent.intentDigest,
2955
+ transactionId: intent.transactionId,
2956
+ }),
2957
+ );
2958
+ }
2959
+ const audit = this.#auditFromSnapshot(snapshot, intent.authorityReceipt);
2960
+ this.#assertReleaseNotRevoked(
2961
+ snapshot,
2962
+ {
2963
+ tenantId: intent.mutationRequest.tenantId,
2964
+ skillName: intent.skillName,
2965
+ audience: intent.mutationRequest.audience,
2966
+ releaseDigest: intent.targetReleaseDigest,
2967
+ candidateId: intent.candidateId,
2968
+ },
2969
+ targetRelease,
2970
+ );
2971
+ const subjectRef = this.#putSubject(
2972
+ ARTIFACT_TYPES.prepare,
2973
+ intent,
2974
+ intent.intentDigest,
2975
+ intent.mutationRequest.audience,
2976
+ );
2977
+ const eventInput = {
2978
+ artifactTenantId: this.#artifactTenantId,
2979
+ correlationId: intent.transactionId,
2980
+ decision: "prepared",
2981
+ eventId,
2982
+ reason: intent.intentDigest,
2983
+ skillName: intent.skillName,
2984
+ sourceRefs: [audit.event.subjectRef],
2985
+ subjectRef,
2986
+ tenantId: intent.mutationRequest.tenantId,
2987
+ type: EVENT_TYPES.prepare,
2988
+ };
2989
+ let persistedSnapshot;
2990
+ try {
2991
+ const previous = snapshot.events.at(-1) || null;
2992
+ const verification = this.#verifiedAppend(eventInput, {
2993
+ expectedHeadDigest: previous?.eventDigest ?? null,
2994
+ expectedSequence: previous?.sequence ?? 0,
2995
+ });
2996
+ persistedSnapshot =
2997
+ this.#snapshotWithVerifiedEvent(snapshot, verification) ||
2998
+ this.#snapshot();
2999
+ } catch (cause) {
3000
+ if (isHeadConflict(cause)) continue;
3001
+ if (!isCommitUnknown(cause) && !isEventConflict(cause)) throw cause;
3002
+ persistedSnapshot = this.#snapshot();
3003
+ }
3004
+ const persisted = persistedSnapshot.byEventId.get(eventId);
3005
+ if (!persisted) {
3006
+ throw portsError(
3007
+ EVOLUTION_LEDGER_PORTS_UNAVAILABLE_CODE,
3008
+ "release prepare append did not converge to a queryable event",
3009
+ );
3010
+ }
2379
3011
  return this.#prepareProjection(
2380
- this.#prepareFromSnapshot(snapshot, existing, {
3012
+ this.#prepareFromSnapshot(persistedSnapshot, persisted, {
2381
3013
  authorityReceiptDigest: intent.authorityReceiptDigest,
2382
3014
  intentDigest: intent.intentDigest,
2383
3015
  transactionId: intent.transactionId,
2384
3016
  }),
2385
3017
  );
2386
3018
  }
2387
- const audit = this.#auditFromSnapshot(snapshot, intent.authorityReceipt);
2388
- const subjectRef = this.#putSubject(
2389
- ARTIFACT_TYPES.prepare,
2390
- intent,
2391
- intent.intentDigest,
2392
- intent.mutationRequest.audience,
2393
- );
2394
- const eventInput = {
2395
- artifactTenantId: this.#artifactTenantId,
2396
- correlationId: intent.transactionId,
2397
- decision: "prepared",
2398
- eventId,
2399
- reason: intent.intentDigest,
2400
- skillName: intent.skillName,
2401
- sourceRefs: [audit.event.subjectRef],
2402
- subjectRef,
2403
- tenantId: intent.mutationRequest.tenantId,
2404
- type: EVENT_TYPES.prepare,
2405
- };
2406
- let persistedSnapshot;
2407
- try {
2408
- const verification = this.#verifiedAppend(eventInput);
2409
- persistedSnapshot =
2410
- this.#snapshotWithVerifiedEvent(snapshot, verification) ||
2411
- this.#snapshot();
2412
- } catch (cause) {
2413
- if (!isCommitUnknown(cause) && !isEventConflict(cause)) throw cause;
2414
- persistedSnapshot = this.#snapshot();
2415
- }
2416
- const persisted = persistedSnapshot.byEventId.get(eventId);
2417
- if (!persisted) {
2418
- throw portsError(
2419
- EVOLUTION_LEDGER_PORTS_UNAVAILABLE_CODE,
2420
- "release prepare append did not converge to a queryable event",
2421
- );
2422
- }
2423
- return this.#prepareProjection(
2424
- this.#prepareFromSnapshot(persistedSnapshot, persisted, {
2425
- authorityReceiptDigest: intent.authorityReceiptDigest,
2426
- intentDigest: intent.intentDigest,
2427
- transactionId: intent.transactionId,
2428
- }),
3019
+ throw portsError(
3020
+ EVOLUTION_LEDGER_PORTS_UNAVAILABLE_CODE,
3021
+ "release prepare could not acquire a stable ledger head",
2429
3022
  );
2430
3023
  }
2431
3024
 
@@ -2560,6 +3153,513 @@ class EvolutionLedgerDomainPorts {
2560
3153
  return this.#committedProjection(finalized, lineages);
2561
3154
  }
2562
3155
 
3156
+ resolveReleaseOperation(inputValue) {
3157
+ return this.#resolveRelease(inputValue, false);
3158
+ }
3159
+
3160
+ resolveReleaseOrigin(inputValue) {
3161
+ return this.#resolveRelease(inputValue, true);
3162
+ }
3163
+
3164
+ readReleaseHistory(inputValue) {
3165
+ return this.#resolveRelease(inputValue, false, true);
3166
+ }
3167
+
3168
+ resolveKnowledgeRevocation(inputValue) {
3169
+ if (this.#audience === null)
3170
+ throw new TypeError(
3171
+ "Knowledge revocation proof requires audience-bound ledger ports",
3172
+ );
3173
+ const input = frozenCanonicalClone(inputValue);
3174
+ assertAllExactRecord(
3175
+ input,
3176
+ new Set(["tenantId", "operationDigest", "context"]),
3177
+ "Knowledge revocation query",
3178
+ );
3179
+ const tenantId = identifier(input.tenantId, "tenantId");
3180
+ const operationDigest = digest(input.operationDigest, "operationDigest");
3181
+ const keys = [
3182
+ "epoch",
3183
+ "ledgerId",
3184
+ "identityDigest",
3185
+ "sequence",
3186
+ "headDigest",
3187
+ ];
3188
+ assertAllExactRecord(
3189
+ input.context,
3190
+ new Set(["mode", "checkpoint"]),
3191
+ "Knowledge revocation context",
3192
+ );
3193
+ assertAllExactRecord(
3194
+ input.context.checkpoint,
3195
+ new Set(keys),
3196
+ "Knowledge revocation checkpoint",
3197
+ );
3198
+ const head = this.#ledgerVerify();
3199
+ if (
3200
+ input.context.mode !== "current" ||
3201
+ keys.some((key) => input.context.checkpoint[key] !== head[key])
3202
+ )
3203
+ throw portsError(
3204
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3205
+ "Knowledge revocation requires the current authenticated head",
3206
+ );
3207
+ const snapshot = this.#snapshot();
3208
+ if (
3209
+ snapshot.events.length !== head.sequence ||
3210
+ (snapshot.events.at(-1)?.eventDigest ?? null) !== head.headDigest
3211
+ )
3212
+ throw portsError(
3213
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3214
+ "Knowledge revocation snapshot changed",
3215
+ );
3216
+ let fence = null;
3217
+ for (const entry of this.#knowledgeRevocations(
3218
+ snapshot,
3219
+ tenantId,
3220
+ this.#audience,
3221
+ )) {
3222
+ if (entry.prepared.operationDigest !== operationDigest) continue;
3223
+ fence = {
3224
+ record: entry.prepared,
3225
+ sequence: entry.event.sequence,
3226
+ evidence: {
3227
+ timestamp: entry.event.timestamp,
3228
+ signature: entry.event.signature,
3229
+ eventDigest: entry.event.eventDigest,
3230
+ },
3231
+ };
3232
+ }
3233
+ const fresh = this.#ledgerVerify();
3234
+ if (keys.some((key) => fresh[key] !== head[key]))
3235
+ throw portsError(
3236
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3237
+ "Knowledge revocation changed during verification",
3238
+ );
3239
+ return deepFreeze({
3240
+ authenticated: true,
3241
+ durable: true,
3242
+ tenantId,
3243
+ operationDigest,
3244
+ checkpoint: { ...input.context.checkpoint },
3245
+ fence,
3246
+ });
3247
+ }
3248
+
3249
+ resolveCandidateRevocation(inputValue) {
3250
+ return this.#resolveCandidateDisposition(inputValue, "reject-candidate");
3251
+ }
3252
+
3253
+ resolveCandidateQuarantine(inputValue) {
3254
+ return this.#resolveCandidateDisposition(inputValue, "quarantine");
3255
+ }
3256
+
3257
+ #resolveCandidateDisposition(inputValue, disposition) {
3258
+ if (this.#audience === null)
3259
+ throw new TypeError(
3260
+ "candidate revocation proof requires audience-bound ledger ports",
3261
+ );
3262
+ const input = frozenCanonicalClone(inputValue);
3263
+ assertAllExactRecord(
3264
+ input,
3265
+ new Set([
3266
+ "tenantId",
3267
+ "skillName",
3268
+ "candidateId",
3269
+ "operationDigest",
3270
+ "context",
3271
+ ]),
3272
+ "candidate revocation query",
3273
+ );
3274
+ const tenantId = identifier(input.tenantId, "tenantId");
3275
+ const name = skillName(input.skillName, "skillName");
3276
+ const candidateId = digest(input.candidateId, "candidateId");
3277
+ const operationDigest = digest(input.operationDigest, "operationDigest");
3278
+ const keys = [
3279
+ "epoch",
3280
+ "ledgerId",
3281
+ "identityDigest",
3282
+ "sequence",
3283
+ "headDigest",
3284
+ ];
3285
+ assertAllExactRecord(
3286
+ input.context,
3287
+ new Set(["mode", "checkpoint"]),
3288
+ "candidate revocation context",
3289
+ );
3290
+ assertAllExactRecord(
3291
+ input.context.checkpoint,
3292
+ new Set(keys),
3293
+ "candidate revocation checkpoint",
3294
+ );
3295
+ if (input.context.mode !== "current")
3296
+ throw new TypeError("candidate revocation requires a current context");
3297
+ const head = this.#ledgerVerify();
3298
+ if (keys.some((key) => input.context.checkpoint[key] !== head[key])) {
3299
+ throw portsError(
3300
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3301
+ "candidate revocation checkpoint is stale",
3302
+ );
3303
+ }
3304
+ const snapshot = this.#snapshot();
3305
+ if (
3306
+ snapshot.events.length !== head.sequence ||
3307
+ (snapshot.events.at(-1)?.eventDigest ?? null) !== head.headDigest
3308
+ ) {
3309
+ throw portsError(
3310
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3311
+ "candidate revocation snapshot changed",
3312
+ );
3313
+ }
3314
+ let fence = null;
3315
+ // This is the exact same authenticated parser as mandatory prepare, not a
3316
+ // separate provider's assertion that admission has supposedly been denied.
3317
+ for (const entry of this.#knowledgeRevocations(
3318
+ snapshot,
3319
+ tenantId,
3320
+ this.#audience,
3321
+ )) {
3322
+ if (entry.prepared.operationDigest !== operationDigest) continue;
3323
+ const dependency = entry.prepared.knowledge.dependencies.find(
3324
+ (item) =>
3325
+ item.kind === "candidate" &&
3326
+ item.digest === candidateId &&
3327
+ item.disposition === disposition,
3328
+ );
3329
+ if (dependency) fence = entry;
3330
+ }
3331
+ const cache = new Map();
3332
+ const lineages = this.#lineages(snapshot, cache);
3333
+ const history = [];
3334
+ const pendingTransactions = [];
3335
+ for (const event of snapshot.events) {
3336
+ if (event.type !== EVENT_TYPES.prepare || event.tenantId !== tenantId)
3337
+ continue;
3338
+ const entry =
3339
+ cache.get(event.eventId) ?? this.#prepareFromSnapshot(snapshot, event);
3340
+ const intent = entry.intent;
3341
+ if (intent.candidateId === candidateId && intent.skillName !== name) {
3342
+ throw portsError(
3343
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3344
+ "candidate history belongs to another Skill",
3345
+ );
3346
+ }
3347
+ if (intent.skillName !== name) continue;
3348
+ const finalized = lineages.byTransaction.get(intent.transactionId);
3349
+ if (!finalized) pendingTransactions.push(intent.transactionId);
3350
+ if (intent.candidateId !== candidateId) continue;
3351
+ history.push({
3352
+ transactionId: intent.transactionId,
3353
+ releaseDigest: intent.targetReleaseDigest,
3354
+ preparationSequence: event.sequence,
3355
+ committed: Boolean(finalized),
3356
+ });
3357
+ }
3358
+ const groupKey = `${tenantId}\0${name}`;
3359
+ const latest = lineages.groups.get(groupKey)?.at(-1);
3360
+ const migrated = lineages.migrations.get(groupKey);
3361
+ const current = latest
3362
+ ? {
3363
+ releaseDigest: latest.prepared.intent.targetReleaseDigest,
3364
+ revision: latest.finalization.revision,
3365
+ stateDigest: latest.finalization.stateDigest,
3366
+ projection: this.#committedProjection(latest, lineages),
3367
+ }
3368
+ : migrated
3369
+ ? {
3370
+ releaseDigest: migrated.migration.state.activeReleaseDigest,
3371
+ revision: migrated.migration.state.revision,
3372
+ stateDigest: migrated.migration.state.stateDigest,
3373
+ projection: this.#migrationProjection(migrated, true),
3374
+ }
3375
+ : null;
3376
+ const fresh = this.#ledgerVerify();
3377
+ if (keys.some((key) => fresh[key] !== head[key])) {
3378
+ throw portsError(
3379
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3380
+ "candidate revocation ledger changed during verification",
3381
+ );
3382
+ }
3383
+ return deepFreeze({
3384
+ authenticated: true,
3385
+ durable: true,
3386
+ tenantId,
3387
+ skillName: name,
3388
+ candidateId,
3389
+ operationDigest,
3390
+ checkpoint: { ...input.context.checkpoint },
3391
+ fence: fence
3392
+ ? {
3393
+ record: fence.prepared,
3394
+ sequence: fence.event.sequence,
3395
+ evidence: {
3396
+ timestamp: fence.event.timestamp,
3397
+ signature: fence.event.signature,
3398
+ eventDigest: fence.event.eventDigest,
3399
+ },
3400
+ }
3401
+ : null,
3402
+ pendingTransactions,
3403
+ history,
3404
+ current,
3405
+ });
3406
+ }
3407
+
3408
+ #resolveRelease(inputValue, origin, history = false) {
3409
+ const input = frozenCanonicalClone(inputValue);
3410
+ assertAllExactRecord(
3411
+ input,
3412
+ new Set([
3413
+ "tenantId",
3414
+ "skillName",
3415
+ ...(history ? [] : [origin ? "releaseDigest" : "operationId"]),
3416
+ "context",
3417
+ ]),
3418
+ "release operation query",
3419
+ );
3420
+ const tenantId = identifier(input.tenantId, "tenantId");
3421
+ const name = skillName(input.skillName, "skillName");
3422
+ const operationId =
3423
+ origin || history ? null : identifier(input.operationId, "operationId");
3424
+ const releaseDigest = origin
3425
+ ? digest(
3426
+ input.releaseDigest,
3427
+ "releaseDigest",
3428
+ EVOLUTION_LEDGER_PORTS_INVALID_CODE,
3429
+ )
3430
+ : null;
3431
+ const context = input.context;
3432
+ assertAllExactRecord(
3433
+ context,
3434
+ new Set(["mode", "checkpoint"]),
3435
+ "release operation context",
3436
+ );
3437
+ const keys = [
3438
+ "epoch",
3439
+ "ledgerId",
3440
+ "identityDigest",
3441
+ "sequence",
3442
+ "headDigest",
3443
+ ];
3444
+ assertAllExactRecord(
3445
+ context.checkpoint,
3446
+ new Set(keys),
3447
+ "release operation checkpoint",
3448
+ );
3449
+ if (!["current", "checkpoint"].includes(context.mode))
3450
+ throw new TypeError("invalid release operation mode");
3451
+ const snapshot = this.#snapshot();
3452
+ const tail = snapshot.events.at(-1);
3453
+ const head = tail
3454
+ ? { ...tail, headDigest: tail.eventDigest }
3455
+ : this.#ledgerVerify();
3456
+ if (
3457
+ snapshot.events.length !== head.sequence ||
3458
+ snapshot.events.some((event) =>
3459
+ ["epoch", "ledgerId", "identityDigest"].some(
3460
+ (key) => event[key] !== head[key],
3461
+ ),
3462
+ )
3463
+ )
3464
+ throw portsError(
3465
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3466
+ "release operation snapshot is not the full current ledger",
3467
+ );
3468
+ const checkpoint = context.checkpoint;
3469
+ const historical =
3470
+ checkpoint.sequence === 0
3471
+ ? null
3472
+ : snapshot.bySequence.get(checkpoint.sequence);
3473
+ if (
3474
+ !Number.isSafeInteger(checkpoint.sequence) ||
3475
+ checkpoint.sequence < 0 ||
3476
+ checkpoint.sequence > head.sequence ||
3477
+ ["epoch", "ledgerId", "identityDigest"].some(
3478
+ (key) => checkpoint[key] !== head[key],
3479
+ ) ||
3480
+ checkpoint.headDigest !== (historical?.eventDigest ?? null) ||
3481
+ (context.mode === "current" &&
3482
+ keys.some((key) => checkpoint[key] !== head[key]))
3483
+ ) {
3484
+ throw portsError(
3485
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3486
+ "release operation checkpoint differs from the authenticated ledger",
3487
+ );
3488
+ }
3489
+ // Authenticate the whole present lineage even for a historical query, then
3490
+ // derive the exact as-of prefix. A later finalize cannot prove an earlier ack.
3491
+ const prepareCache = new Map();
3492
+ const presentLineages = this.#lineages(snapshot, prepareCache);
3493
+ const prefix = this.#indexSnapshot(
3494
+ snapshot.events.slice(0, checkpoint.sequence),
3495
+ snapshot.subjects,
3496
+ );
3497
+ // Reuse only work authenticated in THIS read, and only when all release
3498
+ // events and their consumed authority precede the requested checkpoint.
3499
+ // Unrelated later Wiki/journal events do not change the release lineage.
3500
+ // A later prepare/finalize/migration still forces exact prefix replay.
3501
+ const unchangedReleaseHistory =
3502
+ !snapshot.events
3503
+ .slice(checkpoint.sequence)
3504
+ .some((event) =>
3505
+ [
3506
+ EVENT_TYPES.prepare,
3507
+ EVENT_TYPES.finalize,
3508
+ EVENT_TYPES.migration,
3509
+ ].includes(event.type),
3510
+ ) &&
3511
+ [...prepareCache.values()].every((entry) =>
3512
+ prefix.byEventId.has(entry.consumeAudit.event.eventId),
3513
+ );
3514
+ const lineages = unchangedReleaseHistory
3515
+ ? presentLineages
3516
+ : this.#lineages(prefix);
3517
+ const prepared = [];
3518
+ for (const event of prefix.events) {
3519
+ if (event.type !== EVENT_TYPES.prepare) continue;
3520
+ const cached = prepareCache.get(event.eventId);
3521
+ const entry =
3522
+ cached && prefix.byEventId.has(cached.consumeAudit.event.eventId)
3523
+ ? cached
3524
+ : this.#prepareFromSnapshot(prefix, event);
3525
+ if (
3526
+ entry.intent.mutationRequest.tenantId === tenantId &&
3527
+ entry.intent.skillName === name &&
3528
+ (history ||
3529
+ (origin
3530
+ ? entry.intent.operation === "promote" &&
3531
+ entry.intent.targetReleaseDigest === releaseDigest
3532
+ : entry.intent.operationId === operationId))
3533
+ )
3534
+ prepared.push(entry);
3535
+ }
3536
+ if (!history && prepared.length > 1)
3537
+ throw portsError(
3538
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3539
+ "release operation has multiple transaction intents",
3540
+ );
3541
+ if (history && prepared.length > 10_000)
3542
+ throw portsError(
3543
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3544
+ "release history exceeds its bounded budget",
3545
+ );
3546
+ if (
3547
+ history &&
3548
+ new Set(prepared.map((entry) => entry.intent.operationId)).size !==
3549
+ prepared.length
3550
+ )
3551
+ throw portsError(
3552
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3553
+ "release operation has multiple transaction intents",
3554
+ );
3555
+ const groupKey = `${tenantId}\0${name}`;
3556
+ const baseline = lineages.migrations.get(groupKey)?.migration.state;
3557
+ let previous = baseline
3558
+ ? {
3559
+ revision: baseline.revision,
3560
+ stateDigest: baseline.stateDigest,
3561
+ activeReleaseDigest: baseline.activeReleaseDigest,
3562
+ lastKnownGoodReleaseDigest: baseline.lastKnownGoodReleaseDigest,
3563
+ }
3564
+ : {
3565
+ revision: 0,
3566
+ stateDigest: null,
3567
+ activeReleaseDigest: null,
3568
+ lastKnownGoodReleaseDigest: null,
3569
+ };
3570
+ const predecessors = new Map([[previous.revision, previous]]);
3571
+ for (const prior of lineages.groups.get(groupKey) ?? []) {
3572
+ const intent = prior.prepared.intent;
3573
+ if (
3574
+ intent.operation === "rollback" &&
3575
+ intent.targetReleaseDigest !== previous.lastKnownGoodReleaseDigest
3576
+ )
3577
+ throw portsError(
3578
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3579
+ "historical rollback does not target the last-known-good release",
3580
+ );
3581
+ previous = {
3582
+ revision: prior.finalization.revision,
3583
+ stateDigest: prior.finalization.stateDigest,
3584
+ activeReleaseDigest: intent.targetReleaseDigest,
3585
+ lastKnownGoodReleaseDigest:
3586
+ intent.operation === "promote"
3587
+ ? (previous.activeReleaseDigest ?? intent.targetReleaseDigest)
3588
+ : intent.targetReleaseDigest,
3589
+ };
3590
+ predecessors.set(previous.revision, previous);
3591
+ }
3592
+ const results = prepared.map((entry) => {
3593
+ const previous = predecessors.get(entry.intent.expectedRevision);
3594
+ if (
3595
+ !previous ||
3596
+ previous.revision !== entry.intent.expectedRevision ||
3597
+ previous.stateDigest !== entry.intent.previousStateDigest
3598
+ )
3599
+ throw portsError(
3600
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3601
+ "release operation has no exact predecessor",
3602
+ );
3603
+ const finalized = lineages.byTransaction.get(entry.intent.transactionId);
3604
+ return {
3605
+ intent: entry.intent,
3606
+ previous,
3607
+ preparationCheckpoint: {
3608
+ epoch: entry.event.epoch,
3609
+ ledgerId: entry.event.ledgerId,
3610
+ identityDigest: entry.event.identityDigest,
3611
+ sequence: entry.event.sequence,
3612
+ headDigest: entry.event.eventDigest,
3613
+ },
3614
+ projection: finalized
3615
+ ? this.#committedProjection(finalized, lineages)
3616
+ : this.#prepareProjection(entry),
3617
+ finalizationEvidence: finalized
3618
+ ? {
3619
+ timestamp: finalized.event.timestamp,
3620
+ signature: finalized.event.signature,
3621
+ eventDigest: finalized.event.eventDigest,
3622
+ }
3623
+ : null,
3624
+ };
3625
+ });
3626
+ const result = results[0] ?? null;
3627
+ const fresh = this.#ledgerVerify();
3628
+ if (keys.some((key) => fresh[key] !== head[key]))
3629
+ throw portsError(
3630
+ EVOLUTION_LEDGER_PORTS_CORRUPT_CODE,
3631
+ "release operation ledger changed during verification",
3632
+ );
3633
+ if (history) {
3634
+ const migration = lineages.migrations.get(`${tenantId}\0${name}`);
3635
+ return deepFreeze({
3636
+ authenticated: true,
3637
+ durable: true,
3638
+ tenantId,
3639
+ skillName: name,
3640
+ checkpoint: { ...checkpoint },
3641
+ migration: migration
3642
+ ? {
3643
+ value: migration.migration,
3644
+ artifactRef: migration.event.subjectRef,
3645
+ sequence: migration.event.sequence,
3646
+ eventDigest: migration.event.eventDigest,
3647
+ }
3648
+ : null,
3649
+ operations: results,
3650
+ });
3651
+ }
3652
+ return deepFreeze({
3653
+ authenticated: true,
3654
+ durable: true,
3655
+ tenantId,
3656
+ skillName: name,
3657
+ operationId: origin ? (result?.intent.operationId ?? null) : operationId,
3658
+ checkpoint: { ...checkpoint },
3659
+ result,
3660
+ });
3661
+ }
3662
+
2563
3663
  appendAudit(input) {
2564
3664
  const value = frozenCanonicalClone(input);
2565
3665
  const audit = verifySkillMutationAuditEvent(value);
@@ -3009,16 +4109,69 @@ export function createEvolutionLedgerPorts(options = {}) {
3009
4109
  )
3010
4110
  : "evolution-ledger",
3011
4111
  });
3012
- const prepare = Object.freeze((input) => adapter.prepare(input));
4112
+ const prepare = Object.freeze((input, targetRelease) =>
4113
+ adapter.prepare(input, targetRelease),
4114
+ );
3013
4115
  const finalize = Object.freeze((input) => adapter.finalize(input));
3014
- const migrate = Object.freeze((input) => adapter.migrate(input));
4116
+ const migrate = Object.freeze((input, releases) =>
4117
+ adapter.migrate(input, releases),
4118
+ );
3015
4119
  const query = Object.freeze((transactionId) => adapter.query(transactionId));
3016
4120
  const append = Object.freeze((event) => adapter.appendAudit(event));
3017
4121
  const claim = Object.freeze((nonce) => adapter.claimNonce(nonce));
4122
+ const transactionLedger = Object.freeze({
4123
+ finalize,
4124
+ migrate,
4125
+ prepare,
4126
+ query,
4127
+ });
4128
+ const readCurrentHead = ledger.verify.bind(ledger);
4129
+ RELEASE_OPERATION_READERS.set(
4130
+ transactionLedger,
4131
+ Object.freeze({
4132
+ currentContext: Object.freeze(() => {
4133
+ const head = readCurrentHead();
4134
+ return deepFreeze({
4135
+ mode: "current",
4136
+ checkpoint: Object.fromEntries(
4137
+ [
4138
+ "epoch",
4139
+ "ledgerId",
4140
+ "identityDigest",
4141
+ "sequence",
4142
+ "headDigest",
4143
+ ].map((key) => [key, head[key]]),
4144
+ ),
4145
+ });
4146
+ }),
4147
+ matchesWikiAdapter: Object.freeze((wikiAdapter) =>
4148
+ captureWikiRevisionReader(wikiAdapter).matchesLedger(ledger),
4149
+ ),
4150
+ matchesLedger: Object.freeze((value) => value === ledger),
4151
+ resolveOperation: Object.freeze((input) =>
4152
+ adapter.resolveReleaseOperation(input),
4153
+ ),
4154
+ resolveReleaseOrigin: Object.freeze((input) =>
4155
+ adapter.resolveReleaseOrigin(input),
4156
+ ),
4157
+ readReleaseHistory: Object.freeze((input) =>
4158
+ adapter.readReleaseHistory(input),
4159
+ ),
4160
+ resolveCandidateRevocation: Object.freeze((input) =>
4161
+ adapter.resolveCandidateRevocation(input),
4162
+ ),
4163
+ resolveCandidateQuarantine: Object.freeze((input) =>
4164
+ adapter.resolveCandidateQuarantine(input),
4165
+ ),
4166
+ resolveKnowledgeRevocation: Object.freeze((input) =>
4167
+ adapter.resolveKnowledgeRevocation(input),
4168
+ ),
4169
+ }),
4170
+ );
3018
4171
  return Object.freeze({
3019
4172
  auditSink: Object.freeze({ append }),
3020
4173
  nonceStore: Object.freeze({ claim }),
3021
- transactionLedger: Object.freeze({ finalize, migrate, prepare, query }),
4174
+ transactionLedger,
3022
4175
  });
3023
4176
  }
3024
4177