chainlesschain 0.166.21 → 0.166.24

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 (301) hide show
  1. package/README.md +67 -9
  2. package/package.json +4 -3
  3. package/src/assets/web-panel/assets/{AIOps-BjMnsUci.js → AIOps-DR-MWcZc.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DdYFP03A.js → ActionButton-DT8B7sEb.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Bb8TuuK_.js → Analytics-asjh3dQJ.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-Kn3TIOtk.js → AppLayout-DivQ491i.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-4IxpqI_b.js → Artifacts-DPH2uUmy.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BOV2caqU.js → Audit-Bp2nLyc-.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-B86k-ay4.js → BackgroundAgents-CHS28khl.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-C5_ie1e3.js → Backup-CKeaFSfz.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-xpwg6QCW.js → BaseInput-CxwM9BAH.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CVZOcZau.js → Chat-DYLDwaCv.js} +4 -4
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-D8fPYhUu.js → ChatBubbleRenderer-DdBJDBP0.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-MKTq3zdP.js → Checkbox-uYTWOB8j.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-JUk3wzep.js → Codegen-CvYa_dwT.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-JPvTA0kC.js → Col-CanMAX4m.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-Tqgl87NQ.js → Community-B4WaDtHw.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BuAFYBmN.js → Compact-K93Uof_3.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-CXS9WIPZ.js → Compliance-CKeDLgUW.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-Ds2bFHrr.js → Cowork-P93grAeB.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-C_dV_OeW.js → Cron-BSHnMtDn.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-BsO6tIRo.js → Crosschain-epAOpUVJ.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-rNOFqBac.js → DID-ByjXfP7t.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-C2fcKKVY.js → Dashboard-QztTU8tb.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-Y7Ndr0X_.js → Dropdown-DhUc9yhN.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-DcP_uPmL.js → EmailListRenderer-C2sLhJJN.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Cwn3gDzk.js → FamilyGuardDashboard-CdfbWNDn.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-ClQuOsqb.js → Federation-CcF_R7NW.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-DfwtmlcK.js → FormItemContext-Cm_X2IBk.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-zNZhtbC5.js → GenericCardRenderer-DUi4NWlb.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-BZmdW-G5.js → Git-4Sq5FjBt.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CqBk4lEn.js → Governance-Dx2_v4V6.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-Dbmt3ZXk.js → Inference-7Vr1xekR.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-hMTH6qf3.js → KnowledgeGraph-Cnd2XOzf.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-CkiYgiW2.js → Logs-B66QPVf-.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-BL1FElXg.js → MarkdownRenderer-PLsEvhly.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-CbB6wfin.js → Marketplace-BMIK9BmC.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-BSwiFtte.js → McpTools-BDbyp3J_.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-B03PeHrz.js → Memory-CJdzfZGi.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CRGrnd-X.js → MobileBridge-C2TH5Y3-.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-CE_5v2kO.js → MobileProjects-D1dYXkvV.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-Dp11QVx1.js → Mtc-B-4A1I1j.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-CYu-3JBu.js → MtcAudit-Bgcc9UOl.js} +5 -5
  44. package/src/assets/web-panel/assets/{Multisig-CGyJ0Xl3.js → Multisig-DqOe-etP.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-CoWi_ov1.js → NLProgramming-7VnhzE_6.js} +1 -1
  46. package/src/assets/web-panel/assets/Notes-BxawpeUQ.js +7 -0
  47. package/src/assets/web-panel/assets/{NotificationSettings-DX4I2b4W.js → NotificationSettings-Cr08G2aE.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-Ce8bEGlK.js +1 -0
  49. package/src/assets/web-panel/assets/{Organization-oopLO_tk.js → Organization-BC7lveGv.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-BFVvjMyf.js → Overflow-CakOW-G0.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CBy5t-Tk.js → P2P-Cf8CaOBZ.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser--YWJNsu6.js → PdhVaultBrowser-Dc7b98W9.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-C2dZ8scb.js → Permissions-DGJyMEfS.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-Bs3l7Hlx.js → PersonalDataHub-DNIwSdwu.js} +6 -6
  55. package/src/assets/web-panel/assets/{Pipeline-DEBWbZuD.js → Pipeline-5B1S12wa.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-CjHBb6NU.js → Privacy-CMB6Ke5t.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-D2WipUz5.js → ProjectInit-D5PqTFiT.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-B6WfnrGB.js → ProjectSettings-CbKNdSjV.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-ccXaHzYL.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CCv5M_Dv.js → Providers-CJF5_-Gs.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CGthxU54.js → QrScannerModal-CT6iEAdi.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-CnPmXPFb.js → QuickAsk-Ci0h9mJ_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-Df_tGEa9.js → Recommend-Da5mobZu.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-Z58N0Loe.js → RemoteSession-BaCY8eey.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-CZTBQ2Vt.js → Reputation-CaITfTsI.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-CdK3YpCQ.js → Row-DtUDamyP.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CFMVT5sb.js → RssFeed-DX27gFpg.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DrF8RIvD.js → Search-DFL69osN.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Ddk2f2DM.js → Security-BqGeoWv-.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-CCuK-VOo.js → Services-3z1WnEAc.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-DxCpHzeM.js → Skeleton-C_OJQQ9Z.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-t2oTDgcv.js → Skills-BY7aT6Mo.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-Df63M9_R.js → Sla-BZv7DSaD.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-6lJKLhCn.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-COd_tgPp.js → SyncSettings-B6D7STlI.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-CzDCcrik.js → Tasks-Co_FCZAO.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-D-vfxTGA.js → Templates-CnY-9fgz.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-BlpT_Gxc.js → Tenant-B71yXfZ8.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-D5rq52Hg.js → Terminal-Dd_P7awo.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-DdoMndkK.js → TimelineRenderer-CvIEMyli.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BhgBsI6g.js → Tokens-DknFBGOi.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DwwzoikZ.js → Trigger-D_4nJONB.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-HkTpzXFb.js → Trust-BNl21fa7.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-D9nk6Ehe.js → UkeySign-CFrCI7uK.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BKk0rfoy.js → VideoEditing-BVfY6JLg.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-IVWIU_Lq.js → Wallet-Cj9CAK0J.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-CFTCpfsG.js → WebAuthn-DcqZlzA3.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-Dnf4Obif.js → WorkflowEditor-Dfr_dMld.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-D2snERdj.js → chat-Yv6UF0AD.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-DKEjK1N1.js → colors-CDW_-1fs.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BEDLwQdt.js → compact-item-BYOQvd-6.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-DA9iW1a0.js → createContext-BCGO0BiP.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-H-kXSuf-.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-5l2xEcY9.js → hasIn-DY-70cfQ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-B7_W_rYd.js → index-366wfQBU.js} +1 -1
  96. package/src/assets/web-panel/assets/index-B0o4MeNK.js +1 -0
  97. package/src/assets/web-panel/assets/{index-CxEtQYdi.js → index-B9ZogJJM.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B00GeekA.js → index-B9m5QAMg.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-C7sKbM5s.js → index-BBs2mv5M.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CX1x4AFn.js → index-BFv1hzF6.js} +1 -1
  101. package/src/assets/web-panel/assets/index-BVafOL_I.js +1 -0
  102. package/src/assets/web-panel/assets/{index-DU2TXJu-.js → index-BXlEx4UH.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-e-e40id6.js → index-BayRTE5w.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DXet1xol.js → index-Bb9nyts1.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-D7z4zB_a.js → index-Bf_Va0S-.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-fccZmC_h.js → index-Br3wQLVY.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Bqc8tdIF.js → index-BvK4fjkk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BO9dQjpt.js → index-C40UdtlS.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Csfb-7hw.js → index-C4UJA2ju.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Td8ZwyoC.js → index-CB_Iw73G.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BZ5lY2zx.js → index-CCwWp3mT.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DpqtbXdE.js → index-CFa2fPCk.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-NJieh3T1.js → index-CIyHxV4u.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Dbkghqn_.js → index-CUP-A2_h.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DqwPFbOb.js → index-CUo27q9J.js} +3 -3
  116. package/src/assets/web-panel/assets/{index-B4QYBliR.js → index-CaT8trvf.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BgfImyZI.js → index-CnZNbcux.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dbd7eEex.js → index-Cy2NE6AO.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CbTPvp2_.js → index-CzeEEazr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-5pW4t1iD.js → index-D--TEyDj.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Dg2a9owQ.js → index-DCtsjhhT.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B_eCoZgW.js → index-DLOf7BSz.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-7P1b8HZo.js → index-DM5c4pc-.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CRPrHE7h.js → index-DRFC2Qt0.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Bq5P3piS.js → index-DT_qVaaV.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CjWltbi_.js → index-DUDoRk9r.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CkMKuqUs.js → index-Dg-AQYDf.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DLoalqRX.js → index-DuIPq5MX.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CGlotREA.js → index-NYVBUAVN.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-yYEQXYaU.js → index-NaCESahy.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CmruhzFi.js → index-RjIMPG0u.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-fgYk0QXO.js → index-Y9akzgFO.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DvV03Ayk.js → index-hZ0Eyrrw.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CPrcB1TC.js → initDefaultProps-CG99CcR4.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BQ7mWRh_.js → motion-Z7MH0_0G.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-CzOEq99p.js → move-BX67lOdq.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-BlQI5jrw.js → mtc-parser-CmAbG1fE.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-DlW4gxmv.js → omit-DiU5tI1_.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-BBYms5nP.js → pickAttrs-BGfvLrYL.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-az2MPJ_7.js → placementArrow-CggLEgaJ.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-D1-ibEol.js → responsiveObserve-t3nlghPZ.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DHGqa4GA.js → slide-BkV4dL9s.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-CYGDo6lD.js → statusUtils-qec1PUoC.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-Cl2EM9K6.js → styleChecker-ChjX6T8D.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DdYhzuv1.js → useFlexGapSupport-B1jLoZcM.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DWumPuBW.js → useFs-C3X53s4E.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-DxAO-Aqi.js → usePersonalDataHub-DOvbbnkZ.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-CplsQf_N.js → vnode-Ie0TEVFT.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Cw5HXNSG.js → zoom-CRUMVS8l.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.js +2 -0
  155. package/src/commands/governed-skill-marketplace.js +142 -0
  156. package/src/commands/marketplace.js +4 -1
  157. package/src/commands/serve.js +41 -0
  158. package/src/commands/skill.js +3 -0
  159. package/src/data/changelog.json +39 -0
  160. package/src/gateways/ws/ws-agent-handler.js +59 -2
  161. package/src/gateways/ws/ws-server.js +2 -0
  162. package/src/harness/golden-transcript.js +1 -0
  163. package/src/harness/prompt-compressor.js +51 -5
  164. package/src/harness/provider-backed-compaction.js +28 -1
  165. package/src/harness/remote-session-registry.js +15 -3
  166. package/src/index.js +30 -4
  167. package/src/lazy-dispatch.js +15 -1
  168. package/src/lib/advisor-runtime.js +55 -2
  169. package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
  170. package/src/lib/app-server/graph-runtime.js +32 -0
  171. package/src/lib/app-server/server.js +45 -1
  172. package/src/lib/app-server/websocket-transport.js +23 -0
  173. package/src/lib/autonomous-agent.js +63 -13
  174. package/src/lib/cowork/ab-comparator-cli.js +4 -3
  175. package/src/lib/cowork/debate-review-cli.js +4 -3
  176. package/src/lib/cowork/decision-kb-cli.js +5 -0
  177. package/src/lib/cowork-adapter.js +38 -16
  178. package/src/lib/evolution/agent-evolution-ingress.js +95 -15
  179. package/src/lib/evolution/agent-evolution-runtime-composition.js +82 -0
  180. package/src/lib/evolution/agent-evolution-session-lifecycle.js +46 -0
  181. package/src/lib/evolution/agent-model-projection.js +217 -0
  182. package/src/lib/evolution/bounded-descriptor-read.js +29 -0
  183. package/src/lib/evolution/controlled-skill-pilot-ledger-adapter.js +551 -0
  184. package/src/lib/evolution/controlled-skill-production-pilot.js +308 -18
  185. package/src/lib/evolution/evidence-backed-wiki-maintainer.js +10 -1
  186. package/src/lib/evolution/evidence-json-text.js +236 -0
  187. package/src/lib/evolution/evolution-artifact-ports.js +202 -21
  188. package/src/lib/evolution/evolution-deployment-loader.js +369 -0
  189. package/src/lib/evolution/evolution-eval-child-evidence-ledger-adapter.js +373 -0
  190. package/src/lib/evolution/evolution-eval-gate.js +14 -1
  191. package/src/lib/evolution/evolution-eval-process-supervisor-worker.mjs +14 -0
  192. package/src/lib/evolution/evolution-eval-process-supervisor.js +607 -0
  193. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +14 -1
  194. package/src/lib/evolution/evolution-evidence-projector.js +240 -37
  195. package/src/lib/evolution/evolution-file-witness.js +153 -30
  196. package/src/lib/evolution/evolution-ledger-ports.js +1027 -66
  197. package/src/lib/evolution/evolution-ledger.js +66 -2
  198. package/src/lib/evolution/evolution-raw-crypto-shred.js +29 -15
  199. package/src/lib/evolution/evolution-raw-deletion-ledger-adapter.js +865 -0
  200. package/src/lib/evolution/evolution-release-train-domain-stages.js +769 -0
  201. package/src/lib/evolution/evolution-release-train-ledger-adapter.js +335 -0
  202. package/src/lib/evolution/evolution-release-train-stage-output-ledger-adapter.js +333 -0
  203. package/src/lib/evolution/evolution-release-train.js +586 -0
  204. package/src/lib/evolution/evolution-workbench-batch-executor.js +101 -144
  205. package/src/lib/evolution/evolution-workbench-control-ports.js +203 -0
  206. package/src/lib/evolution/evolution-workbench-file-resources.js +403 -0
  207. package/src/lib/evolution/evolution-workbench-projection.js +152 -25
  208. package/src/lib/evolution/evolution-workbench-registry-source.js +482 -0
  209. package/src/lib/evolution/evolution-workbench-review-ledger-adapter.js +823 -0
  210. package/src/lib/evolution/evolution-workbench-review-protocol.js +157 -0
  211. package/src/lib/evolution/evolution-workbench-rollback-authorization.js +57 -0
  212. package/src/lib/evolution/evolution-workbench-rollback-ledger-adapter.js +1016 -0
  213. package/src/lib/evolution/evolution-workbench-runtime.js +133 -0
  214. package/src/lib/evolution/evolution-workbench-version-control.js +70 -36
  215. package/src/lib/evolution/evolvable-artifact-ledger-adapter.js +736 -0
  216. package/src/lib/evolution/governed-knowledge-artifact-lifecycle.js +364 -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-ledger-executor.js +95 -83
  220. package/src/lib/evolution/governed-knowledge-merge-ledger-executor.js +29 -2
  221. package/src/lib/evolution/governed-knowledge-merge-publisher-authority.js +31 -3
  222. package/src/lib/evolution/governed-knowledge-record.js +148 -0
  223. package/src/lib/evolution/governed-knowledge-revocation-record.js +135 -0
  224. package/src/lib/evolution/governed-knowledge-skill-rollback.js +475 -0
  225. package/src/lib/evolution/governed-knowledge-sync-ledger-adapter.js +92 -6
  226. package/src/lib/evolution/governed-knowledge-sync-merge-publisher.js +57 -4
  227. package/src/lib/evolution/governed-knowledge-sync.js +332 -99
  228. package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +462 -0
  229. package/src/lib/evolution/governed-skill-marketplace-badge.js +208 -0
  230. package/src/lib/evolution/governed-skill-marketplace-candidate.js +330 -0
  231. package/src/lib/evolution/governed-skill-marketplace-cli-host.js +308 -0
  232. package/src/lib/evolution/governed-skill-marketplace-ledger-adapter.js +420 -0
  233. package/src/lib/evolution/governed-skill-marketplace.js +288 -5
  234. package/src/lib/evolution/governed-wiki-pruning-journal.js +302 -0
  235. package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +459 -0
  236. package/src/lib/evolution/governed-wiki-pruning-maintenance.js +576 -0
  237. package/src/lib/evolution/governed-wiki-pruning-plan-authority.js +169 -0
  238. package/src/lib/evolution/governed-wiki-pruning-raw-shred.js +207 -0
  239. package/src/lib/evolution/governed-wiki-pruning-retrieval.js +587 -0
  240. package/src/lib/evolution/governed-wiki-pruning-runtime.js +153 -0
  241. package/src/lib/evolution/governed-wiki-pruning-skill-rollback.js +360 -0
  242. package/src/lib/evolution/governed-wiki-pruning.js +322 -143
  243. package/src/lib/evolution/independent-skill-revocation-source.js +231 -0
  244. package/src/lib/evolution/knowledge-wiki-source-admission.js +124 -0
  245. package/src/lib/evolution/knowledge-wiki-source-provenance.js +359 -0
  246. package/src/lib/evolution/progressive-canary-external-watchdog.js +578 -0
  247. package/src/lib/evolution/progressive-canary-traffic-worker.js +628 -0
  248. package/src/lib/evolution/progressive-canary-watchdog-file-store.js +285 -0
  249. package/src/lib/evolution/progressive-canary-watchdog-node-pki.js +265 -0
  250. package/src/lib/evolution/skill-candidate-registry.js +22 -0
  251. package/src/lib/evolution/skill-promotion-controller.js +25 -0
  252. package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +100 -0
  253. package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +131 -2
  254. package/src/lib/evolution/skill-release-registry.js +25 -4
  255. package/src/lib/evolution/skill-retrieval-revocation-authority.js +361 -0
  256. package/src/lib/evolution/skill-retrieval-revocation-ledger-adapter.js +346 -0
  257. package/src/lib/evolution/skill-revocation-propagation.js +467 -0
  258. package/src/lib/evolution/skill-target-matrix-eval.js +162 -11
  259. package/src/lib/evolution/skill-wiki-reconciliation.js +985 -0
  260. package/src/lib/evolution/skill-writer-inventory-manifest.js +15 -12
  261. package/src/lib/evolution/statistical-progressive-canary.js +845 -0
  262. package/src/lib/evolution/structured-memory-agent-control-plane.js +120 -0
  263. package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +5 -1
  264. package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +126 -0
  265. package/src/lib/evolution/wiki-informed-skill-proposer.js +127 -21
  266. package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +760 -100
  267. package/src/lib/evolution/wiki-revision-protocol.js +120 -0
  268. package/src/lib/evolution/wiki-skill-proposal-ledger-adapter.js +307 -0
  269. package/src/lib/evolution/wiki-target-tombstone-revision.js +101 -0
  270. package/src/lib/evolution/wikiskill-benchmark-cli-host.js +178 -0
  271. package/src/lib/evolution/wikiskill-benchmark-execution-host.js +702 -0
  272. package/src/lib/evolution/wikiskill-benchmark-ledger-adapter.js +613 -0
  273. package/src/lib/evolution/wikiskill-benchmark.js +574 -0
  274. package/src/lib/goal-assess.js +17 -10
  275. package/src/lib/interactive-planner.js +9 -1
  276. package/src/lib/iteration-budget.js +16 -2
  277. package/src/lib/micro-compact.js +4 -1
  278. package/src/lib/model-failure-policy.js +21 -0
  279. package/src/lib/process-execution-broker/index.js +1 -0
  280. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  281. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  282. package/src/lib/process-execution-broker/windows-sandbox.cs +33 -15
  283. package/src/lib/read-file-page.js +191 -0
  284. package/src/lib/runnable-provider.js +2 -1
  285. package/src/lib/session-host-lease.js +11 -16
  286. package/src/lib/skill-retrieval-router.js +22 -1
  287. package/src/repl/agent-repl.js +127 -33
  288. package/src/runtime/agent-core.js +224 -80
  289. package/src/runtime/agent-runtime.js +43 -0
  290. package/src/runtime/coding-agent-contract-shared.cjs +7 -1
  291. package/src/runtime/fallback-model.js +143 -62
  292. package/src/runtime/headless-runner.js +54 -10
  293. package/src/runtime/headless-stream.js +53 -6
  294. package/src/runtime/runtime-factory.js +41 -2
  295. package/src/assets/web-panel/assets/Notes-CgU9DDo9.js +0 -7
  296. package/src/assets/web-panel/assets/OrderTableRenderer-CwHc15Zs.js +0 -1
  297. package/src/assets/web-panel/assets/Projects-FF_thRi6.js +0 -1
  298. package/src/assets/web-panel/assets/SpeechSettings-l7ox6KuX.js +0 -1
  299. package/src/assets/web-panel/assets/devWarning-DyhgpXPf.js +0 -1
  300. package/src/assets/web-panel/assets/index-Ck1jhFE0.js +0 -1
  301. package/src/assets/web-panel/assets/index-c8jJEHVs.js +0 -1
@@ -0,0 +1,578 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ export const PROGRESSIVE_CANARY_WATCHDOG_PLAN_SCHEMA =
4
+ "chainlesschain.progressive-canary-watchdog-plan/v2";
5
+ export const PROGRESSIVE_CANARY_HOST_HEARTBEAT_SCHEMA =
6
+ "chainlesschain.progressive-canary-host-heartbeat/v2";
7
+ export const PROGRESSIVE_CANARY_WATCHDOG_INCIDENT_SCHEMA =
8
+ "chainlesschain.progressive-canary-watchdog-incident/v1";
9
+
10
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
11
+ const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
12
+ const PILOT_STAGES = new Set([
13
+ "candidate",
14
+ "shadow",
15
+ "canary",
16
+ "active-probation",
17
+ "active",
18
+ "rolled-back",
19
+ ]);
20
+ const WATCHED_STAGES = new Set(["shadow", "canary", "active-probation"]);
21
+ const HEARTBEAT_AUTHORITIES = new WeakSet();
22
+ const HEARTBEAT_SOURCES = new WeakSet();
23
+ const ROLLBACK_AUTHORITIES = new WeakSet();
24
+ const INCIDENT_STORES = new WeakSet();
25
+
26
+ function canonical(value) {
27
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
28
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
29
+ return `{${Object.keys(value)
30
+ .sort()
31
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
32
+ .join(",")}}`;
33
+ }
34
+
35
+ function hash(schema, value) {
36
+ return `sha256:${createHash("sha256")
37
+ .update(schema)
38
+ .update("\0")
39
+ .update(canonical(value))
40
+ .digest("hex")}`;
41
+ }
42
+
43
+ function exact(value, keys, label) {
44
+ if (
45
+ !value ||
46
+ typeof value !== "object" ||
47
+ Array.isArray(value) ||
48
+ canonical(Object.keys(value).sort()) !== canonical([...keys].sort())
49
+ )
50
+ throw new TypeError(`${label} has unexpected or missing fields`);
51
+ }
52
+
53
+ function id(value, label) {
54
+ if (typeof value !== "string" || !SAFE_ID.test(value))
55
+ throw new TypeError(`${label} is invalid`);
56
+ return value;
57
+ }
58
+
59
+ function digest(value, label) {
60
+ if (!DIGEST.test(value ?? "")) throw new TypeError(`${label} is invalid`);
61
+ return value;
62
+ }
63
+
64
+ function timestamp(value, label) {
65
+ if (!Number.isSafeInteger(value) || value < 0)
66
+ throw new TypeError(`${label} is invalid`);
67
+ return value;
68
+ }
69
+
70
+ function authorityDescriptor(value, label) {
71
+ exact(
72
+ value,
73
+ ["id", "revision", "handlerDigest", "publicKeySpkiDigest"],
74
+ label,
75
+ );
76
+ if (!Number.isSafeInteger(value.revision) || value.revision < 1)
77
+ throw new TypeError(`${label}.revision is invalid`);
78
+ return Object.freeze({
79
+ id: id(value.id, `${label}.id`),
80
+ revision: value.revision,
81
+ handlerDigest: digest(value.handlerDigest, `${label}.handlerDigest`),
82
+ publicKeySpkiDigest: digest(
83
+ value.publicKeySpkiDigest,
84
+ `${label}.publicKeySpkiDigest`,
85
+ ),
86
+ });
87
+ }
88
+
89
+ export function createProgressiveCanaryWatchdogPlan(input = {}) {
90
+ exact(
91
+ input,
92
+ [
93
+ "tenantId",
94
+ "pilotId",
95
+ "descriptorDigest",
96
+ "baselineDigest",
97
+ "hostId",
98
+ "leaseDurationMs",
99
+ "heartbeatAuthority",
100
+ "rollbackAuthority",
101
+ ],
102
+ "watchdog plan",
103
+ );
104
+ if (
105
+ !Number.isSafeInteger(input.leaseDurationMs) ||
106
+ input.leaseDurationMs < 1_000 ||
107
+ input.leaseDurationMs > 86_400_000
108
+ )
109
+ throw new TypeError("leaseDurationMs is invalid");
110
+ const core = {
111
+ schema: PROGRESSIVE_CANARY_WATCHDOG_PLAN_SCHEMA,
112
+ tenantId: id(input.tenantId, "tenantId"),
113
+ pilotId: id(input.pilotId, "pilotId"),
114
+ descriptorDigest: digest(input.descriptorDigest, "descriptorDigest"),
115
+ baselineDigest: digest(input.baselineDigest, "baselineDigest"),
116
+ hostId: id(input.hostId, "hostId"),
117
+ leaseDurationMs: input.leaseDurationMs,
118
+ heartbeatAuthority: authorityDescriptor(
119
+ input.heartbeatAuthority,
120
+ "heartbeatAuthority",
121
+ ),
122
+ rollbackAuthority: authorityDescriptor(
123
+ input.rollbackAuthority,
124
+ "rollbackAuthority",
125
+ ),
126
+ };
127
+ return Object.freeze({
128
+ ...core,
129
+ planDigest: hash(PROGRESSIVE_CANARY_WATCHDOG_PLAN_SCHEMA, core),
130
+ });
131
+ }
132
+
133
+ function verifyPlan(plan) {
134
+ if (plan?.schema !== PROGRESSIVE_CANARY_WATCHDOG_PLAN_SCHEMA)
135
+ throw new TypeError("a canonical watchdog plan is required");
136
+ const core = structuredClone(plan);
137
+ delete core.planDigest;
138
+ if (hash(PROGRESSIVE_CANARY_WATCHDOG_PLAN_SCHEMA, core) !== plan.planDigest)
139
+ throw new Error("watchdog plan digest mismatch");
140
+ return plan;
141
+ }
142
+
143
+ export function createProgressiveCanaryHeartbeatAuthority({
144
+ plan: planInput,
145
+ attestor,
146
+ verifier,
147
+ now = Date.now,
148
+ } = {}) {
149
+ const plan = verifyPlan(planInput);
150
+ if (
151
+ typeof attestor !== "function" ||
152
+ typeof verifier !== "function" ||
153
+ typeof now !== "function"
154
+ )
155
+ throw new TypeError("heartbeat authority ports are required");
156
+
157
+ async function verify(receipt) {
158
+ exact(
159
+ receipt,
160
+ [
161
+ "schema",
162
+ "planDigest",
163
+ "tenantId",
164
+ "pilotId",
165
+ "descriptorDigest",
166
+ "hostId",
167
+ "sequence",
168
+ "stage",
169
+ "activeStateDigest",
170
+ "issuedAt",
171
+ "expiresAt",
172
+ "authorityId",
173
+ "authorityRevision",
174
+ "handlerDigest",
175
+ "publicKeySpkiDigest",
176
+ "signature",
177
+ "receiptDigest",
178
+ ],
179
+ "host heartbeat",
180
+ );
181
+ if (
182
+ receipt.schema !== PROGRESSIVE_CANARY_HOST_HEARTBEAT_SCHEMA ||
183
+ receipt.planDigest !== plan.planDigest ||
184
+ receipt.tenantId !== plan.tenantId ||
185
+ receipt.pilotId !== plan.pilotId ||
186
+ receipt.descriptorDigest !== plan.descriptorDigest ||
187
+ receipt.hostId !== plan.hostId ||
188
+ !Number.isSafeInteger(receipt.sequence) ||
189
+ receipt.sequence < 0 ||
190
+ !PILOT_STAGES.has(receipt.stage) ||
191
+ !DIGEST.test(receipt.activeStateDigest ?? "") ||
192
+ !Number.isSafeInteger(receipt.issuedAt) ||
193
+ !Number.isSafeInteger(receipt.expiresAt) ||
194
+ receipt.expiresAt !== receipt.issuedAt + plan.leaseDurationMs ||
195
+ receipt.authorityId !== plan.heartbeatAuthority.id ||
196
+ receipt.authorityRevision !== plan.heartbeatAuthority.revision ||
197
+ receipt.handlerDigest !== plan.heartbeatAuthority.handlerDigest ||
198
+ receipt.publicKeySpkiDigest !==
199
+ plan.heartbeatAuthority.publicKeySpkiDigest ||
200
+ typeof receipt.signature !== "string" ||
201
+ receipt.signature.length < 32
202
+ )
203
+ throw new Error("host heartbeat binding is invalid");
204
+ const core = structuredClone(receipt);
205
+ delete core.receiptDigest;
206
+ if (
207
+ hash(PROGRESSIVE_CANARY_HOST_HEARTBEAT_SCHEMA, core) !==
208
+ receipt.receiptDigest
209
+ )
210
+ throw new Error("host heartbeat digest mismatch");
211
+ const payload = structuredClone(core);
212
+ delete payload.signature;
213
+ if (!(await verifier({ payload, signature: receipt.signature })))
214
+ throw new Error("host heartbeat signature rejected");
215
+ return Object.freeze(structuredClone(receipt));
216
+ }
217
+
218
+ const authority = Object.freeze({
219
+ planDigest: plan.planDigest,
220
+ async issue({ sequence, stage, activeStateDigest } = {}) {
221
+ const payload = {
222
+ schema: PROGRESSIVE_CANARY_HOST_HEARTBEAT_SCHEMA,
223
+ planDigest: plan.planDigest,
224
+ tenantId: plan.tenantId,
225
+ pilotId: plan.pilotId,
226
+ descriptorDigest: plan.descriptorDigest,
227
+ hostId: plan.hostId,
228
+ sequence: timestamp(sequence, "heartbeat sequence"),
229
+ stage: id(stage, "heartbeat stage"),
230
+ activeStateDigest: digest(activeStateDigest, "activeStateDigest"),
231
+ issuedAt: timestamp(Number(now()), "heartbeat clock"),
232
+ expiresAt: Number(now()) + plan.leaseDurationMs,
233
+ authorityId: plan.heartbeatAuthority.id,
234
+ authorityRevision: plan.heartbeatAuthority.revision,
235
+ handlerDigest: plan.heartbeatAuthority.handlerDigest,
236
+ publicKeySpkiDigest: plan.heartbeatAuthority.publicKeySpkiDigest,
237
+ };
238
+ if (payload.expiresAt !== payload.issuedAt + plan.leaseDurationMs)
239
+ throw new Error("heartbeat clock changed during issuance");
240
+ const signature = await attestor(Object.freeze(structuredClone(payload)));
241
+ const core = { ...payload, signature };
242
+ return verify(
243
+ Object.freeze({
244
+ ...core,
245
+ receiptDigest: hash(PROGRESSIVE_CANARY_HOST_HEARTBEAT_SCHEMA, core),
246
+ }),
247
+ );
248
+ },
249
+ verify,
250
+ });
251
+ HEARTBEAT_AUTHORITIES.add(authority);
252
+ return authority;
253
+ }
254
+
255
+ function verifyActionReceipt(receipt, action, plan, incidentDigest) {
256
+ if (
257
+ receipt?.authenticated !== true ||
258
+ receipt?.durable !== true ||
259
+ receipt.action !== action ||
260
+ receipt.planDigest !== plan.planDigest ||
261
+ receipt.incidentDigest !== incidentDigest ||
262
+ receipt.authorityId !== plan.rollbackAuthority.id ||
263
+ receipt.authorityRevision !== plan.rollbackAuthority.revision ||
264
+ receipt.handlerDigest !== plan.rollbackAuthority.handlerDigest ||
265
+ receipt.publicKeySpkiDigest !==
266
+ plan.rollbackAuthority.publicKeySpkiDigest ||
267
+ !DIGEST.test(receipt.receiptDigest ?? "")
268
+ )
269
+ throw new Error(`external ${action} authority receipt is invalid`);
270
+ if (action === "kill" && receipt.hostId !== plan.hostId)
271
+ throw new Error("external kill receipt targets another host");
272
+ if (
273
+ action === "rollback" &&
274
+ (receipt.baselineDigest !== plan.baselineDigest ||
275
+ !DIGEST.test(receipt.activeStateDigest ?? ""))
276
+ )
277
+ throw new Error("external rollback receipt targets another baseline");
278
+ return Object.freeze(structuredClone(receipt));
279
+ }
280
+
281
+ export function createProgressiveCanaryExternalRollbackAuthority({
282
+ plan: planInput,
283
+ killHost,
284
+ rollbackToBaseline,
285
+ verifyKill,
286
+ verifyRollback,
287
+ } = {}) {
288
+ const plan = verifyPlan(planInput);
289
+ if (
290
+ typeof killHost !== "function" ||
291
+ typeof rollbackToBaseline !== "function" ||
292
+ typeof verifyKill !== "function" ||
293
+ typeof verifyRollback !== "function"
294
+ )
295
+ throw new TypeError("external rollback authority ports are required");
296
+ async function verifyEffects({
297
+ incidentDigest,
298
+ heartbeatReceiptDigest,
299
+ observedAt,
300
+ killReceipt: killInput,
301
+ rollbackReceipt: rollbackInput,
302
+ }) {
303
+ digest(incidentDigest, "incidentDigest");
304
+ digest(heartbeatReceiptDigest, "heartbeatReceiptDigest");
305
+ timestamp(observedAt, "observedAt");
306
+ const request = Object.freeze({
307
+ planDigest: plan.planDigest,
308
+ incidentDigest,
309
+ heartbeatReceiptDigest,
310
+ observedAt,
311
+ });
312
+ const killReceipt = verifyActionReceipt(
313
+ killInput,
314
+ "kill",
315
+ plan,
316
+ incidentDigest,
317
+ );
318
+ if ((await verifyKill({ request, receipt: killReceipt })) !== true)
319
+ throw new Error("external kill receipt signature rejected");
320
+ const rollbackReceipt = verifyActionReceipt(
321
+ rollbackInput,
322
+ "rollback",
323
+ plan,
324
+ incidentDigest,
325
+ );
326
+ if ((await verifyRollback({ request, receipt: rollbackReceipt })) !== true)
327
+ throw new Error("external rollback receipt signature rejected");
328
+ return Object.freeze({ killReceipt, rollbackReceipt });
329
+ }
330
+ const authority = Object.freeze({
331
+ planDigest: plan.planDigest,
332
+ async engage({ incidentDigest, heartbeatReceiptDigest, observedAt }) {
333
+ digest(incidentDigest, "incidentDigest");
334
+ digest(heartbeatReceiptDigest, "heartbeatReceiptDigest");
335
+ timestamp(observedAt, "observedAt");
336
+ const request = Object.freeze({
337
+ planDigest: plan.planDigest,
338
+ incidentDigest,
339
+ heartbeatReceiptDigest,
340
+ observedAt,
341
+ });
342
+ const killReceipt = verifyActionReceipt(
343
+ await killHost({ ...request, hostId: plan.hostId }),
344
+ "kill",
345
+ plan,
346
+ incidentDigest,
347
+ );
348
+ if ((await verifyKill({ request, receipt: killReceipt })) !== true)
349
+ throw new Error("external kill receipt signature rejected");
350
+ const rollbackReceipt = verifyActionReceipt(
351
+ await rollbackToBaseline({
352
+ ...request,
353
+ baselineDigest: plan.baselineDigest,
354
+ }),
355
+ "rollback",
356
+ plan,
357
+ incidentDigest,
358
+ );
359
+ if (
360
+ (await verifyRollback({ request, receipt: rollbackReceipt })) !== true
361
+ )
362
+ throw new Error("external rollback receipt signature rejected");
363
+ return Object.freeze({ killReceipt, rollbackReceipt });
364
+ },
365
+ verifyEffects,
366
+ });
367
+ ROLLBACK_AUTHORITIES.add(authority);
368
+ return authority;
369
+ }
370
+
371
+ export function createProgressiveCanaryWatchdogIncidentStore({
372
+ reserve,
373
+ load,
374
+ commit,
375
+ } = {}) {
376
+ if (
377
+ typeof reserve !== "function" ||
378
+ typeof load !== "function" ||
379
+ typeof commit !== "function"
380
+ )
381
+ throw new TypeError("watchdog incident store ports are required");
382
+ const store = Object.freeze({ reserve, load, commit });
383
+ INCIDENT_STORES.add(store);
384
+ return store;
385
+ }
386
+
387
+ export function createProgressiveCanaryHeartbeatSource({ readLatest } = {}) {
388
+ if (typeof readLatest !== "function")
389
+ throw new TypeError("heartbeat source readLatest() is required");
390
+ const source = Object.freeze({ readLatest });
391
+ HEARTBEAT_SOURCES.add(source);
392
+ return source;
393
+ }
394
+
395
+ async function verifyIncident(value, plan, incidentDigest, rollbackAuthority) {
396
+ if (
397
+ value?.schema !== PROGRESSIVE_CANARY_WATCHDOG_INCIDENT_SCHEMA ||
398
+ value.planDigest !== plan.planDigest ||
399
+ value.incidentDigest !== incidentDigest ||
400
+ !DIGEST.test(value.killReceipt?.receiptDigest ?? "") ||
401
+ !DIGEST.test(value.rollbackReceipt?.receiptDigest ?? "")
402
+ )
403
+ throw new Error("watchdog incident binding is invalid");
404
+ const trigger = {
405
+ schema: value.schema,
406
+ planDigest: value.planDigest,
407
+ heartbeatReceiptDigest: value.heartbeatReceiptDigest,
408
+ leaseExpiredAt: value.leaseExpiredAt,
409
+ };
410
+ if (
411
+ hash(PROGRESSIVE_CANARY_WATCHDOG_INCIDENT_SCHEMA, trigger) !==
412
+ incidentDigest ||
413
+ value.killReceipt.incidentDigest !== incidentDigest ||
414
+ value.rollbackReceipt.incidentDigest !== incidentDigest
415
+ )
416
+ throw new Error("watchdog incident digest mismatch");
417
+ await rollbackAuthority.verifyEffects({
418
+ incidentDigest,
419
+ heartbeatReceiptDigest: value.heartbeatReceiptDigest,
420
+ observedAt: value.observedAt,
421
+ killReceipt: value.killReceipt,
422
+ rollbackReceipt: value.rollbackReceipt,
423
+ });
424
+ return Object.freeze(structuredClone(value));
425
+ }
426
+
427
+ export class ProgressiveCanaryExternalWatchdog {
428
+ constructor({
429
+ plan: planInput,
430
+ heartbeatAuthority,
431
+ heartbeatSource,
432
+ rollbackAuthority,
433
+ incidentStore,
434
+ } = {}) {
435
+ this.plan = verifyPlan(planInput);
436
+ if (
437
+ !HEARTBEAT_AUTHORITIES.has(heartbeatAuthority) ||
438
+ heartbeatAuthority.planDigest !== this.plan.planDigest
439
+ )
440
+ throw new TypeError("a plan-bound heartbeat authority is required");
441
+ if (
442
+ !ROLLBACK_AUTHORITIES.has(rollbackAuthority) ||
443
+ rollbackAuthority.planDigest !== this.plan.planDigest
444
+ )
445
+ throw new TypeError(
446
+ "a plan-bound external rollback authority is required",
447
+ );
448
+ if (!HEARTBEAT_SOURCES.has(heartbeatSource))
449
+ throw new TypeError("a branded durable heartbeat source is required");
450
+ if (!INCIDENT_STORES.has(incidentStore))
451
+ throw new TypeError("a branded durable incident store is required");
452
+ this._heartbeats = heartbeatAuthority;
453
+ this._heartbeatSource = heartbeatSource;
454
+ this._rollback = rollbackAuthority;
455
+ this._store = incidentStore;
456
+ Object.freeze(this);
457
+ }
458
+
459
+ async inspect({ observedAt } = {}) {
460
+ timestamp(observedAt, "observedAt");
461
+ const latest = await this._heartbeatSource.readLatest({
462
+ planDigest: this.plan.planDigest,
463
+ hostId: this.plan.hostId,
464
+ });
465
+ if (
466
+ latest?.authenticated !== true ||
467
+ latest?.durable !== true ||
468
+ !latest.receipt
469
+ )
470
+ throw new Error("latest host heartbeat was not durably authenticated");
471
+ const heartbeat = await this._heartbeats.verify(latest.receipt);
472
+ if (!WATCHED_STAGES.has(heartbeat.stage))
473
+ return Object.freeze({
474
+ healthy: true,
475
+ rolledBack: false,
476
+ incident: null,
477
+ inactive: true,
478
+ });
479
+ if (observedAt <= heartbeat.expiresAt)
480
+ return Object.freeze({
481
+ healthy: true,
482
+ rolledBack: false,
483
+ incident: null,
484
+ });
485
+ const incidentCore = {
486
+ schema: PROGRESSIVE_CANARY_WATCHDOG_INCIDENT_SCHEMA,
487
+ planDigest: this.plan.planDigest,
488
+ heartbeatReceiptDigest: heartbeat.receiptDigest,
489
+ leaseExpiredAt: heartbeat.expiresAt,
490
+ };
491
+ const incidentDigest = hash(
492
+ PROGRESSIVE_CANARY_WATCHDOG_INCIDENT_SCHEMA,
493
+ incidentCore,
494
+ );
495
+ const prior = await this._store.load({
496
+ planDigest: this.plan.planDigest,
497
+ incidentDigest,
498
+ });
499
+ if (prior)
500
+ return Object.freeze({
501
+ healthy: false,
502
+ rolledBack: true,
503
+ incident: await verifyIncident(
504
+ prior,
505
+ this.plan,
506
+ incidentDigest,
507
+ this._rollback,
508
+ ),
509
+ recovered: true,
510
+ });
511
+ const reservation = await this._store.reserve({
512
+ planDigest: this.plan.planDigest,
513
+ incidentDigest,
514
+ observedAt,
515
+ leaseDurationMs: this.plan.leaseDurationMs,
516
+ });
517
+ if (
518
+ reservation?.authenticated !== true ||
519
+ reservation?.durable !== true ||
520
+ reservation.incidentDigest !== incidentDigest ||
521
+ typeof reservation.acquired !== "boolean"
522
+ )
523
+ throw new Error("watchdog incident reservation was not authenticated");
524
+ if (!reservation.acquired) {
525
+ const completed = await this._store.load({
526
+ planDigest: this.plan.planDigest,
527
+ incidentDigest,
528
+ });
529
+ if (!completed)
530
+ throw new Error("watchdog incident is reserved by another process");
531
+ return Object.freeze({
532
+ healthy: false,
533
+ rolledBack: true,
534
+ incident: await verifyIncident(
535
+ completed,
536
+ this.plan,
537
+ incidentDigest,
538
+ this._rollback,
539
+ ),
540
+ recovered: true,
541
+ });
542
+ }
543
+ const { killReceipt, rollbackReceipt } = await this._rollback.engage({
544
+ incidentDigest,
545
+ heartbeatReceiptDigest: heartbeat.receiptDigest,
546
+ observedAt,
547
+ });
548
+ const incident = Object.freeze({
549
+ ...incidentCore,
550
+ observedAt,
551
+ killReceipt,
552
+ rollbackReceipt,
553
+ incidentDigest,
554
+ });
555
+ const acknowledgement = await this._store.commit(incident);
556
+ if (
557
+ acknowledgement?.authenticated !== true ||
558
+ acknowledgement?.durable !== true ||
559
+ acknowledgement.incidentDigest !== incidentDigest
560
+ )
561
+ throw new Error("watchdog incident was not durably authenticated");
562
+ const readback = await verifyIncident(
563
+ await this._store.load({
564
+ planDigest: this.plan.planDigest,
565
+ incidentDigest,
566
+ }),
567
+ this.plan,
568
+ incidentDigest,
569
+ this._rollback,
570
+ );
571
+ return Object.freeze({
572
+ healthy: false,
573
+ rolledBack: true,
574
+ incident: readback,
575
+ recovered: false,
576
+ });
577
+ }
578
+ }