chainlesschain 0.163.6 → 0.163.7

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 (218) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DDIUofA8.js → AIOps-axqQfwv8.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-Bm-5xYRn.js → ActionButton-DV-Ro0By.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-D5UH4ljI.js → Analytics-Bt72WEVu.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-D_ifjOOP.js → AppLayout-BtepG55E.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-BY1mXdC7.js → Artifacts-B7KaJ7S_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-Bujr4Ml3.js → Audit-FNFaUg7A.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-sioKSTcC.js → BackgroundAgents-DFb6J2wQ.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DDOAK8RK.js → Backup-CC7YBhyj.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CtCsVVke.js → BaseInput-RkgTNVtj.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-DpNj0vnd.js → Chat-hHEmGZy-.js} +4 -4
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZta3Ftr.js → ChatBubbleRenderer-CAP9YhHv.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-DoHVNSXq.js → Checkbox-z5wXOQP1.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-DlVl7Qmv.js → Codegen-DVaDJnxy.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-GIqoPYty.js → Col-CJmaRDR5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CIAPEVji.js → Community-DF29_2bI.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-BN7JiI_h.js → Compact-DtkQkBzn.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CqUWCM9B.js → Compliance-xoHDxp7I.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-A4iPp7A4.js → Cowork-BUm-R7ht.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-B2zeXXWb.js → Cron-Cgl14ZkB.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BR2xmWr8.js → Crosschain-BNcbmoqh.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BzFDjrIv.js → DID-Bwja0Zo9.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-DKtDo3yA.js → Dashboard-Bk5XjEdJ.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-RNx43_YG.js → Dropdown-Ci36Oitq.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-SwMt4Rcy.js → EmailListRenderer--U04ZN4q.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CsYebZ4X.js → FamilyGuardDashboard-B2gNPR2s.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BmRKvBTy.js → Federation-C4KghYn7.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CVxGTA-0.js → FormItemContext-QL7x_Q_0.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-x2iXpyB7.js → GenericCardRenderer-F3Ryltwm.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DfqbkiOP.js → Git-2HassK5k.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-RuHyyj5O.js → Governance-DoBIp7oe.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-Bn7uZ7rI.js → Inference--W01QhZ-.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DlP7XefZ.js → KnowledgeGraph-DmvwqGpT.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-BYNdOiCd.js → Logs-BBJ4yAel.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-aMtgN-R6.js → MarkdownRenderer-BLCZMzhJ.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-JQYmDqM8.js → Marketplace-D5lNngSI.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Cyx4yZ-9.js → McpTools-CkEVOMKH.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-VDuGZTN2.js → Memory-B1Ow1xVE.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-_yKo97gi.js → MobileBridge-SgYbUfb6.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CXRXW3q7.js → MobileProjects-BWdOvQAj.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-acTGtfLH.js → Mtc-DcTXSSma.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-ClpjXfkY.js → MtcAudit-Dt3WG4oj.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-_6Tn3o96.js → Multisig-B9B38UZx.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CK7pbZzP.js → NLProgramming-B0S4GGvG.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Czy6V_P8.js → Notes-DZ5U58Ng.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-Cqx-UVv3.js → NotificationSettings-PjL5ZW34.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C69WDxGy.js → OrderTableRenderer-DrAX2ESt.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-DFnA9vLQ.js → Organization-Cv1GYs-c.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-ReZkk2yT.js → Overflow-Bbkp_PL3.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-DzjSI0aI.js → P2P-BD8QUgoZ.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-DKTf5xIP.js → PdhVaultBrowser-BO-2PeaB.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DhQ5klhR.js → Permissions-D_OPVa02.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CUL1iHrW.js → PersonalDataHub-mh-pEmaB.js} +4 -4
  54. package/src/assets/web-panel/assets/{Pipeline-DU88iu4N.js → Pipeline-6JC2EDdb.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-Bw-sYfyK.js → Privacy-CUshzUAG.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-Bq3Q5y0z.js → ProjectInit-Cs2Aalri.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-C8spzpho.js → ProjectSettings-1ak49tcj.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +1 -0
  59. package/src/assets/web-panel/assets/{Providers-Bf4eTP9W.js → Providers-CXXxvafH.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-Dme9BDU1.js → QrScannerModal-PTcDsF58.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CIXfv1rE.js → QuickAsk-CDwucrJw.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-CIxvdeZ-.js → Recommend-CJlLVRXR.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C6k7MExI.js → RemoteSession-DlN-ETsO.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-CISDz2bl.js → Reputation-DI23LR6m.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-CdnDxXyf.js → Row-Cl7UQMrM.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-C-QpRHsl.js → RssFeed-CexHNfh8.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DBjaGzSn.js → Search-BneBWvRN.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CQKukOeE.js → Security-DX7Phgrp.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-DZz86jWb.js → Services-BWXO8Mte.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-jb8RMK0d.js → Skeleton-DCyOjKPJ.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CdY76fZG.js → Skills-CXqERsTB.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-C_CSiZX9.js → Sla-bhbrbz8E.js} +1 -1
  73. package/src/assets/web-panel/assets/SpeechSettings-3IPU0HBZ.js +1 -0
  74. package/src/assets/web-panel/assets/{SyncSettings-qvimGO0O.js → SyncSettings-DBNTQLbM.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-Dng5LPJC.js → Tasks-quP0bkN-.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-Bwqq5Wll.js → Templates-BouWmgho.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DNWuwP7Z.js → Tenant-qv0D9s7z.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-B-6Othpp.js → Terminal-BxvbE8BB.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DKpKZfzx.js → TimelineRenderer-D-IeLnJ2.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-DzfGMd2J.js → Tokens-CFMKKyVG.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-BXwUi74J.js → Trigger-L8as3UuJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BNzUq4ui.js → Trust-MxmA4VZG.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-BYugxww4.js → UkeySign-C0VvJYRi.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DdauhtSJ.js → VideoEditing-Bf5QZj8N.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-CSC9bCe_.js → Wallet-BIJ9riRz.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Q8AN3bTO.js → WebAuthn-B8p9Mhkw.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-d-LBGCuA.js → WorkflowEditor-BVsuaPen.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-BLVDCgsZ.js → chat-BfkjoKpV.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-BZlPSEHl.js → colors-DeAlsWK8.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-IWseP6R6.js → compact-item-Cs97bz5j.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DnVRV3Ao.js → createContext-BqbG60LH.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DLQZA_Wn.js → hasIn-i_RY0b1X.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-B_N4-Gq9.js → index-0-agYlWL.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DB0MJgF_.js → index-79V_zv1s.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BOZJBTWZ.js → index-B-3tEpTc.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DUq0c7gq.js → index-B-JVTrpr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Dy0R5ZED.js → index-B1CbOH1i.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Bxp7uDD8.js → index-B5UkyA3c.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DpVrK6fr.js → index-BESLFt4q.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CT9vVN-X.js → index-BOVkf1K3.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DOoQpuQY.js → index-BYUVuwKt.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CINJQEj6.js → index-BcUXAB2s.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CarMTIyQ.js → index-BkBi5TmC.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C5dgnilC.js → index-Bm7lLR4c.js} +1 -1
  106. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +1 -0
  107. package/src/assets/web-panel/assets/{index-CbQNL0ue.js → index-BuLQobzW.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CpBaJ3TD.js → index-CE2VtTlp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-jWb70ZgZ.js → index-CED2PL_y.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BEu2lMBy.js → index-CG3PRyAL.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DocEhinm.js → index-CIG8fQ2_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D_LQodeJ.js → index-COdGA-8n.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DZpYeqrh.js → index-CeWoNHau.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-gt8bNefW.js → index-Cf3WCLmy.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-N_GoWZX4.js → index-CgsqdnRV.js} +1 -1
  116. package/src/assets/web-panel/assets/index-ChVT0p9u.js +1 -0
  117. package/src/assets/web-panel/assets/{index-CZDekj7T.js → index-D2B4VPyP.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-YSw_gxlZ.js → index-D9evtvg2.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DTbxp4UH.js → index-DUUrv141.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Bbj2NS_I.js → index-DiSkx4UB.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-BZs5bBnk.js → index-Dk2qouAz.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DalA0TKC.js → index-Dk7-v4hP.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-1jeAudHd.js → index-DmbfhJUP.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C1ifZtXo.js → index-DqBgBpgp.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BhA3QEni.js → index-PT_5sBMA.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BSjilZ9L.js → index-U4f5izHz.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-C2FqfMvU.js → index-YXgLng0K.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-COev0W2g.js → index-ZxO_-E8a.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-M7wxfAbm.js → index-dIHr4B_u.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DjWnONdy.js → index-gyFpvL7l.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dkwsi1Kn.js → index-s1opAL-M.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-hwVDeoC0.js → index-yObj1O4n.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-Co67Kqmb.js → initDefaultProps-C9h9yKL3.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BMOxQSF_.js → motion-BvmLsPdu.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-C5fWDw-N.js → move-CoL4ekU1.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-BJevpL0e.js → mtc-parser-C4pMy6xV.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BCzNU8s6.js → omit-DPuJfNxx.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-CybWvDPk.js → pickAttrs-D0KEeaK2.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BMWS9HnW.js → placementArrow-BpkyINxt.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BoL2UnGY.js → responsiveObserve-DQI_wOq8.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-DWNfXraU.js → slide-DYfdDiRg.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BquTM3tX.js → statusUtils-B5dtvb0D.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BEkCleim.js → styleChecker-CF310mSj.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Oecnq7EA.js → useFlexGapSupport-D1Qp4BLp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-CkDffJ4F.js → useFs-C7_iyvJK.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-qbvKXesB.js → usePersonalDataHub-DZUt_fIm.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-C6v8n6mA.js → vnode-D3dsi0lZ.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-4CTeFILV.js → zoom-WdbOlvdQ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +2 -2
  151. package/src/commands/agent.js +90 -1
  152. package/src/commands/chat.js +11 -2
  153. package/src/commands/compact.js +106 -23
  154. package/src/commands/loop.js +28 -10
  155. package/src/commands/routine.js +1 -1
  156. package/src/commands/scheduler-daemon.js +359 -2
  157. package/src/commands/session-observability.js +305 -0
  158. package/src/commands/session.js +38 -0
  159. package/src/data/changelog.json +14 -1
  160. package/src/gateways/ws/ws-agent-handler.js +439 -5
  161. package/src/harness/jsonl-session-store.js +463 -125
  162. package/src/harness/prompt-compressor.js +86 -13
  163. package/src/harness/provider-backed-compaction.js +100 -27
  164. package/src/lib/advisor-runtime.js +3 -1
  165. package/src/lib/agent-schedule-store.js +414 -4
  166. package/src/lib/agent-team/team-adjudication.js +40 -1
  167. package/src/lib/automation-engine.js +494 -0
  168. package/src/lib/background-agent-supervisor.js +793 -215
  169. package/src/lib/background-command-argv.js +24 -0
  170. package/src/lib/background-interaction-journal.js +361 -52
  171. package/src/lib/background-interaction-resolver.js +32 -0
  172. package/src/lib/background-launch-profile.js +2 -0
  173. package/src/lib/causal-observability.js +2661 -0
  174. package/src/lib/chat-session-admission.js +76 -0
  175. package/src/lib/cost-budget.js +5 -7
  176. package/src/lib/cowork/ab-comparator-cli.js +11 -0
  177. package/src/lib/cowork/debate-review-cli.js +12 -0
  178. package/src/lib/cowork-adapter.js +159 -38
  179. package/src/lib/cowork-cron.js +357 -1
  180. package/src/lib/cowork-task-runner.js +112 -17
  181. package/src/lib/delivery-coordinator.js +142 -0
  182. package/src/lib/direct-model-usage.js +121 -0
  183. package/src/lib/file-lines.js +183 -47
  184. package/src/lib/llm-pricing.js +12 -17
  185. package/src/lib/loop.js +26 -2
  186. package/src/lib/routine-store.js +380 -21
  187. package/src/lib/runtime-usage-ledger.js +182 -0
  188. package/src/lib/scheduler-kernel/agenda-adapter.js +308 -3
  189. package/src/lib/scheduler-kernel/automation-adapter.js +410 -8
  190. package/src/lib/scheduler-kernel/automation-event-adapter.js +36 -0
  191. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +285 -3
  192. package/src/lib/scheduler-kernel/loop-adapter.js +541 -6
  193. package/src/lib/scheduler-kernel/migration-admin.js +346 -0
  194. package/src/lib/scheduler-kernel/migration-rollback-admin.js +932 -0
  195. package/src/lib/scheduler-kernel/routine-adapter.js +394 -20
  196. package/src/lib/scheduler-kernel/runtime.js +63 -1
  197. package/src/lib/scheduler-kernel/source-locator-path.js +142 -0
  198. package/src/lib/scheduler-kernel/store.js +2586 -85
  199. package/src/lib/session-host-lease.js +171 -2
  200. package/src/lib/session-host-snapshot.js +14 -3
  201. package/src/lib/session-persistence-failure.js +1 -0
  202. package/src/lib/session-tail.js +179 -34
  203. package/src/lib/session-transcript-structure.js +96 -0
  204. package/src/lib/sub-agent-context.js +328 -22
  205. package/src/lib/ws-agent-handler.js +4 -1
  206. package/src/repl/agent-repl.js +732 -91
  207. package/src/repl/chat-repl.js +5 -1
  208. package/src/runtime/agent-core.js +1272 -207
  209. package/src/runtime/fallback-model.js +5 -0
  210. package/src/runtime/headless-runner.js +324 -82
  211. package/src/runtime/headless-stream.js +232 -26
  212. package/src/runtime/policies/agent-policy.js +4 -0
  213. package/src/workers/background-agent-worker.js +403 -96
  214. package/src/assets/web-panel/assets/Projects-Dd-xuPIc.js +0 -1
  215. package/src/assets/web-panel/assets/SpeechSettings-C7tT9iad.js +0 -1
  216. package/src/assets/web-panel/assets/devWarning-Jzu62CLC.js +0 -1
  217. package/src/assets/web-panel/assets/index-Zb2MeDSy.js +0 -1
  218. package/src/assets/web-panel/assets/index-fikqml4k.js +0 -1
@@ -43,6 +43,7 @@ export const NODE_TYPE = Object.freeze({
43
43
  PARALLEL: "parallel",
44
44
  LOOP: "loop",
45
45
  });
46
+ export const AUTOMATION_SCHEDULER_MIGRATION_SCHEMA_VERSION = 1;
46
47
 
47
48
  /* ── Built-in connector catalog ────────────────────────────── */
48
49
 
@@ -310,6 +311,33 @@ export function ensureAutomationTables(db) {
310
311
  created_at TEXT DEFAULT (datetime('now'))
311
312
  )
312
313
  `);
314
+ db.exec(`
315
+ CREATE TABLE IF NOT EXISTS auto_scheduler_migrations (
316
+ flow_id TEXT PRIMARY KEY NOT NULL,
317
+ schema_version INTEGER NOT NULL CHECK (schema_version = 1),
318
+ state TEXT NOT NULL CHECK (state IN ('prepared', 'retired')),
319
+ migration_id TEXT NOT NULL UNIQUE,
320
+ source_digest TEXT NOT NULL,
321
+ target_job_id TEXT NOT NULL UNIQUE,
322
+ retirement_token TEXT UNIQUE,
323
+ prior_status TEXT NOT NULL CHECK (prior_status = 'active'),
324
+ prior_updated_at TEXT NOT NULL,
325
+ source_snapshot TEXT,
326
+ prepared_at TEXT NOT NULL,
327
+ retired_at TEXT
328
+ )
329
+ `);
330
+ const migrationColumns = new Set(
331
+ db
332
+ .prepare("PRAGMA table_info(auto_scheduler_migrations)")
333
+ .all()
334
+ .map((column) => column.name),
335
+ );
336
+ if (!migrationColumns.has("source_snapshot")) {
337
+ db.exec(
338
+ "ALTER TABLE auto_scheduler_migrations ADD COLUMN source_snapshot TEXT",
339
+ );
340
+ }
313
341
  }
314
342
 
315
343
  /* ── Helpers ───────────────────────────────────────────────── */
@@ -322,6 +350,89 @@ function _now() {
322
350
  return new Date().toISOString();
323
351
  }
324
352
 
353
+ function _stableJsonValue(value) {
354
+ if (Array.isArray(value)) return value.map(_stableJsonValue);
355
+ if (value && typeof value === "object") {
356
+ return Object.fromEntries(
357
+ Object.keys(value)
358
+ .sort()
359
+ .map((key) => [key, _stableJsonValue(value[key])]),
360
+ );
361
+ }
362
+ return value;
363
+ }
364
+
365
+ function _automationMigrationField(value, field) {
366
+ if (typeof value !== "string" || value.trim().length === 0) {
367
+ const error = new Error(
368
+ `automation scheduler migration ${field} is required`,
369
+ );
370
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_INVALID";
371
+ throw error;
372
+ }
373
+ return value.trim();
374
+ }
375
+
376
+ function _automationTransaction(db, callback) {
377
+ if (typeof db.transaction !== "function") return callback();
378
+ const transaction = db.transaction(callback);
379
+ return typeof transaction.immediate === "function"
380
+ ? transaction.immediate()
381
+ : transaction();
382
+ }
383
+
384
+ function _rowToSchedulerMigration(row) {
385
+ if (!row) return null;
386
+ return {
387
+ flowId: row.flow_id,
388
+ schemaVersion: row.schema_version,
389
+ state: row.state,
390
+ migrationId: row.migration_id,
391
+ sourceDigest: row.source_digest,
392
+ targetJobId: row.target_job_id,
393
+ retirementToken: row.retirement_token || null,
394
+ priorStatus: row.prior_status,
395
+ priorUpdatedAt: row.prior_updated_at,
396
+ sourceSnapshot: _parseJSON(row.source_snapshot, null),
397
+ preparedAt: row.prepared_at,
398
+ retiredAt: row.retired_at || null,
399
+ };
400
+ }
401
+
402
+ function _automationMigrationOptionalField(value, field) {
403
+ if (value == null) return null;
404
+ return _automationMigrationField(value, field);
405
+ }
406
+
407
+ function _automationMigrationSourceDefinition(migration) {
408
+ const source = migration?.sourceSnapshot;
409
+ if (
410
+ !source ||
411
+ typeof source !== "object" ||
412
+ source.id !== migration.flowId ||
413
+ source.status !== migration.priorStatus ||
414
+ typeof source.schedule !== "string" ||
415
+ source.schedule.length === 0
416
+ ) {
417
+ const error = new Error(
418
+ `Automation migration source definition is invalid: ${migration?.flowId || "unknown"}`,
419
+ );
420
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
421
+ throw error;
422
+ }
423
+ return source;
424
+ }
425
+
426
+ function _assertAutomationSchedulerMutationSafe(db, flowId) {
427
+ const migration = getAutomationSchedulerMigration(db, flowId);
428
+ if (!migration) return;
429
+ const error = new Error(
430
+ `Automation flow scheduler authority is owned by migration ${migration.migrationId}: ${flowId}`,
431
+ );
432
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_ACTIVE";
433
+ throw error;
434
+ }
435
+
325
436
  function _parseJSON(value, fallback) {
326
437
  if (value == null) return fallback;
327
438
  if (typeof value !== "string") return value;
@@ -469,6 +580,292 @@ export function getFlow(db, flowId) {
469
580
  );
470
581
  }
471
582
 
583
+ export function automationMigrationSourceSnapshot(flow) {
584
+ const source = { ...flow };
585
+ delete source.updatedAt;
586
+ delete source.schedulerMigration;
587
+ return _stableJsonValue(source);
588
+ }
589
+
590
+ export function automationMigrationSourceDigest(flow) {
591
+ return crypto
592
+ .createHash("sha256")
593
+ .update("chainlesschain.automation.scheduler-migration-source.v1\0", "utf8")
594
+ .update(JSON.stringify(automationMigrationSourceSnapshot(flow)), "utf8")
595
+ .digest("hex");
596
+ }
597
+
598
+ export function getAutomationSchedulerMigration(db, flowId) {
599
+ return _rowToSchedulerMigration(
600
+ db
601
+ .prepare("SELECT * FROM auto_scheduler_migrations WHERE flow_id = ?")
602
+ .get(flowId),
603
+ );
604
+ }
605
+
606
+ export function automationEffectiveSchedulerFlow(db, flow) {
607
+ if (!flow) return flow;
608
+ const migration = getAutomationSchedulerMigration(db, flow.id);
609
+ if (
610
+ migration?.schemaVersion ===
611
+ AUTOMATION_SCHEDULER_MIGRATION_SCHEMA_VERSION &&
612
+ migration.state === "retired" &&
613
+ migration.priorStatus === FLOW_STATUS.ACTIVE &&
614
+ flow.schedule === null &&
615
+ [FLOW_STATUS.PAUSED, FLOW_STATUS.ACTIVE].includes(flow.status)
616
+ ) {
617
+ const source = _automationMigrationSourceDefinition(migration);
618
+ return {
619
+ ...flow,
620
+ status: source.status,
621
+ schedule: source.schedule,
622
+ updatedAt: migration.priorUpdatedAt,
623
+ schedulerMigration: migration,
624
+ };
625
+ }
626
+ return flow;
627
+ }
628
+
629
+ export function listAutomationSchedulerFlows(db, { limit = 10_000 } = {}) {
630
+ return db
631
+ .prepare(
632
+ `SELECT f.* FROM auto_flows f
633
+ JOIN auto_scheduler_migrations m ON m.flow_id = f.id
634
+ WHERE m.state = 'retired' AND f.schedule IS NULL
635
+ AND f.status IN ('paused', 'active')
636
+ ORDER BY f.created_at DESC LIMIT ?`,
637
+ )
638
+ .all(limit)
639
+ .map(_rowToFlow)
640
+ .map((flow) => automationEffectiveSchedulerFlow(db, flow));
641
+ }
642
+
643
+ export function prepareAutomationSchedulerMigration(
644
+ db,
645
+ flowId,
646
+ { migrationId, sourceDigest, targetJobId } = {},
647
+ ) {
648
+ const migration = _automationMigrationField(migrationId, "migrationId");
649
+ const digest = _automationMigrationField(sourceDigest, "sourceDigest");
650
+ const target = _automationMigrationField(targetJobId, "targetJobId");
651
+ return _automationTransaction(db, () => {
652
+ const flow = getFlow(db, flowId);
653
+ if (!flow) throw new Error(`Flow not found: ${flowId}`);
654
+ if (flow.status !== FLOW_STATUS.ACTIVE) {
655
+ const error = new Error(`Automation flow is not active: ${flowId}`);
656
+ error.code = "AUTOMATION_SCHEDULER_FLOW_NOT_ACTIVE";
657
+ throw error;
658
+ }
659
+ if (automationMigrationSourceDigest(flow) !== digest) {
660
+ const error = new Error(
661
+ `Automation flow changed before migration: ${flowId}`,
662
+ );
663
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED";
664
+ throw error;
665
+ }
666
+ const prior = getAutomationSchedulerMigration(db, flowId);
667
+ if (prior) {
668
+ if (
669
+ prior.migrationId !== migration ||
670
+ prior.sourceDigest !== digest ||
671
+ prior.targetJobId !== target ||
672
+ prior.state !== "prepared"
673
+ ) {
674
+ const error = new Error(
675
+ `Automation flow already belongs to another migration: ${flowId}`,
676
+ );
677
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
678
+ throw error;
679
+ }
680
+ return prior;
681
+ }
682
+ const now = _now();
683
+ db.prepare(
684
+ `INSERT INTO auto_scheduler_migrations
685
+ (flow_id, schema_version, state, migration_id, source_digest,
686
+ target_job_id, retirement_token, prior_status, prior_updated_at,
687
+ source_snapshot, prepared_at, retired_at)
688
+ VALUES (?, 1, 'prepared', ?, ?, ?, NULL, 'active', ?, ?, ?, NULL)`,
689
+ ).run(
690
+ flowId,
691
+ migration,
692
+ digest,
693
+ target,
694
+ flow.updatedAt,
695
+ JSON.stringify(automationMigrationSourceSnapshot(flow)),
696
+ now,
697
+ );
698
+ return getAutomationSchedulerMigration(db, flowId);
699
+ });
700
+ }
701
+
702
+ export function retireAutomationSchedulerMigration(
703
+ db,
704
+ flowId,
705
+ { migrationId, sourceDigest, targetJobId, retirementToken } = {},
706
+ ) {
707
+ const migration = _automationMigrationField(migrationId, "migrationId");
708
+ const digest = _automationMigrationField(sourceDigest, "sourceDigest");
709
+ const target = _automationMigrationField(targetJobId, "targetJobId");
710
+ const token = _automationMigrationField(retirementToken, "retirementToken");
711
+ return _automationTransaction(db, () => {
712
+ const marker = getAutomationSchedulerMigration(db, flowId);
713
+ const flow = getFlow(db, flowId);
714
+ if (
715
+ !marker ||
716
+ marker.migrationId !== migration ||
717
+ marker.sourceDigest !== digest ||
718
+ marker.targetJobId !== target ||
719
+ !["prepared", "retired"].includes(marker.state) ||
720
+ !flow
721
+ ) {
722
+ const error = new Error(
723
+ `Automation migration changed before retirement: ${flowId}`,
724
+ );
725
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
726
+ throw error;
727
+ }
728
+ if (marker.state === "retired") {
729
+ if (
730
+ marker.retirementToken !== token ||
731
+ flow.schedule !== null ||
732
+ ![FLOW_STATUS.PAUSED, FLOW_STATUS.ACTIVE].includes(flow.status)
733
+ ) {
734
+ const error = new Error(
735
+ `Automation migration fence changed: ${flowId}`,
736
+ );
737
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
738
+ throw error;
739
+ }
740
+ if (flow.status === FLOW_STATUS.ACTIVE) {
741
+ db.prepare(
742
+ `UPDATE auto_flows SET status = 'paused' WHERE id = ? AND schedule IS NULL`,
743
+ ).run(flowId);
744
+ }
745
+ return automationEffectiveSchedulerFlow(db, flow);
746
+ }
747
+ if (automationMigrationSourceDigest(flow) !== digest) {
748
+ const error = new Error(
749
+ `Automation flow changed before retirement: ${flowId}`,
750
+ );
751
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED";
752
+ throw error;
753
+ }
754
+ const now = _now();
755
+ db.prepare(
756
+ `UPDATE auto_flows SET status = 'paused', schedule = NULL, updated_at = ?
757
+ WHERE id = ? AND status = 'active' AND updated_at = ?`,
758
+ ).run(now, flowId, marker.priorUpdatedAt);
759
+ const fenced = getFlow(db, flowId);
760
+ if (fenced?.status !== FLOW_STATUS.PAUSED || fenced.schedule !== null) {
761
+ const error = new Error(
762
+ `Automation flow changed during retirement: ${flowId}`,
763
+ );
764
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
765
+ throw error;
766
+ }
767
+ const changed = db
768
+ .prepare(
769
+ `UPDATE auto_scheduler_migrations
770
+ SET state = 'retired', retirement_token = ?, retired_at = ?
771
+ WHERE flow_id = ? AND state = 'prepared'`,
772
+ )
773
+ .run(token, now, flowId);
774
+ if (changed.changes !== 1) {
775
+ const error = new Error(
776
+ `Automation migration changed during retirement: ${flowId}`,
777
+ );
778
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
779
+ throw error;
780
+ }
781
+ return automationEffectiveSchedulerFlow(db, getFlow(db, flowId));
782
+ });
783
+ }
784
+
785
+ export function restoreAutomationSchedulerMigration(
786
+ db,
787
+ flowId,
788
+ { migrationId, sourceDigest, targetJobId, retirementToken } = {},
789
+ ) {
790
+ const migration = _automationMigrationField(migrationId, "migrationId");
791
+ const digest = _automationMigrationOptionalField(
792
+ sourceDigest,
793
+ "sourceDigest",
794
+ );
795
+ const target = _automationMigrationField(targetJobId, "targetJobId");
796
+ const token = _automationMigrationOptionalField(
797
+ retirementToken,
798
+ "retirementToken",
799
+ );
800
+ return _automationTransaction(db, () => {
801
+ const marker = getAutomationSchedulerMigration(db, flowId);
802
+ const flow = getFlow(db, flowId);
803
+ if (!marker) {
804
+ if (flow && digest && automationMigrationSourceDigest(flow) === digest) {
805
+ return flow;
806
+ }
807
+ const error = new Error(
808
+ `Automation migration fence changed before rollback: ${flowId}`,
809
+ );
810
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
811
+ throw error;
812
+ }
813
+ const source = _automationMigrationSourceDefinition(marker);
814
+ if (
815
+ marker.migrationId !== migration ||
816
+ marker.targetJobId !== target ||
817
+ (digest !== null && marker.sourceDigest !== digest) ||
818
+ marker.priorStatus !== FLOW_STATUS.ACTIVE ||
819
+ !flow
820
+ ) {
821
+ const error = new Error(
822
+ `Automation migration fence changed before rollback: ${flowId}`,
823
+ );
824
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
825
+ throw error;
826
+ }
827
+ if (marker.state === "prepared") {
828
+ if (
829
+ token !== null ||
830
+ marker.retirementToken !== null ||
831
+ automationMigrationSourceDigest(flow) !== marker.sourceDigest
832
+ ) {
833
+ const error = new Error(
834
+ `Automation migration fence changed before rollback: ${flowId}`,
835
+ );
836
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
837
+ throw error;
838
+ }
839
+ db.prepare("DELETE FROM auto_scheduler_migrations WHERE flow_id = ?").run(
840
+ flowId,
841
+ );
842
+ return flow;
843
+ }
844
+ if (
845
+ marker.state !== "retired" ||
846
+ marker.retirementToken !== token ||
847
+ flow.schedule !== null ||
848
+ ![FLOW_STATUS.PAUSED, FLOW_STATUS.ACTIVE].includes(flow.status) ||
849
+ automationMigrationSourceDigest(
850
+ automationEffectiveSchedulerFlow(db, flow),
851
+ ) !== marker.sourceDigest
852
+ ) {
853
+ const error = new Error(
854
+ `Automation migration fence changed before rollback: ${flowId}`,
855
+ );
856
+ error.code = "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT";
857
+ throw error;
858
+ }
859
+ db.prepare(
860
+ `UPDATE auto_flows SET status = ?, schedule = ?, updated_at = ? WHERE id = ?`,
861
+ ).run(source.status, source.schedule, marker.priorUpdatedAt, flowId);
862
+ db.prepare("DELETE FROM auto_scheduler_migrations WHERE flow_id = ?").run(
863
+ flowId,
864
+ );
865
+ return getFlow(db, flowId);
866
+ });
867
+ }
868
+
472
869
  export function listFlows(db, filters = {}) {
473
870
  const { status, limit = 50 } = filters;
474
871
  const all = db.data?.get("auto_flows") || [];
@@ -500,6 +897,7 @@ export function updateFlowStatus(db, flowId, status) {
500
897
  throw new Error(`Invalid flow status: ${status}`);
501
898
  }
502
899
  _requireFlow(db, flowId);
900
+ _assertAutomationSchedulerMutationSafe(db, flowId);
503
901
  db.prepare(
504
902
  `UPDATE auto_flows SET status = ?, updated_at = ? WHERE id = ?`,
505
903
  ).run(status, _now(), flowId);
@@ -510,6 +908,7 @@ export function updateFlowStatus(db, flowId, status) {
510
908
 
511
909
  export function deleteFlow(db, flowId) {
512
910
  _requireFlow(db, flowId);
911
+ _assertAutomationSchedulerMutationSafe(db, flowId);
513
912
  db.prepare(`DELETE FROM auto_triggers WHERE flow_id = ?`).run(flowId);
514
913
  db.prepare(`DELETE FROM auto_executions WHERE flow_id = ?`).run(flowId);
515
914
  db.prepare(`DELETE FROM auto_flows WHERE id = ?`).run(flowId);
@@ -527,6 +926,7 @@ export function scheduleFlow(db, flowId, cron) {
527
926
  throw new Error("cron expression has no occurrence in the next 366 days");
528
927
  }
529
928
  _requireFlow(db, flowId);
929
+ _assertAutomationSchedulerMutationSafe(db, flowId);
530
930
  db.prepare(
531
931
  `UPDATE auto_flows SET schedule = ?, updated_at = ? WHERE id = ?`,
532
932
  ).run(cron, _now(), flowId);
@@ -840,6 +1240,100 @@ export function executeFlow(db, flowId, options = {}) {
840
1240
  );
841
1241
  }
842
1242
 
1243
+ export function adjudicateAutomationExecution(
1244
+ db,
1245
+ executionId,
1246
+ { flowId, triggerType, decision, requestId } = {},
1247
+ ) {
1248
+ const execId = _normalizeExecutionId(executionId);
1249
+ if (!["confirmed_applied", "confirmed_not_applied"].includes(decision)) {
1250
+ const error = new Error("automation adjudication decision is invalid");
1251
+ error.code = "AUTOMATION_ADJUDICATION_INVALID";
1252
+ throw error;
1253
+ }
1254
+ const marker = JSON.stringify({
1255
+ authority: "scheduler-adjudication",
1256
+ requestId,
1257
+ decision,
1258
+ });
1259
+ const archivedId = `${execId}:adjudication:${String(requestId).slice(-24)}`;
1260
+ const existing = getExecution(db, execId);
1261
+ const archived = getExecution(db, archivedId);
1262
+ if (decision === "confirmed_not_applied" && archived) {
1263
+ if (
1264
+ archived.flowId !== flowId ||
1265
+ archived.triggerType !== triggerType ||
1266
+ archived.error !== marker
1267
+ ) {
1268
+ const error = new Error(
1269
+ `Automation adjudication archive mismatch: ${execId}`,
1270
+ );
1271
+ error.code = "AUTOMATION_ADJUDICATION_EVIDENCE_MISMATCH";
1272
+ throw error;
1273
+ }
1274
+ return archived;
1275
+ }
1276
+ if (!existing) {
1277
+ const error = new Error(`Automation execution not found: ${execId}`);
1278
+ error.code = "AUTOMATION_ADJUDICATION_EVIDENCE_MISMATCH";
1279
+ throw error;
1280
+ }
1281
+ if (existing.flowId !== flowId || existing.triggerType !== triggerType) {
1282
+ const error = new Error(`Automation execution binding mismatch: ${execId}`);
1283
+ error.code = "AUTOMATION_ADJUDICATION_EVIDENCE_MISMATCH";
1284
+ throw error;
1285
+ }
1286
+ if (
1287
+ existing.status !== EXECUTION_STATUS.RUNNING &&
1288
+ existing.error === marker
1289
+ ) {
1290
+ return existing;
1291
+ }
1292
+ if (existing.status !== EXECUTION_STATUS.RUNNING) {
1293
+ const error = new Error(
1294
+ `Automation execution is not outcome-unknown: ${execId}`,
1295
+ );
1296
+ error.code = "AUTOMATION_ADJUDICATION_EVIDENCE_MISMATCH";
1297
+ throw error;
1298
+ }
1299
+ if (decision === "confirmed_not_applied") {
1300
+ const result = db
1301
+ .prepare(
1302
+ `UPDATE auto_executions
1303
+ SET id = ?, status = ?, error = ?, completed_at = ?
1304
+ WHERE id = ? AND status = ?`,
1305
+ )
1306
+ .run(
1307
+ archivedId,
1308
+ EXECUTION_STATUS.CANCELLED,
1309
+ marker,
1310
+ _now(),
1311
+ execId,
1312
+ EXECUTION_STATUS.RUNNING,
1313
+ );
1314
+ if (result.changes !== 1) {
1315
+ const error = new Error(
1316
+ `Automation adjudication changed concurrently: ${execId}`,
1317
+ );
1318
+ error.code = "AUTOMATION_ADJUDICATION_EVIDENCE_MISMATCH";
1319
+ throw error;
1320
+ }
1321
+ return getExecution(db, archivedId);
1322
+ }
1323
+ db.prepare(
1324
+ `UPDATE auto_executions
1325
+ SET status = ?, error = ?, completed_at = ?
1326
+ WHERE id = ? AND status = ?`,
1327
+ ).run(
1328
+ EXECUTION_STATUS.SUCCESS,
1329
+ marker,
1330
+ _now(),
1331
+ execId,
1332
+ EXECUTION_STATUS.RUNNING,
1333
+ );
1334
+ return getExecution(db, execId);
1335
+ }
1336
+
843
1337
  function _normalizeExecutionId(value) {
844
1338
  if (
845
1339
  typeof value !== "string" ||