chainlesschain 0.163.7 → 0.164.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/package.json +5 -1
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
  23. package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
  39. package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
  41. package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
  43. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
  44. package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
  112. package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
  124. package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
  125. package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +6 -6
  154. package/src/commands/automation.js +103 -1
  155. package/src/commands/cowork.js +174 -19
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/commands/team-merge-review.js +937 -0
  161. package/src/commands/team.js +2 -0
  162. package/src/data/changelog.json +27 -1
  163. package/src/gateways/ws/action-protocol.js +35 -10
  164. package/src/gateways/ws/remote-session-protocol.js +24 -1
  165. package/src/gateways/ws/ws-agent-handler.js +12 -0
  166. package/src/gateways/ws/ws-server.js +48 -12
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +1 -0
  170. package/src/harness/remote-session-crypto.js +210 -2
  171. package/src/harness/remote-session-registry.js +159 -6
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/agent-schedule-store.js +139 -28
  175. package/src/lib/agent-team/team-merge-review-store.js +765 -0
  176. package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
  177. package/src/lib/agent-team/team-merge-review.js +1847 -0
  178. package/src/lib/automation-center-incidents.js +314 -0
  179. package/src/lib/automation-center-runtime.js +448 -0
  180. package/src/lib/automation-center.js +182 -38
  181. package/src/lib/automation-engine.js +41 -0
  182. package/src/lib/automation-execution-authority.js +241 -12
  183. package/src/lib/automation-execution-incident.js +737 -0
  184. package/src/lib/background-agent-keeper-client.js +248 -0
  185. package/src/lib/background-agent-keeper-protocol.js +147 -0
  186. package/src/lib/background-agent-supervisor.js +520 -40
  187. package/src/lib/background-interaction-resolver.js +12 -0
  188. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  189. package/src/lib/cowork-cron.js +85 -14
  190. package/src/lib/cowork-workflow.js +336 -16
  191. package/src/lib/dynamic-workflow-facade.js +648 -0
  192. package/src/lib/execution-location-contract.js +551 -0
  193. package/src/lib/execution-location-runtime.js +130 -0
  194. package/src/lib/ide-context.js +94 -6
  195. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  196. package/src/lib/packer/pkg-config-generator.js +2 -0
  197. package/src/lib/permission-authority.js +77 -0
  198. package/src/lib/permission-side-effect-center.js +495 -0
  199. package/src/lib/plugin-runtime/install.js +514 -13
  200. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  201. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  202. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  203. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  204. package/src/lib/plugin-security.js +60 -3
  205. package/src/lib/process-execution-broker/index.js +1095 -57
  206. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  207. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  208. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  209. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  210. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  211. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  212. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  213. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  214. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  215. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  216. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  217. package/src/lib/public-ide-capability-manifest.js +3 -0
  218. package/src/lib/remote-approval-bridge.js +123 -17
  219. package/src/lib/remote-membership-authority.js +632 -0
  220. package/src/lib/remote-membership-coordinator.js +2409 -0
  221. package/src/lib/remote-membership-host-store.js +1750 -0
  222. package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
  223. package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
  224. package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
  225. package/src/lib/scheduler-kernel/contract.js +91 -0
  226. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
  227. package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
  228. package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
  229. package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
  230. package/src/lib/scheduler-kernel/runtime.js +176 -3
  231. package/src/lib/scheduler-kernel/store.js +1253 -45
  232. package/src/lib/scoped-permission-store.js +369 -0
  233. package/src/lib/session-anti-rollback-anchor.js +262 -5
  234. package/src/lib/sub-agent-context.js +4 -0
  235. package/src/lib/workflow-definition-contract.js +149 -0
  236. package/src/repl/agent-repl.js +41 -7
  237. package/src/repl/chat-repl.js +2 -0
  238. package/src/repl/clipboard-image.js +735 -16
  239. package/src/repl/ide-status.js +1 -1
  240. package/src/repl/prompt-interactions.js +59 -6
  241. package/src/runtime/agent-core.js +93 -3
  242. package/src/runtime/headless-runner.js +30 -25
  243. package/src/runtime/headless-stream.js +32 -25
  244. package/src/runtime/mcp-config.js +81 -10
  245. package/src/workers/background-agent-keeper.js +498 -0
  246. package/src/workers/background-agent-worker.js +358 -13
  247. package/src/workers/background-turn-bootstrap.js +143 -0
  248. package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
  249. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
  250. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
  251. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
  252. package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
@@ -15,6 +15,7 @@ import {
15
15
  normalizeJson,
16
16
  } from "./contract.js";
17
17
  import { SchedulerRuntime } from "./runtime.js";
18
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
18
19
  import { schedulerMigrationSourceDigest } from "./store.js";
19
20
  import {
20
21
  bindSchedulerAuthorityPolicy,
@@ -677,6 +678,7 @@ export function createAgendaSchedulerAdapter({
677
678
  }
678
679
  return {
679
680
  kind: AGENDA_SCHEDULER_KIND,
681
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
680
682
  async adjudicate({ occurrence, adjudication }) {
681
683
  const payload = occurrence.payload;
682
684
  const expected = agendaEntrySnapshot(payload?.entry);
@@ -711,7 +713,7 @@ export function createAgendaSchedulerAdapter({
711
713
  }
712
714
  return { continue: true };
713
715
  },
714
- async execute({ occurrence }) {
716
+ async execute({ occurrence, checkpoint }) {
715
717
  const payload = occurrence.payload;
716
718
  const expected = agendaEntrySnapshot(payload?.entry);
717
719
  const expectedDigest = agendaEntrySnapshotDigest(expected);
@@ -757,6 +759,17 @@ export function createAgendaSchedulerAdapter({
757
759
  `Agenda entry changed after occurrence enqueue: ${expected.id}`,
758
760
  );
759
761
  }
762
+ if (expected.kind === "monitor" && typeof runMonitor !== "function") {
763
+ throw agendaError(
764
+ "AGENDA_SCHEDULER_MONITOR_RUNNER_REQUIRED",
765
+ "Agenda scheduler monitor execution requires a monitor runner",
766
+ );
767
+ }
768
+
769
+ checkpoint({
770
+ entryId: expected.id,
771
+ phase: "before_execution_bind",
772
+ });
760
773
 
761
774
  current = agendaStore.bindSchedulerExecution(expected.id, {
762
775
  occurrenceId: occurrence.id,
@@ -784,12 +797,6 @@ export function createAgendaSchedulerAdapter({
784
797
  let action = null;
785
798
  try {
786
799
  if (expected.kind === "monitor") {
787
- if (typeof runMonitor !== "function") {
788
- throw agendaError(
789
- "AGENDA_SCHEDULER_MONITOR_RUNNER_REQUIRED",
790
- "Agenda scheduler monitor execution requires a monitor runner",
791
- );
792
- }
793
800
  observation = normalizeMonitorObservation(
794
801
  expected,
795
802
  await runMonitor({
@@ -944,6 +951,9 @@ export function createAgendaSchedulerAdapter({
944
951
  );
945
952
  }
946
953
  },
954
+ async resume(context) {
955
+ return this.execute(context);
956
+ },
947
957
  classifyError(error) {
948
958
  return {
949
959
  retryable: error?.retryable === true,
@@ -1,12 +1,18 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { nextCronTime } from "../agent-schedule-store.js";
3
3
  import {
4
+ assertAutomationRuntimeBoundary,
4
5
  automationExecutionAuthorityDigest,
5
6
  automationExecutionAuthoritySnapshot,
6
7
  automationSchedulerAuthority,
8
+ classifyAutomationBoundaryError,
7
9
  normalizeAutomationExecutionAuthoritySnapshot,
8
10
  reserveAutomationExecutionAuthority,
9
11
  } from "../automation-execution-authority.js";
12
+ import {
13
+ resolveAutomationExecutionIncidentsForSucceededRun,
14
+ upsertAutomationExecutionIncident,
15
+ } from "../automation-execution-incident.js";
10
16
  import {
11
17
  EXECUTION_STATUS,
12
18
  FLOW_STATUS,
@@ -33,6 +39,7 @@ import {
33
39
  normalizeJson,
34
40
  } from "./contract.js";
35
41
  import { SchedulerRuntime } from "./runtime.js";
42
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
36
43
  import {
37
44
  schedulerJobDefinitionDigest,
38
45
  schedulerMigrationSourceDigest,
@@ -178,6 +185,54 @@ export function automationSchedulerExecutionId(occurrenceId) {
178
185
  return `exec-scheduler-${digest}`;
179
186
  }
180
187
 
188
+ function automationBoundaryIncidentEvidence(error, snapshot) {
189
+ const classified = classifyAutomationBoundaryError(error);
190
+ if (!classified) return null;
191
+ const deniedPermissions = Array.isArray(error?.details?.permissions)
192
+ ? error.details.permissions.map(String).slice(0, 32)
193
+ : [];
194
+ return {
195
+ classified,
196
+ boundary: {
197
+ ...(deniedPermissions.length > 0 ? { deniedPermissions } : {}),
198
+ ...(snapshot?.budget?.revision === undefined
199
+ ? {}
200
+ : { budgetRevision: snapshot.budget.revision }),
201
+ ...(Array.isArray(snapshot?.connectors)
202
+ ? { connectors: snapshot.connectors }
203
+ : {}),
204
+ },
205
+ details: { reasonCode: classified.code, retryable: false },
206
+ };
207
+ }
208
+
209
+ function persistAutomationSchedulerIncident(
210
+ db,
211
+ occurrence,
212
+ flow,
213
+ snapshot,
214
+ error,
215
+ now,
216
+ ) {
217
+ const evidence = automationBoundaryIncidentEvidence(error, snapshot);
218
+ if (!evidence) return null;
219
+ return upsertAutomationExecutionIncident(
220
+ db,
221
+ {
222
+ runId: automationSchedulerExecutionId(occurrence.id),
223
+ flowId: flow.id,
224
+ occurrenceId: occurrence.id,
225
+ triggerType: TRIGGER_TYPE.SCHEDULE,
226
+ category: evidence.classified.category,
227
+ code: evidence.classified.code,
228
+ authorityDigest: automationExecutionAuthorityDigest(snapshot, flow),
229
+ boundary: evidence.boundary,
230
+ details: evidence.details,
231
+ },
232
+ { now },
233
+ );
234
+ }
235
+
181
236
  export function buildAutomationSchedulerJob(flow, executionAuthority) {
182
237
  const snapshot = automationFlowSnapshot(flow);
183
238
  const normalizedExecutionAuthority =
@@ -702,7 +757,7 @@ export function authorizeAutomationOccurrence({ job, occurrence }) {
702
757
  }
703
758
  }
704
759
 
705
- function existingExecutionResult(db, occurrence, expected) {
760
+ function existingExecutionResult(db, occurrence, expected, now) {
706
761
  const executionId = automationSchedulerExecutionId(occurrence.id);
707
762
  const execution = getExecution(db, executionId);
708
763
  if (!execution) return null;
@@ -729,6 +784,9 @@ function existingExecutionResult(db, occurrence, expected) {
729
784
  { executionId: execution.id, status: execution.status },
730
785
  );
731
786
  }
787
+ resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
788
+ now,
789
+ });
732
790
  return execution;
733
791
  }
734
792
 
@@ -741,6 +799,7 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
741
799
  }
742
800
  return {
743
801
  kind: AUTOMATION_SCHEDULER_KIND,
802
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
744
803
  async adjudicate({ occurrence, adjudication }) {
745
804
  const payload = occurrence?.payload;
746
805
  const expected = automationFlowSnapshot(payload?.flow);
@@ -772,7 +831,7 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
772
831
  }
773
832
  return { continue: true };
774
833
  },
775
- async execute({ occurrence }) {
834
+ async execute({ occurrence, checkpoint }) {
776
835
  const payload = occurrence?.payload;
777
836
  const expected = automationFlowSnapshot(payload?.flow);
778
837
  const expectedDigest = automationFlowSnapshotDigest(expected);
@@ -789,7 +848,7 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
789
848
  // A prior process may have committed the flow result and died before the
790
849
  // scheduler settlement. Durable success is authoritative even if the flow
791
850
  // was subsequently paused or edited.
792
- const recovered = existingExecutionResult(db, occurrence, expected);
851
+ const recovered = existingExecutionResult(db, occurrence, expected, now);
793
852
  if (recovered) return recovered;
794
853
 
795
854
  const current = getFlow(db, expected.id);
@@ -813,14 +872,31 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
813
872
  );
814
873
  }
815
874
 
816
- reserveAutomationExecutionAuthority(
817
- db,
818
- effectiveCurrent,
819
- occurrence.id,
820
- payload.executionAuthority,
821
- payload.executionAuthorityDigest,
822
- { now },
823
- );
875
+ checkpoint({
876
+ executionId: automationSchedulerExecutionId(occurrence.id),
877
+ phase: "before_execution_reservation",
878
+ });
879
+
880
+ try {
881
+ reserveAutomationExecutionAuthority(
882
+ db,
883
+ effectiveCurrent,
884
+ occurrence.id,
885
+ payload.executionAuthority,
886
+ payload.executionAuthorityDigest,
887
+ { now },
888
+ );
889
+ } catch (error) {
890
+ persistAutomationSchedulerIncident(
891
+ db,
892
+ occurrence,
893
+ effectiveCurrent,
894
+ payload.executionAuthority,
895
+ error,
896
+ now,
897
+ );
898
+ throw error;
899
+ }
824
900
 
825
901
  let execution;
826
902
  try {
@@ -828,8 +904,20 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
828
904
  inputData: {},
829
905
  triggerType: TRIGGER_TYPE.SCHEDULE,
830
906
  executionId: automationSchedulerExecutionId(occurrence.id),
907
+ executionAuthority: payload.executionAuthority,
908
+ assertRuntimeBoundary: assertAutomationRuntimeBoundary,
831
909
  });
832
910
  } catch (cause) {
911
+ if (classifyAutomationBoundaryError(cause)) {
912
+ persistAutomationSchedulerIncident(
913
+ db,
914
+ occurrence,
915
+ effectiveCurrent,
916
+ payload.executionAuthority,
917
+ cause,
918
+ now,
919
+ );
920
+ }
833
921
  if (cause?.code === "AUTOMATION_EXECUTION_OUTCOME_UNKNOWN") {
834
922
  throw automationError(
835
923
  "AUTOMATION_SCHEDULER_OUTCOME_UNKNOWN",
@@ -847,8 +935,14 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
847
935
  { executionId: execution.id, error: execution.error },
848
936
  );
849
937
  }
938
+ resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
939
+ now,
940
+ });
850
941
  return execution;
851
942
  },
943
+ async resume(context) {
944
+ return this.execute(context);
945
+ },
852
946
  classifyError() {
853
947
  return { retryable: false };
854
948
  },
@@ -1,12 +1,18 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { Buffer } from "node:buffer";
3
3
  import {
4
+ assertAutomationRuntimeBoundary,
4
5
  automationExecutionAuthorityDigest,
5
6
  automationExecutionAuthoritySnapshot,
6
7
  automationSchedulerAuthority,
8
+ classifyAutomationBoundaryError,
7
9
  normalizeAutomationExecutionAuthoritySnapshot,
8
10
  reserveAutomationExecutionAuthority,
9
11
  } from "../automation-execution-authority.js";
12
+ import {
13
+ resolveAutomationExecutionIncidentsForSucceededRun,
14
+ upsertAutomationExecutionIncident,
15
+ } from "../automation-execution-incident.js";
10
16
  import {
11
17
  EXECUTION_STATUS,
12
18
  FLOW_STATUS,
@@ -26,6 +32,7 @@ import {
26
32
  normalizeJson,
27
33
  } from "./contract.js";
28
34
  import { SchedulerRuntime } from "./runtime.js";
35
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
29
36
 
30
37
  export const AUTOMATION_EVENT_KIND = "automation-event";
31
38
  export const AUTOMATION_EVENT_CAPABILITY = "automation.execute";
@@ -294,6 +301,39 @@ export function automationEventExecutionId(occurrenceId) {
294
301
  .digest("hex")}`;
295
302
  }
296
303
 
304
+ function persistAutomationEventIncident(db, occurrence, flow, error, now) {
305
+ const classified = classifyAutomationBoundaryError(error);
306
+ if (!classified) return null;
307
+ const snapshot = occurrence.payload.executionAuthority;
308
+ const deniedPermissions = Array.isArray(error?.details?.permissions)
309
+ ? error.details.permissions.map(String).slice(0, 32)
310
+ : [];
311
+ return upsertAutomationExecutionIncident(
312
+ db,
313
+ {
314
+ runId: automationEventExecutionId(occurrence.id),
315
+ flowId: flow.id,
316
+ occurrenceId: occurrence.id,
317
+ triggerType: TRIGGER_TYPE.EVENT,
318
+ triggerId: occurrence.payload?.trigger?.id || null,
319
+ category: classified.category,
320
+ code: classified.code,
321
+ authorityDigest: automationExecutionAuthorityDigest(snapshot, flow),
322
+ boundary: {
323
+ ...(deniedPermissions.length > 0 ? { deniedPermissions } : {}),
324
+ ...(snapshot?.budget?.revision === undefined
325
+ ? {}
326
+ : { budgetRevision: snapshot.budget.revision }),
327
+ ...(Array.isArray(snapshot?.connectors)
328
+ ? { connectors: snapshot.connectors }
329
+ : {}),
330
+ },
331
+ details: { reasonCode: classified.code, retryable: false },
332
+ },
333
+ { now },
334
+ );
335
+ }
336
+
297
337
  export function automationEventTriggerKey(event) {
298
338
  const normalized = normalizeAutomationChannelEvent(event);
299
339
  return `channel:${createHash("sha256")
@@ -514,7 +554,7 @@ export function authorizeAutomationEventOccurrence({ job, occurrence }) {
514
554
  }
515
555
  }
516
556
 
517
- function existingExecutionResult(db, occurrence, expectedFlow) {
557
+ function existingExecutionResult(db, occurrence, expectedFlow, now) {
518
558
  const executionId = automationEventExecutionId(occurrence.id);
519
559
  const execution = getExecution(db, executionId);
520
560
  if (!execution) return null;
@@ -541,6 +581,9 @@ function existingExecutionResult(db, occurrence, expectedFlow) {
541
581
  { executionId: execution.id, status: execution.status },
542
582
  );
543
583
  }
584
+ resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
585
+ now,
586
+ });
544
587
  return execution;
545
588
  }
546
589
 
@@ -553,6 +596,7 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
553
596
  }
554
597
  return {
555
598
  kind: AUTOMATION_EVENT_KIND,
599
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
556
600
  async adjudicate({ occurrence, adjudication }) {
557
601
  const payload = occurrence?.payload;
558
602
  const expectedFlow = automationEventFlowSnapshot(payload?.flow);
@@ -588,7 +632,7 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
588
632
  }
589
633
  return { continue: true };
590
634
  },
591
- async execute({ occurrence }) {
635
+ async execute({ occurrence, checkpoint }) {
592
636
  const payload = occurrence?.payload;
593
637
  const expectedFlow = automationEventFlowSnapshot(payload?.flow);
594
638
  const expectedTrigger = automationEventTriggerSnapshot(payload?.trigger);
@@ -605,7 +649,12 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
605
649
  );
606
650
  }
607
651
 
608
- const recovered = existingExecutionResult(db, occurrence, expectedFlow);
652
+ const recovered = existingExecutionResult(
653
+ db,
654
+ occurrence,
655
+ expectedFlow,
656
+ now,
657
+ );
609
658
  if (recovered) return recovered;
610
659
 
611
660
  const currentFlow = getFlow(db, expectedFlow.id);
@@ -630,14 +679,24 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
630
679
  );
631
680
  }
632
681
 
633
- reserveAutomationExecutionAuthority(
634
- db,
635
- currentFlow,
636
- occurrence.id,
637
- payload.executionAuthority,
638
- payload.executionAuthorityDigest,
639
- { now },
640
- );
682
+ checkpoint({
683
+ executionId: automationEventExecutionId(occurrence.id),
684
+ phase: "before_execution_reservation",
685
+ });
686
+
687
+ try {
688
+ reserveAutomationExecutionAuthority(
689
+ db,
690
+ currentFlow,
691
+ occurrence.id,
692
+ payload.executionAuthority,
693
+ payload.executionAuthorityDigest,
694
+ { now },
695
+ );
696
+ } catch (error) {
697
+ persistAutomationEventIncident(db, occurrence, currentFlow, error, now);
698
+ throw error;
699
+ }
641
700
 
642
701
  let execution;
643
702
  try {
@@ -645,8 +704,19 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
645
704
  inputData: { event: expectedEvent },
646
705
  triggerType: TRIGGER_TYPE.EVENT,
647
706
  executionId: automationEventExecutionId(occurrence.id),
707
+ executionAuthority: payload.executionAuthority,
708
+ assertRuntimeBoundary: assertAutomationRuntimeBoundary,
648
709
  });
649
710
  } catch (cause) {
711
+ if (classifyAutomationBoundaryError(cause)) {
712
+ persistAutomationEventIncident(
713
+ db,
714
+ occurrence,
715
+ currentFlow,
716
+ cause,
717
+ now,
718
+ );
719
+ }
650
720
  if (cause?.code === "AUTOMATION_EXECUTION_OUTCOME_UNKNOWN") {
651
721
  throw eventError(
652
722
  "AUTOMATION_EVENT_OUTCOME_UNKNOWN",
@@ -664,8 +734,14 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
664
734
  { executionId: execution.id, error: execution.error },
665
735
  );
666
736
  }
737
+ resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
738
+ now,
739
+ });
667
740
  return execution;
668
741
  },
742
+ async resume(context) {
743
+ return this.execute(context);
744
+ },
669
745
  classifyError() {
670
746
  return { retryable: false };
671
747
  },
@@ -3,6 +3,26 @@ import { Buffer } from "node:buffer";
3
3
 
4
4
  export const SCHEDULER_SCHEMA_VERSION = 1;
5
5
  export const AUTHORITY_ENVELOPE_VERSION = 1;
6
+ export const RUNTIME_CONTROL_SCHEMA_VERSION = 1;
7
+
8
+ export const RUNTIME_PAUSE_RESUME = Object.freeze({
9
+ NONE: "none",
10
+ CHECKPOINT_V1: "checkpoint_v1",
11
+ });
12
+
13
+ export const RUNTIME_CONTROL_SAFE_POINTS = Object.freeze({
14
+ BEFORE_EXECUTE: "before_execute",
15
+ ADAPTER_CHECKPOINT: "adapter_checkpoint",
16
+ });
17
+
18
+ const RUNTIME_CONTROL_FIELDS = new Set([
19
+ "schemaVersion",
20
+ "pauseResume",
21
+ "safePoints",
22
+ ]);
23
+ const RUNTIME_CONTROL_SAFE_POINT_SET = new Set(
24
+ Object.values(RUNTIME_CONTROL_SAFE_POINTS),
25
+ );
6
26
 
7
27
  export const OCCURRENCE_STATUS = Object.freeze({
8
28
  QUEUED: "queued",
@@ -286,6 +306,77 @@ export function normalizeHistoryLimit(value = DEFAULT_HISTORY_LIMIT) {
286
306
  return Math.min(value, MAX_HISTORY_LIMIT);
287
307
  }
288
308
 
309
+ /**
310
+ * Normalize the durable runtime-control capability advertised by an adapter.
311
+ *
312
+ * Missing declarations are deliberately treated as unsupported. A checkpoint
313
+ * declaration is evidence, not a hint: only the two kernel-owned safe points
314
+ * are accepted and every persisted pause request is bound to these canonical
315
+ * bytes.
316
+ */
317
+ export function normalizeRuntimeControlCapability(input) {
318
+ if (input === undefined || input === null) {
319
+ return Object.freeze({
320
+ schemaVersion: RUNTIME_CONTROL_SCHEMA_VERSION,
321
+ pauseResume: RUNTIME_PAUSE_RESUME.NONE,
322
+ safePoints: Object.freeze([]),
323
+ });
324
+ }
325
+ const capability = assertPlainObject(input, "runtimeControl");
326
+ assertKnownFields(capability, RUNTIME_CONTROL_FIELDS, "runtimeControl");
327
+ if (
328
+ capability.schemaVersion !== undefined &&
329
+ capability.schemaVersion !== RUNTIME_CONTROL_SCHEMA_VERSION
330
+ ) {
331
+ throw invalidArgument(
332
+ `runtimeControl.schemaVersion must be ${RUNTIME_CONTROL_SCHEMA_VERSION}`,
333
+ );
334
+ }
335
+ const pauseResume = capability.pauseResume ?? RUNTIME_PAUSE_RESUME.NONE;
336
+ if (!Object.values(RUNTIME_PAUSE_RESUME).includes(pauseResume)) {
337
+ throw invalidArgument(
338
+ "runtimeControl.pauseResume must be none or checkpoint_v1",
339
+ );
340
+ }
341
+ const inputSafePoints = capability.safePoints ?? [];
342
+ if (!Array.isArray(inputSafePoints)) {
343
+ throw invalidArgument("runtimeControl.safePoints must be an array");
344
+ }
345
+ const safePoints = [
346
+ ...new Set(
347
+ inputSafePoints.map((safePoint, index) =>
348
+ normalizeIdentifier(safePoint, `runtimeControl.safePoints[${index}]`, {
349
+ maxLength: 64,
350
+ }),
351
+ ),
352
+ ),
353
+ ].sort();
354
+ const unknownSafePoints = safePoints.filter(
355
+ (safePoint) => !RUNTIME_CONTROL_SAFE_POINT_SET.has(safePoint),
356
+ );
357
+ if (unknownSafePoints.length > 0) {
358
+ throw invalidArgument("runtimeControl.safePoints contains unknown values", {
359
+ safePoints: unknownSafePoints,
360
+ });
361
+ }
362
+ if (
363
+ (pauseResume === RUNTIME_PAUSE_RESUME.NONE && safePoints.length !== 0) ||
364
+ (pauseResume === RUNTIME_PAUSE_RESUME.CHECKPOINT_V1 &&
365
+ safePoints.length === 0)
366
+ ) {
367
+ throw invalidArgument(
368
+ pauseResume === RUNTIME_PAUSE_RESUME.NONE
369
+ ? "runtimeControl.safePoints must be empty when pauseResume is none"
370
+ : "runtimeControl.safePoints must declare at least one checkpoint",
371
+ );
372
+ }
373
+ return Object.freeze({
374
+ schemaVersion: RUNTIME_CONTROL_SCHEMA_VERSION,
375
+ pauseResume,
376
+ safePoints: Object.freeze(safePoints),
377
+ });
378
+ }
379
+
289
380
  /**
290
381
  * Stable identity for one logical firing. All adapters must supply the same
291
382
  * triggerKey for the same logical schedule. Including jobRevision prevents an
@@ -25,6 +25,7 @@ import {
25
25
  normalizeJson,
26
26
  } from "./contract.js";
27
27
  import { SchedulerRuntime } from "./runtime.js";
28
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
28
29
  import { schedulerMigrationSourceDigest } from "./store.js";
29
30
  import {
30
31
  bindSchedulerAuthorityPolicy,
@@ -571,6 +572,7 @@ export function createCoworkCronSchedulerAdapter({ runTask, now } = {}) {
571
572
  }
572
573
  return {
573
574
  kind: COWORK_CRON_SCHEDULER_KIND,
575
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
574
576
  async adjudicate({ occurrence, adjudication }) {
575
577
  const payload = occurrence.payload;
576
578
  const cwd = normalizedCwd(payload.cwd);
@@ -604,7 +606,7 @@ export function createCoworkCronSchedulerAdapter({ runTask, now } = {}) {
604
606
  }
605
607
  return { continue: true };
606
608
  },
607
- async execute({ occurrence, signal }) {
609
+ async execute({ occurrence, signal, checkpoint }) {
608
610
  const payload = occurrence.payload;
609
611
  const expected = coworkCronScheduleSnapshot(payload?.schedule);
610
612
  const expectedDigest = coworkCronScheduleDigest(expected);
@@ -662,6 +664,12 @@ export function createCoworkCronSchedulerAdapter({ runTask, now } = {}) {
662
664
  );
663
665
  }
664
666
 
667
+ checkpoint({
668
+ deliveryId,
669
+ phase: "before_execution_bind",
670
+ scheduleId: expected.id,
671
+ });
672
+
665
673
  current = bindSchedulerScheduleFire(cwd, expected.id, {
666
674
  deliveryId,
667
675
  occurrenceId: occurrence.id,
@@ -803,6 +811,9 @@ export function createCoworkCronSchedulerAdapter({ runTask, now } = {}) {
803
811
  );
804
812
  }
805
813
  },
814
+ async resume(context) {
815
+ return this.execute(context);
816
+ },
806
817
  classifyError(error) {
807
818
  return {
808
819
  retryable: error?.retryable === true,
@@ -7,6 +7,7 @@ import {
7
7
  normalizeJson,
8
8
  } from "./contract.js";
9
9
  import { SchedulerRuntime } from "./runtime.js";
10
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
10
11
  import {
11
12
  schedulerJobDefinitionDigest,
12
13
  schedulerMigrationSourceDigest,
@@ -785,6 +786,7 @@ export function createLoopSchedulerAdapter({ runIteration } = {}) {
785
786
  const transientResults = new Map();
786
787
  return {
787
788
  kind: LOOP_SCHEDULER_KIND,
789
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
788
790
  async adjudicate({ occurrence, adjudication }) {
789
791
  if (adjudication.decision === "confirmed_applied") {
790
792
  const match = /^iteration:(\d+)$/.exec(occurrence.triggerKey);
@@ -799,7 +801,7 @@ export function createLoopSchedulerAdapter({ runIteration } = {}) {
799
801
  }
800
802
  return { continue: true };
801
803
  },
802
- async execute({ occurrence, signal, adjudication }) {
804
+ async execute({ occurrence, signal, adjudication, checkpoint }) {
803
805
  const definition = loopExecutionSnapshot(occurrence?.payload?.definition);
804
806
  if (
805
807
  occurrence.payload.snapshotDigest !== loopExecutionDigest(definition)
@@ -826,6 +828,7 @@ export function createLoopSchedulerAdapter({ runIteration } = {}) {
826
828
  `Loop iteration may already have produced side effects; refusing replay: ${occurrence.id}`,
827
829
  );
828
830
  }
831
+ checkpoint({ iteration, phase: "before_runner" });
829
832
  const result =
830
833
  (await runIteration(iteration, { signal, definition })) || {};
831
834
  const persisted = persistedIterationResult(iteration, result);
@@ -835,6 +838,9 @@ export function createLoopSchedulerAdapter({ runIteration } = {}) {
835
838
  });
836
839
  return persisted;
837
840
  },
841
+ async resume(context) {
842
+ return this.execute(context);
843
+ },
838
844
  classifyError() {
839
845
  return { retryable: false };
840
846
  },
@@ -13,6 +13,7 @@ import {
13
13
  normalizeIdentifier,
14
14
  } from "./contract.js";
15
15
  import { SchedulerRuntime } from "./runtime.js";
16
+ import { CHECKPOINT_V1_RUNTIME_CONTROL } from "./runtime-control-capabilities.js";
16
17
  import { schedulerMigrationSourceDigest } from "./store.js";
17
18
  import {
18
19
  bindSchedulerAuthorityPolicy,
@@ -772,6 +773,7 @@ export function createRoutineSchedulerAdapter({ routineStore, runAgent } = {}) {
772
773
  }
773
774
  return {
774
775
  kind: ROUTINE_SCHEDULER_KIND,
776
+ runtimeControl: CHECKPOINT_V1_RUNTIME_CONTROL,
775
777
  async adjudicate({ occurrence, adjudication }) {
776
778
  const payload = occurrence.payload;
777
779
  const expected = payload?.routine;
@@ -812,7 +814,7 @@ export function createRoutineSchedulerAdapter({ routineStore, runAgent } = {}) {
812
814
  }
813
815
  return { continue: true };
814
816
  },
815
- async execute({ occurrence, adjudication }) {
817
+ async execute({ occurrence, adjudication, checkpoint }) {
816
818
  const payload = occurrence.payload;
817
819
  const expected = payload?.routine;
818
820
  if (!expected) {
@@ -884,6 +886,7 @@ export function createRoutineSchedulerAdapter({ routineStore, runAgent } = {}) {
884
886
  `Routine was disabled before scheduled execution: ${expected.id}`,
885
887
  );
886
888
  }
889
+ checkpoint({ phase: "before_run_bind", runId: schedulerRunId });
887
890
  const execution = await executeRoutine(
888
891
  routineStore,
889
892
  effectiveCurrent,
@@ -912,6 +915,9 @@ export function createRoutineSchedulerAdapter({ routineStore, runAgent } = {}) {
912
915
  }
913
916
  return execution;
914
917
  },
918
+ async resume(context) {
919
+ return this.execute(context);
920
+ },
915
921
  classifyError(error) {
916
922
  return { retryable: error?.retryable !== false };
917
923
  },