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
@@ -0,0 +1,737 @@
1
+ import { createHash } from "node:crypto";
2
+ import { Buffer } from "node:buffer";
3
+ import {
4
+ SchedulerKernelError,
5
+ canonicalJson,
6
+ normalizeEpochMs,
7
+ normalizeIdentifier,
8
+ } from "./scheduler-kernel/contract.js";
9
+
10
+ export const AUTOMATION_EXECUTION_INCIDENT_SCHEMA_VERSION = 1;
11
+
12
+ export const AUTOMATION_EXECUTION_INCIDENT_CATEGORY = Object.freeze({
13
+ PERMISSION: "permission",
14
+ CONNECTOR: "connector",
15
+ BUDGET: "budget",
16
+ WRITE_SCOPE: "write_scope",
17
+ });
18
+
19
+ export const AUTOMATION_EXECUTION_INCIDENT_STATUS = Object.freeze({
20
+ OPEN: "open",
21
+ RESOLVED: "resolved",
22
+ CANCELLED: "cancelled",
23
+ });
24
+
25
+ const CATEGORIES = new Set(
26
+ Object.values(AUTOMATION_EXECUTION_INCIDENT_CATEGORY),
27
+ );
28
+ const STATUSES = new Set(Object.values(AUTOMATION_EXECUTION_INCIDENT_STATUS));
29
+ const DIGEST_PATTERN = /^[0-9a-f]{64}$/u;
30
+ const TRIGGER_TYPE_PATTERN = /^[a-z][a-z0-9_-]{0,31}$/u;
31
+ const CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,127}$/u;
32
+ const CONNECTOR_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/u;
33
+ const PERMISSION_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9:._*-]{0,255}$/u;
34
+ const MAX_EVIDENCE_LIST = 32;
35
+ const MAX_EVIDENCE_BYTES = 8 * 1024;
36
+ const MAX_DETAILS_BYTES = 4 * 1024;
37
+ const OBVIOUS_SECRET_PATTERN =
38
+ /(?:-----BEGIN [A-Z ]*PRIVATE KEY-----|\b(?:bearer|basic)\s+[a-z0-9._~+/=-]{8,}|\b(?:sk|ghp|xox[baprs])[-_][a-z0-9]{16,}|\bgithub_pat_[a-z0-9_]{16,}|\bAKIA[0-9A-Z]{16}|\b(?:api[_-]?key|password|secret|token)\s*[:=])/iu;
39
+
40
+ const EVIDENCE_FIELDS = new Set([
41
+ "actionId",
42
+ "actionIndex",
43
+ "budgetLimit",
44
+ "budgetRequested",
45
+ "budgetRevision",
46
+ "budgetUsed",
47
+ "budgetWindowStartedAtMs",
48
+ "connector",
49
+ "connectors",
50
+ "decisionId",
51
+ "deniedPermissions",
52
+ "evidenceDigests",
53
+ "permission",
54
+ "policyRevision",
55
+ "reasonCode",
56
+ "recoveryCode",
57
+ "schedulerFence",
58
+ "retryable",
59
+ "writeScopeDigests",
60
+ ]);
61
+
62
+ function incidentError(code, message, details = undefined) {
63
+ const error = new SchedulerKernelError(code, message, details);
64
+ error.retryable = false;
65
+ return error;
66
+ }
67
+
68
+ function assertDatabase(db) {
69
+ if (
70
+ !db ||
71
+ typeof db.exec !== "function" ||
72
+ typeof db.prepare !== "function" ||
73
+ typeof db.transaction !== "function"
74
+ ) {
75
+ throw incidentError(
76
+ "AUTOMATION_EXECUTION_INCIDENT_DATABASE_REQUIRED",
77
+ "automation execution incidents require a compatible database",
78
+ );
79
+ }
80
+ }
81
+
82
+ function normalizeOptionalIdentifier(value, field, options = undefined) {
83
+ if (value === undefined || value === null) return null;
84
+ return normalizeSafeIdentifier(value, field, options);
85
+ }
86
+
87
+ function normalizeSafeIdentifier(value, field, options = undefined) {
88
+ const identifier = normalizeIdentifier(value, field, options);
89
+ if (OBVIOUS_SECRET_PATTERN.test(identifier)) {
90
+ throw incidentError(
91
+ "AUTOMATION_EXECUTION_INCIDENT_UNSAFE_DETAILS",
92
+ `${field} appears to contain secret material`,
93
+ );
94
+ }
95
+ return identifier;
96
+ }
97
+
98
+ function normalizeDigest(value, field) {
99
+ if (typeof value !== "string" || !DIGEST_PATTERN.test(value)) {
100
+ throw incidentError(
101
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
102
+ `${field} must be a lowercase SHA-256 digest`,
103
+ );
104
+ }
105
+ return value;
106
+ }
107
+
108
+ function normalizeCode(value, field) {
109
+ if (typeof value !== "string" || !CODE_PATTERN.test(value)) {
110
+ throw incidentError(
111
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
112
+ `${field} must be an uppercase machine-readable code`,
113
+ );
114
+ }
115
+ return value;
116
+ }
117
+
118
+ function normalizeNonnegativeInteger(value, field) {
119
+ const number = Number(value);
120
+ if (!Number.isSafeInteger(number) || number < 0) {
121
+ throw incidentError(
122
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
123
+ `${field} must be a non-negative safe integer`,
124
+ );
125
+ }
126
+ return number;
127
+ }
128
+
129
+ function normalizeStringList(value, field, itemNormalizer) {
130
+ if (!Array.isArray(value) || value.length > MAX_EVIDENCE_LIST) {
131
+ throw incidentError(
132
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
133
+ `${field} must be an array with at most ${MAX_EVIDENCE_LIST} entries`,
134
+ );
135
+ }
136
+ return [
137
+ ...new Set(
138
+ value.map((entry, index) => itemNormalizer(entry, `${field}[${index}]`)),
139
+ ),
140
+ ].sort();
141
+ }
142
+
143
+ function normalizePermission(value, field) {
144
+ const permission = normalizeSafeIdentifier(value, field);
145
+ if (!PERMISSION_PATTERN.test(permission)) {
146
+ throw incidentError(
147
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
148
+ `${field} must be a machine-readable permission`,
149
+ );
150
+ }
151
+ return permission;
152
+ }
153
+
154
+ function normalizeConnector(value, field) {
155
+ const connector = normalizeSafeIdentifier(value, field, { maxLength: 64 });
156
+ if (!CONNECTOR_PATTERN.test(connector)) {
157
+ throw incidentError(
158
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
159
+ `${field} must be a lowercase connector identifier`,
160
+ );
161
+ }
162
+ return connector;
163
+ }
164
+
165
+ function assertPlainObject(value, field) {
166
+ if (
167
+ value === null ||
168
+ typeof value !== "object" ||
169
+ Array.isArray(value) ||
170
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value))
171
+ ) {
172
+ throw incidentError(
173
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
174
+ `${field} must be a plain object`,
175
+ );
176
+ }
177
+ }
178
+
179
+ function normalizeEvidence(value, field, maximumBytes) {
180
+ const input = value ?? {};
181
+ assertPlainObject(input, field);
182
+ const unknown = Object.keys(input).filter((key) => !EVIDENCE_FIELDS.has(key));
183
+ if (unknown.length > 0) {
184
+ throw incidentError(
185
+ "AUTOMATION_EXECUTION_INCIDENT_UNSAFE_DETAILS",
186
+ `${field} contains fields that are not safe to persist`,
187
+ { fields: unknown.sort() },
188
+ );
189
+ }
190
+
191
+ const normalized = {};
192
+ for (const key of Object.keys(input).sort()) {
193
+ const entry = input[key];
194
+ if (entry === undefined) continue;
195
+ switch (key) {
196
+ case "actionId":
197
+ case "decisionId":
198
+ case "policyRevision":
199
+ normalized[key] = normalizeSafeIdentifier(entry, `${field}.${key}`);
200
+ break;
201
+ case "reasonCode":
202
+ case "recoveryCode":
203
+ normalized[key] = normalizeCode(entry, `${field}.${key}`);
204
+ break;
205
+ case "actionIndex":
206
+ case "budgetLimit":
207
+ case "budgetRequested":
208
+ case "budgetRevision":
209
+ case "budgetUsed":
210
+ case "budgetWindowStartedAtMs":
211
+ case "schedulerFence":
212
+ normalized[key] = normalizeNonnegativeInteger(entry, `${field}.${key}`);
213
+ break;
214
+ case "retryable":
215
+ if (typeof entry !== "boolean") {
216
+ throw incidentError(
217
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
218
+ `${field}.${key} must be a boolean`,
219
+ );
220
+ }
221
+ normalized[key] = entry;
222
+ break;
223
+ case "connector":
224
+ normalized[key] = normalizeConnector(entry, `${field}.${key}`);
225
+ break;
226
+ case "connectors":
227
+ normalized[key] = normalizeStringList(
228
+ entry,
229
+ `${field}.${key}`,
230
+ normalizeConnector,
231
+ );
232
+ break;
233
+ case "permission":
234
+ normalized[key] = normalizePermission(entry, `${field}.${key}`);
235
+ break;
236
+ case "deniedPermissions":
237
+ normalized[key] = normalizeStringList(
238
+ entry,
239
+ `${field}.${key}`,
240
+ normalizePermission,
241
+ );
242
+ break;
243
+ case "evidenceDigests":
244
+ case "writeScopeDigests":
245
+ normalized[key] = normalizeStringList(
246
+ entry,
247
+ `${field}.${key}`,
248
+ normalizeDigest,
249
+ );
250
+ break;
251
+ default:
252
+ throw incidentError(
253
+ "AUTOMATION_EXECUTION_INCIDENT_UNSAFE_DETAILS",
254
+ `${field}.${key} is not safe to persist`,
255
+ );
256
+ }
257
+ }
258
+
259
+ const encoded = canonicalJson(normalized, field);
260
+ if (Buffer.byteLength(encoded, "utf8") > maximumBytes) {
261
+ throw incidentError(
262
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
263
+ `${field} exceeds ${maximumBytes} encoded bytes`,
264
+ );
265
+ }
266
+ return { value: normalized, encoded };
267
+ }
268
+
269
+ function digest(namespace, value) {
270
+ return createHash("sha256")
271
+ .update(namespace, "utf8")
272
+ .update(canonicalJson(value), "utf8")
273
+ .digest("hex");
274
+ }
275
+
276
+ function normalizeTriggerType(value) {
277
+ if (typeof value !== "string" || !TRIGGER_TYPE_PATTERN.test(value)) {
278
+ throw incidentError(
279
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
280
+ "triggerType must be a lowercase machine-readable trigger type",
281
+ );
282
+ }
283
+ return value;
284
+ }
285
+
286
+ function normalizeCategory(value) {
287
+ if (!CATEGORIES.has(value)) {
288
+ throw incidentError(
289
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
290
+ `category must be one of ${[...CATEGORIES].join(", ")}`,
291
+ );
292
+ }
293
+ return value;
294
+ }
295
+
296
+ function normalizeStatus(value, field = "status") {
297
+ if (!STATUSES.has(value)) {
298
+ throw incidentError(
299
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
300
+ `${field} must be one of ${[...STATUSES].join(", ")}`,
301
+ );
302
+ }
303
+ return value;
304
+ }
305
+
306
+ function normalizeNow(now) {
307
+ const value = typeof now === "function" ? now() : (now ?? Date.now());
308
+ return normalizeEpochMs(value, "now");
309
+ }
310
+
311
+ function normalizeNewIncident(input) {
312
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
313
+ throw incidentError(
314
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
315
+ "automation execution incident input must be an object",
316
+ );
317
+ }
318
+ const boundary = normalizeEvidence(
319
+ input.boundary,
320
+ "incident.boundary",
321
+ MAX_EVIDENCE_BYTES,
322
+ );
323
+ const details = normalizeEvidence(
324
+ input.details,
325
+ "incident.details",
326
+ MAX_DETAILS_BYTES,
327
+ );
328
+ const authorityDigest = normalizeDigest(
329
+ input.authorityDigest,
330
+ "incident.authorityDigest",
331
+ );
332
+ const boundaryDigest = digest(
333
+ "chainlesschain.automation.incident.boundary.v1\0",
334
+ boundary.value,
335
+ );
336
+ const detailsDigest = digest(
337
+ "chainlesschain.automation.incident.details.v1\0",
338
+ details.value,
339
+ );
340
+ const identity = {
341
+ schemaVersion: AUTOMATION_EXECUTION_INCIDENT_SCHEMA_VERSION,
342
+ runId: normalizeSafeIdentifier(input.runId, "incident.runId"),
343
+ flowId: normalizeSafeIdentifier(input.flowId, "incident.flowId"),
344
+ occurrenceId: normalizeOptionalIdentifier(
345
+ input.occurrenceId,
346
+ "incident.occurrenceId",
347
+ ),
348
+ triggerType: normalizeTriggerType(input.triggerType),
349
+ triggerId: normalizeOptionalIdentifier(
350
+ input.triggerId,
351
+ "incident.triggerId",
352
+ ),
353
+ category: normalizeCategory(input.category),
354
+ code: normalizeCode(input.code, "incident.code"),
355
+ };
356
+ return {
357
+ ...identity,
358
+ incidentId: digest("chainlesschain.automation.incident.identity.v2\0", {
359
+ ...identity,
360
+ authorityDigest,
361
+ boundaryDigest,
362
+ detailsDigest,
363
+ }),
364
+ authorityDigest,
365
+ boundaryDigest,
366
+ boundary: boundary.value,
367
+ boundaryJson: boundary.encoded,
368
+ details: details.value,
369
+ detailsJson: details.encoded,
370
+ };
371
+ }
372
+
373
+ function parseEvidence(value, field) {
374
+ try {
375
+ return JSON.parse(value);
376
+ } catch {
377
+ throw incidentError(
378
+ "AUTOMATION_EXECUTION_INCIDENT_CORRUPT",
379
+ `stored ${field} is not valid JSON`,
380
+ );
381
+ }
382
+ }
383
+
384
+ function rowToIncident(row) {
385
+ if (!row) return null;
386
+ return {
387
+ schemaVersion: row.schema_version,
388
+ incidentId: row.incident_id,
389
+ runId: row.run_id,
390
+ flowId: row.flow_id,
391
+ occurrenceId: row.occurrence_id,
392
+ triggerType: row.trigger_type,
393
+ triggerId: row.trigger_id,
394
+ category: row.category,
395
+ code: row.code,
396
+ authorityDigest: row.authority_digest,
397
+ boundaryDigest: row.boundary_digest,
398
+ boundary: parseEvidence(row.boundary_json, "incident boundary"),
399
+ details: parseEvidence(row.details_json, "incident details"),
400
+ status: row.status,
401
+ revision: row.revision,
402
+ resolutionCode: row.resolution_code,
403
+ createdAtMs: row.created_at_ms,
404
+ updatedAtMs: row.updated_at_ms,
405
+ closedAtMs: row.closed_at_ms,
406
+ };
407
+ }
408
+
409
+ export function ensureAutomationExecutionIncidentSchema(db) {
410
+ assertDatabase(db);
411
+ db.exec(`
412
+ CREATE TABLE IF NOT EXISTS auto_execution_incidents (
413
+ incident_id TEXT PRIMARY KEY,
414
+ schema_version INTEGER NOT NULL CHECK (schema_version = 1),
415
+ run_id TEXT NOT NULL,
416
+ flow_id TEXT NOT NULL,
417
+ occurrence_id TEXT,
418
+ trigger_type TEXT NOT NULL,
419
+ trigger_id TEXT,
420
+ category TEXT NOT NULL CHECK (category IN ('permission', 'connector', 'budget', 'write_scope')),
421
+ code TEXT NOT NULL,
422
+ authority_digest TEXT NOT NULL,
423
+ boundary_digest TEXT NOT NULL,
424
+ boundary_json TEXT NOT NULL,
425
+ details_json TEXT NOT NULL,
426
+ status TEXT NOT NULL CHECK (status IN ('open', 'resolved', 'cancelled')),
427
+ revision INTEGER NOT NULL,
428
+ resolution_code TEXT,
429
+ created_at_ms INTEGER NOT NULL,
430
+ updated_at_ms INTEGER NOT NULL,
431
+ closed_at_ms INTEGER
432
+ );
433
+ CREATE INDEX IF NOT EXISTS auto_execution_incidents_run_idx
434
+ ON auto_execution_incidents (run_id, created_at_ms DESC);
435
+ CREATE INDEX IF NOT EXISTS auto_execution_incidents_flow_status_idx
436
+ ON auto_execution_incidents (flow_id, status, created_at_ms DESC);
437
+ CREATE INDEX IF NOT EXISTS auto_execution_incidents_occurrence_idx
438
+ ON auto_execution_incidents (occurrence_id, created_at_ms DESC);
439
+ `);
440
+ }
441
+
442
+ export function deriveAutomationExecutionIncidentId(input) {
443
+ return normalizeNewIncident(input).incidentId;
444
+ }
445
+
446
+ export function automationExecutionBoundaryDigest(boundary) {
447
+ const normalized = normalizeEvidence(
448
+ boundary,
449
+ "incident.boundary",
450
+ MAX_EVIDENCE_BYTES,
451
+ );
452
+ return digest(
453
+ "chainlesschain.automation.incident.boundary.v1\0",
454
+ normalized.value,
455
+ );
456
+ }
457
+
458
+ export function upsertAutomationExecutionIncident(
459
+ db,
460
+ input,
461
+ { now = Date.now } = {},
462
+ ) {
463
+ ensureAutomationExecutionIncidentSchema(db);
464
+ const incident = normalizeNewIncident(input);
465
+ const nowMs = normalizeNow(now);
466
+ const transaction = db.transaction(() => {
467
+ const inserted = db
468
+ .prepare(
469
+ `INSERT INTO auto_execution_incidents
470
+ (incident_id, schema_version, run_id, flow_id, occurrence_id,
471
+ trigger_type, trigger_id, category, code, authority_digest,
472
+ boundary_digest, boundary_json, details_json, status, revision,
473
+ resolution_code, created_at_ms, updated_at_ms, closed_at_ms)
474
+ VALUES
475
+ (@incidentId, @schemaVersion, @runId, @flowId, @occurrenceId,
476
+ @triggerType, @triggerId, @category, @code, @authorityDigest,
477
+ @boundaryDigest, @boundaryJson, @detailsJson, 'open', 1,
478
+ NULL, @nowMs, @nowMs, NULL)
479
+ ON CONFLICT(incident_id) DO NOTHING`,
480
+ )
481
+ .run({ ...incident, nowMs });
482
+ const existing = db
483
+ .prepare("SELECT * FROM auto_execution_incidents WHERE incident_id = ?")
484
+ .get(incident.incidentId);
485
+ const expected = {
486
+ schema_version: incident.schemaVersion,
487
+ run_id: incident.runId,
488
+ flow_id: incident.flowId,
489
+ occurrence_id: incident.occurrenceId,
490
+ trigger_type: incident.triggerType,
491
+ trigger_id: incident.triggerId,
492
+ category: incident.category,
493
+ code: incident.code,
494
+ authority_digest: incident.authorityDigest,
495
+ boundary_digest: incident.boundaryDigest,
496
+ boundary_json: incident.boundaryJson,
497
+ details_json: incident.detailsJson,
498
+ };
499
+ const mismatchedFields = Object.entries(expected)
500
+ .filter(([field, value]) => existing?.[field] !== value)
501
+ .map(([field]) => field)
502
+ .sort();
503
+ if (mismatchedFields.length > 0) {
504
+ throw incidentError(
505
+ "AUTOMATION_EXECUTION_INCIDENT_CONFLICT",
506
+ `automation execution incident evidence conflicts with ${incident.incidentId}`,
507
+ { incidentId: incident.incidentId, fields: mismatchedFields },
508
+ );
509
+ }
510
+ return {
511
+ ...rowToIncident(existing),
512
+ deduplicated: inserted.changes === 0,
513
+ };
514
+ });
515
+ // BEGIN IMMEDIATE serializes cross-process observers before the atomic
516
+ // INSERT-or-read path, eliminating the select-then-insert race.
517
+ return transaction.immediate();
518
+ }
519
+
520
+ export function getAutomationExecutionIncident(db, incidentId) {
521
+ ensureAutomationExecutionIncidentSchema(db);
522
+ const id = normalizeIdentifier(incidentId, "incidentId");
523
+ return rowToIncident(
524
+ db
525
+ .prepare("SELECT * FROM auto_execution_incidents WHERE incident_id = ?")
526
+ .get(id),
527
+ );
528
+ }
529
+
530
+ export function listAutomationExecutionIncidents(db, filters = {}) {
531
+ ensureAutomationExecutionIncidentSchema(db);
532
+ if (!filters || typeof filters !== "object" || Array.isArray(filters)) {
533
+ throw incidentError(
534
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
535
+ "incident filters must be an object",
536
+ );
537
+ }
538
+ const clauses = [];
539
+ const parameters = [];
540
+ const addIdentifierFilter = (column, value, field) => {
541
+ if (value === undefined) return;
542
+ clauses.push(`${column} = ?`);
543
+ parameters.push(normalizeIdentifier(value, field));
544
+ };
545
+ addIdentifierFilter("run_id", filters.runId, "filters.runId");
546
+ addIdentifierFilter("flow_id", filters.flowId, "filters.flowId");
547
+ addIdentifierFilter(
548
+ "occurrence_id",
549
+ filters.occurrenceId,
550
+ "filters.occurrenceId",
551
+ );
552
+ if (filters.triggerType !== undefined) {
553
+ clauses.push("trigger_type = ?");
554
+ parameters.push(normalizeTriggerType(filters.triggerType));
555
+ }
556
+ if (filters.category !== undefined) {
557
+ clauses.push("category = ?");
558
+ parameters.push(normalizeCategory(filters.category));
559
+ }
560
+ if (filters.status !== undefined) {
561
+ clauses.push("status = ?");
562
+ parameters.push(normalizeStatus(filters.status, "filters.status"));
563
+ }
564
+ const requestedLimit = filters.limit ?? 50;
565
+ if (!Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {
566
+ throw incidentError(
567
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
568
+ "filters.limit must be a positive safe integer",
569
+ );
570
+ }
571
+ const limit = Math.min(requestedLimit, 200);
572
+ parameters.push(limit);
573
+ const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
574
+ return db
575
+ .prepare(
576
+ `SELECT * FROM auto_execution_incidents
577
+ ${where}
578
+ ORDER BY created_at_ms DESC, incident_id ASC
579
+ LIMIT ?`,
580
+ )
581
+ .all(...parameters)
582
+ .map(rowToIncident);
583
+ }
584
+
585
+ function transitionIncident(
586
+ db,
587
+ incidentId,
588
+ targetStatus,
589
+ { expectedRevision, resolutionCode, now },
590
+ ) {
591
+ ensureAutomationExecutionIncidentSchema(db);
592
+ const id = normalizeIdentifier(incidentId, "incidentId");
593
+ const revision = normalizeNonnegativeInteger(
594
+ expectedRevision,
595
+ "expectedRevision",
596
+ );
597
+ if (revision < 1) {
598
+ throw incidentError(
599
+ "AUTOMATION_EXECUTION_INCIDENT_INVALID",
600
+ "expectedRevision must be a positive safe integer",
601
+ );
602
+ }
603
+ const normalizedResolutionCode = normalizeCode(
604
+ resolutionCode,
605
+ "resolutionCode",
606
+ );
607
+ const nowMs = normalizeNow(now);
608
+ const transaction = db.transaction(() => {
609
+ const current = db
610
+ .prepare("SELECT * FROM auto_execution_incidents WHERE incident_id = ?")
611
+ .get(id);
612
+ if (!current) {
613
+ throw incidentError(
614
+ "AUTOMATION_EXECUTION_INCIDENT_NOT_FOUND",
615
+ `automation execution incident was not found: ${id}`,
616
+ { incidentId: id },
617
+ );
618
+ }
619
+ if (current.revision !== revision) {
620
+ throw incidentError(
621
+ "AUTOMATION_EXECUTION_INCIDENT_REVISION_CONFLICT",
622
+ `automation execution incident revision changed: ${id}`,
623
+ {
624
+ incidentId: id,
625
+ expectedRevision: revision,
626
+ actualRevision: current.revision,
627
+ },
628
+ );
629
+ }
630
+ if (current.status !== AUTOMATION_EXECUTION_INCIDENT_STATUS.OPEN) {
631
+ throw incidentError(
632
+ "AUTOMATION_EXECUTION_INCIDENT_STATE_CONFLICT",
633
+ `automation execution incident is already closed: ${id}`,
634
+ { incidentId: id, status: current.status },
635
+ );
636
+ }
637
+ const result = db
638
+ .prepare(
639
+ `UPDATE auto_execution_incidents
640
+ SET status = ?, revision = revision + 1, resolution_code = ?,
641
+ updated_at_ms = ?, closed_at_ms = ?
642
+ WHERE incident_id = ? AND revision = ? AND status = 'open'`,
643
+ )
644
+ .run(targetStatus, normalizedResolutionCode, nowMs, nowMs, id, revision);
645
+ if (result.changes !== 1) {
646
+ throw incidentError(
647
+ "AUTOMATION_EXECUTION_INCIDENT_REVISION_CONFLICT",
648
+ `automation execution incident changed concurrently: ${id}`,
649
+ { incidentId: id, expectedRevision: revision },
650
+ );
651
+ }
652
+ return rowToIncident(
653
+ db
654
+ .prepare("SELECT * FROM auto_execution_incidents WHERE incident_id = ?")
655
+ .get(id),
656
+ );
657
+ });
658
+ return transaction();
659
+ }
660
+
661
+ export function resolveAutomationExecutionIncident(
662
+ db,
663
+ incidentId,
664
+ { expectedRevision, resolutionCode = "RESOLVED", now = Date.now } = {},
665
+ ) {
666
+ return transitionIncident(
667
+ db,
668
+ incidentId,
669
+ AUTOMATION_EXECUTION_INCIDENT_STATUS.RESOLVED,
670
+ { expectedRevision, resolutionCode, now },
671
+ );
672
+ }
673
+
674
+ export function cancelAutomationExecutionIncident(
675
+ db,
676
+ incidentId,
677
+ { expectedRevision, resolutionCode = "CANCELLED", now = Date.now } = {},
678
+ ) {
679
+ return transitionIncident(
680
+ db,
681
+ incidentId,
682
+ AUTOMATION_EXECUTION_INCIDENT_STATUS.CANCELLED,
683
+ { expectedRevision, resolutionCode, now },
684
+ );
685
+ }
686
+
687
+ /**
688
+ * Close every incident that is still open for one exact, authoritative run.
689
+ * The per-row revision/status predicate is the CAS: only applied updates are
690
+ * reported, so an incident closed before this transaction is never presented
691
+ * to callers as resolved by the successful execution.
692
+ */
693
+ export function resolveAutomationExecutionIncidentsForSucceededRun(
694
+ db,
695
+ runId,
696
+ { now = Date.now } = {},
697
+ ) {
698
+ ensureAutomationExecutionIncidentSchema(db);
699
+ const id = normalizeSafeIdentifier(runId, "runId");
700
+ const nowMs = normalizeNow(now);
701
+ const transaction = db.transaction(() => {
702
+ const candidates = db
703
+ .prepare(
704
+ `SELECT incident_id, revision
705
+ FROM auto_execution_incidents
706
+ WHERE run_id = ? AND status = 'open'
707
+ ORDER BY created_at_ms ASC, incident_id ASC`,
708
+ )
709
+ .all(id);
710
+ const update = db.prepare(
711
+ `UPDATE auto_execution_incidents
712
+ SET status = 'resolved', revision = revision + 1,
713
+ resolution_code = 'EXECUTION_SUCCEEDED', updated_at_ms = ?,
714
+ closed_at_ms = ?
715
+ WHERE incident_id = ? AND revision = ? AND status = 'open'`,
716
+ );
717
+ const resolvedIncidentIds = [];
718
+ for (const candidate of candidates) {
719
+ const result = update.run(
720
+ nowMs,
721
+ nowMs,
722
+ candidate.incident_id,
723
+ candidate.revision,
724
+ );
725
+ if (result.changes === 1) {
726
+ resolvedIncidentIds.push(candidate.incident_id);
727
+ }
728
+ }
729
+ return {
730
+ runId: id,
731
+ resolutionCode: "EXECUTION_SUCCEEDED",
732
+ resolvedCount: resolvedIncidentIds.length,
733
+ resolvedIncidentIds,
734
+ };
735
+ });
736
+ return transaction.immediate();
737
+ }