chainlesschain 0.166.6 → 0.166.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 (189) hide show
  1. package/package.json +3 -1
  2. package/src/assets/web-panel/assets/{AIOps-CVnFjTfG.js → AIOps-BlrmQxa2.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BxkwuuQC.js → ActionButton-zyRyLITg.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-C2670q6z.js → Analytics-DwGz7OGN.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-CU_rylW6.js → AppLayout-Dc-nj7Zd.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-DGJmYqnj.js → Artifacts-7Hu3O73p.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-BZOQbINJ.js → Audit-Bnoe3-fR.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DghB4QwF.js → BackgroundAgents-BqYFrDKZ.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-l0mwPbta.js → Backup-B3hwW1nz.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-Bv3WSZOh.js → BaseInput-XFVxLA4w.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-s88nBdvt.js → Chat-CWRDNw7e.js} +5 -5
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Z8CBuB1a.js → ChatBubbleRenderer-Bf30VM8G.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-B5icasEs.js → Checkbox-kFeeBgac.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-CsUFqNud.js → Codegen-CCxp8xoI.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DlBtClaW.js → Col-BLKZalle.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-xRn1IdLB.js → Community-DD0eWCez.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-naIr8a_o.js → Compact-CHqHWdy0.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Dp9esfFE.js → Compliance-Bw54uPiK.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-DQlMYJB-.js → Cowork-DZ13zKNJ.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-Cd0oNLzJ.js → Cron-Dlj5Jevg.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BtDIx3XX.js → Crosschain-Nvz0aR0j.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BOlpzEwg.js → DID-Ct89eUyY.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-DV15Axk1.js → Dashboard-BHUH5IAe.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-COXrewN1.js → Dropdown-BhZG-PO7.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-EjIt0Cm7.js → EmailListRenderer-ae4RVwwJ.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DJlhwb-R.js → FamilyGuardDashboard-AOcxLfLr.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BMiFl82k.js → Federation-BK2PJQOF.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-BUcDQyxn.js → FormItemContext-C2n3xO2_.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-C25uFxvK.js → GenericCardRenderer-DcyUVFZq.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-D20uaEUU.js → Git-tBae9Lt8.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CQxYJjCX.js → Governance-DmNR3AP4.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-m-sczpS5.js → Inference-CoseEigi.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-CBsIlU0S.js → KnowledgeGraph-Bdjd1sxr.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-D0-5bqeu.js → Logs-CtlkKIcn.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-BwH414Ms.js → MarkdownRenderer-CZsTBEQE.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-CwDGFu2Q.js → Marketplace-BTYb7nEx.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-7FxJ3omT.js → McpTools-D0iUdW3P.js} +2 -2
  38. package/src/assets/web-panel/assets/{Memory-DOVyb59U.js → Memory--gwI7w4Y.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-DZXl-Hje.js → MobileBridge-JmFBi24T.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-DlZ8tRXt.js → MobileProjects-BK01cQRx.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-D7Pjx1s_.js → Mtc-u7avzyoO.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-BND7lX8p.js → MtcAudit-gT3z5fo_.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-BknS7B-p.js → Multisig-BIqZTz5n.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-7C2-KPHt.js → NLProgramming-DdhVfXYq.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-DNWdTndN.js → Notes-CBlyUmY3.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-DCm4KcJZ.js → NotificationSettings-DSyI26N3.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DyVwwjJx.js → OrderTableRenderer-B7IEuNz4.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-Dl2O_qJ9.js → Organization-ozhi4kGS.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-BOFCvk9Q.js → Overflow-CBy57RVM.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-DgdVowY1.js → P2P-CA-ZRv77.js} +2 -2
  51. package/src/assets/web-panel/assets/PdhVaultBrowser-DOHc9zm8.js +7 -0
  52. package/src/assets/web-panel/assets/{Permissions-BHNEUUwa.js → Permissions-DiP632GP.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CaZbrOdz.js → PersonalDataHub-AnU8O-SS.js} +5 -5
  54. package/src/assets/web-panel/assets/{Pipeline-DJDnoXmE.js → Pipeline-DDibOUaP.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-CBQr2eX8.js → Privacy-D421t36T.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-Yghqa06z.js → ProjectInit-DR879ZPJ.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-HBAtJi8U.js → ProjectSettings-Ded8o6aY.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-DiCGnMjz.js → Projects-BHPxiucB.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-uJTz77GI.js → Providers-Boivuu-E.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-k3M5ouTp.js → QrScannerModal-xKD_ntKp.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CMji45PH.js → QuickAsk-D3y_A6FV.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-DyoZYPls.js → Recommend-BjKM-YC2.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-s1gR38IO.js → RemoteSession-CgqKMXG4.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-D4hIs4vV.js → Reputation-Ci2GjH5p.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-mzE-ElTg.js → Row-B0-T2BSh.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-cg7J3hI6.js → RssFeed-Bet-ur-r.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-6M0TkGSZ.js → Search-DWtRAS2R.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-B1GQ67qh.js → Security-BDfu2Qn6.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-D_RwU_5S.js → Services-CvJmvSMM.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-TZjk-dsW.js → Skeleton-CEbrKpdC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CG6FcaCV.js → Skills-CjVeiETf.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-BI190QDv.js → Sla-Dibypxum.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-BWmxF2Wu.js → SpeechSettings-XflYXp7a.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-CwPiGw6L.js → SyncSettings-ro1Ivx1E.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-BIXgCeSk.js → Tasks-CHq1qFbo.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CQFgGCoK.js → Templates-CRnUZxtZ.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DAelEdkL.js → Tenant-jUX72JCA.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-BbqWK6qh.js → Terminal-BBhAs7pt.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-cmG3zvY5.js → TimelineRenderer-CD5M3RGp.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-C8444NKU.js → Tokens-sah3v0gu.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-C1Rpnz0I.js → Trigger-BNT3Uz3s.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-u4koPiFD.js → Trust-BytMGPMo.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-oPWKn80Z.js → UkeySign-BkYVMRQs.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-D0CUUY_5.js → VideoEditing-psvb5Q7Y.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-fu9pIAbt.js → Wallet-PFQTW0MH.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Bc5ciuOx.js → WebAuthn-DgO-OwRT.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-BCin4_4N.js → WorkflowEditor-DL2l9VNl.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-B2jbM-XN.js → chat-C84akEzN.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-CUVoUQ_2.js → colors-DzTWuQKP.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-DgOGpkRH.js → compact-item-CR9LJQFv.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DIxU6eKI.js → createContext-CTTov5Kn.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-BOhvmlpc.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DoKRKMav.js → hasIn-DALj523o.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-i5MB455u.js → index-3-XJoYgX.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CLdpHe6w.js → index-7ux_XohH.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B3F_p8NA.js → index-AXnERsyV.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-D2yo6ast.js → index-B2qpjU-D.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CWbL1-N0.js → index-B6QOJbSn.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DtyAuGOm.js → index-BDyt57zL.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DpTFx8Xx.js → index-BHRXKiU1.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CF80xxPG.js → index-BKNIzw0U.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BRMEO2Tl.js → index-BNaQt49r.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-ByjrulIZ.js → index-Be6Os5S8.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BCLeNqIL.js → index-C5eeMl_2.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DJMHnbmu.js → index-CNmTDXmf.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-2flsPFIX.js → index-CXTEpfGe.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BwYofQJg.js → index-CXaCRXN4.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-B5ySiGYy.js → index-CZhhFQi9.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CeWSw-z5.js → index-Cef0n4k_.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C846lPGD.js → index-CjkPDSX4.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C9TsO9T9.js → index-CmELknPe.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CqlwIjJx.js → index-CnxjXIsK.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Co4lDEk-.js → index-CqUgXYIQ.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Cj-us-D_.js → index-CunGDV0g.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BFUprhNd.js → index-D0MqUnKO.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DGTZdZOE.js → index-D9ScRFxz.js} +3 -3
  117. package/src/assets/web-panel/assets/{index-C88m9lsi.js → index-DBIPnoTj.js} +1 -1
  118. package/src/assets/web-panel/assets/index-DDyMJexx.js +1 -0
  119. package/src/assets/web-panel/assets/{index-BXb-Smmm.js → index-DH6OG-ci.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-eTWPaeBI.js → index-DZER6Lj3.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cskz--fd.js → index-D_Bg0LdK.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-D-ufbAJB.js → index-Dah8M4l2.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DHugFl3v.js → index-DjE_ew7U.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B9mSYovv.js → index-DtW6Zr_i.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Ds8r3Fzb.js → index-DxdzSljS.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CPXdBnGi.js → index-QW0EXx14.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-B-f6l4Vm.js → index-W9axN_Ce.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CpvyOt5Z.js → index-_8vetPbU.js} +1 -1
  129. package/src/assets/web-panel/assets/index-btiojFYn.js +1 -0
  130. package/src/assets/web-panel/assets/{index-eYxUASSG.js → index-eJcFleIV.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-be8SonCh.js → index-hzzTITR9.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BtSPhEyC.js → index-s4CFyn-n.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-B4chl7iR.js → initDefaultProps-JuW8mFj7.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-DruN9h96.js → motion-Cwb0HBve.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Cl0UtCgU.js → move-DHokzMgu.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-FX2ttw70.js → mtc-parser-DX31y6QS.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BDCneY46.js → omit-BCIUYDA6.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-DycsEg8b.js → pickAttrs-DMCj4EoZ.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-Bc-dBuMv.js → placementArrow-Dy5K-u1s.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve--Wwaf8lu.js → responsiveObserve-DkGeZu54.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-vDmHQqHH.js → slide-Dc5dyJdg.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-9c52yv3G.js → statusUtils-DIUBjOaC.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BT4BiO6_.js → styleChecker-DmyEOxm5.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-C7XxWPcP.js → useFlexGapSupport-FRhakk1e.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-BHoMqh4i.js → useFs-clXyV1WQ.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-BOLxvsAG.js → usePersonalDataHub-UF6DG41z.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-CA7poeeP.js → vnode-CoCt95G7.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-B_sAn-co.js → zoom-yVWt-ENm.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/graph.js +215 -5
  151. package/src/commands/team-distributed.js +342 -2
  152. package/src/commands/team.js +169 -7
  153. package/src/data/changelog.json +13 -0
  154. package/src/generated/cc-agent-protocol.schema.json +6 -1
  155. package/src/lib/agent-team/task-lease.js +315 -0
  156. package/src/lib/agent-team/team-agent-stream.js +16 -0
  157. package/src/lib/agent-team/team-distributed-graph-bridge.js +257 -0
  158. package/src/lib/agent-team/team-distributed-graph-writer.js +523 -0
  159. package/src/lib/agent-team/team-distributed-queue.js +251 -0
  160. package/src/lib/agent-team/team-graph-runtime-adapter.js +1918 -0
  161. package/src/lib/agent-team/team-runner.js +225 -2
  162. package/src/lib/app-server/graph-runtime.js +754 -0
  163. package/src/lib/app-server/rollout-store.js +32 -0
  164. package/src/lib/app-server/server.js +140 -0
  165. package/src/lib/autonomous-agent.js +11 -0
  166. package/src/lib/cowork-graph-authority-adapter.js +455 -0
  167. package/src/lib/dynamic-workflow-facade.js +83 -16
  168. package/src/lib/graph-kernel/adapters.js +93 -20
  169. package/src/lib/graph-kernel/authority.js +324 -0
  170. package/src/lib/graph-kernel/compiler.js +1 -8
  171. package/src/lib/graph-kernel/cutover-authority-resolver.js +219 -0
  172. package/src/lib/graph-kernel/cutover-ledger.js +650 -0
  173. package/src/lib/graph-kernel/event-store.js +15 -1
  174. package/src/lib/graph-kernel/graph-runtime-surfaces.json +1427 -0
  175. package/src/lib/graph-kernel/index.js +4 -0
  176. package/src/lib/graph-kernel/migration-saga.js +309 -0
  177. package/src/lib/graph-kernel/runtime-surface-manifest.js +481 -0
  178. package/src/lib/graph-kernel/runtime.js +661 -24
  179. package/src/lib/graph-kernel/store-cutover-evidence.js +354 -0
  180. package/src/lib/graph-kernel/trace-reducer.js +6 -0
  181. package/src/lib/graph-kernel/trigger-adapter.js +60 -3
  182. package/src/lib/legacy-runtime-authority.js +160 -0
  183. package/src/lib/orchestrator.js +28 -0
  184. package/src/lib/scheduler-kernel/graph-authority-adapter.js +512 -0
  185. package/src/lib/scheduler-kernel/runtime.js +75 -2
  186. package/src/assets/web-panel/assets/PdhVaultBrowser-BiaZfQIM.js +0 -7
  187. package/src/assets/web-panel/assets/devWarning-DiSlgCC4.js +0 -1
  188. package/src/assets/web-panel/assets/index-9WIQEHvv.js +0 -1
  189. package/src/assets/web-panel/assets/index-B7mDobAl.js +0 -1
@@ -27,6 +27,10 @@ import { AgentRouter } from "./agent-router.js";
27
27
  import { NotificationManager } from "./notifiers/index.js";
28
28
  import { createChatFn } from "./cowork-adapter.js";
29
29
  import { firstBalancedJson } from "./json-schema-output.js";
30
+ import {
31
+ assertCLILegacyMutationAllowed,
32
+ cliLegacyRuntimeReadOnly,
33
+ } from "./legacy-runtime-authority.js";
30
34
  import executionBroker from "./process-execution-broker/index.js";
31
35
  import runtimeClaimsContract from "@chainlesschain/session-core/runtime-claims";
32
36
 
@@ -108,6 +112,20 @@ export class Orchestrator extends EventEmitter {
108
112
  /** @type {Map<string, object>} taskId → task */
109
113
  this._tasks = new Map();
110
114
 
115
+ this._legacyReadOnly = cliLegacyRuntimeReadOnly(process.env, {
116
+ entryId: "cli-legacy-orchestrate",
117
+ });
118
+ if (this._legacyReadOnly) {
119
+ this._router = new AgentRouter({
120
+ backends: [],
121
+ maxParallel: this.maxParallel,
122
+ });
123
+ this.notifier = { isConfigured: false };
124
+ this._chat = null;
125
+ this._cronTimer = null;
126
+ return;
127
+ }
128
+
111
129
  // Multi-path agent router
112
130
  this._router =
113
131
  options.agentRouter ||
@@ -155,6 +173,7 @@ export class Orchestrator extends EventEmitter {
155
173
  * @returns {Promise<object>} Final task record
156
174
  */
157
175
  async addTask(description, opts = {}) {
176
+ assertCLILegacyMutationAllowed("Orchestrator.addTask");
158
177
  const task = {
159
178
  id: generateId("task"),
160
179
  description,
@@ -222,12 +241,14 @@ export class Orchestrator extends EventEmitter {
222
241
  * @param {number} intervalMs - Poll interval (default 600_000 = 10 min)
223
242
  */
224
243
  startCronWatch(intervalMs = 600_000) {
244
+ assertCLILegacyMutationAllowed("Orchestrator.startCronWatch");
225
245
  if (this._cronTimer) return;
226
246
  this._log(`Cron watch started (every ${Math.round(intervalMs / 60_000)}m)`);
227
247
  this._cronTimer = setInterval(() => this._cronTick(), intervalMs);
228
248
  }
229
249
 
230
250
  stopCronWatch() {
251
+ assertCLILegacyMutationAllowed("Orchestrator.stopCronWatch");
231
252
  if (this._cronTimer) {
232
253
  clearInterval(this._cronTimer);
233
254
  this._cronTimer = null;
@@ -237,6 +258,7 @@ export class Orchestrator extends EventEmitter {
237
258
  // ─── Orchestration pipeline ──────────────────────────────────────
238
259
 
239
260
  async _orchestrate(task) {
261
+ assertCLILegacyMutationAllowed("Orchestrator._orchestrate");
240
262
  try {
241
263
  // Step 1: Decompose
242
264
  task.subtasks = await this._decompose(task);
@@ -264,6 +286,7 @@ export class Orchestrator extends EventEmitter {
264
286
 
265
287
  /** LLM-driven task decomposition into coding subtasks. */
266
288
  async _decompose(task) {
289
+ assertCLILegacyMutationAllowed("Orchestrator._decompose");
267
290
  task.status = TASK_STATUS.DECOMPOSING;
268
291
  this.emit("task:decomposing", task);
269
292
 
@@ -306,6 +329,7 @@ export class Orchestrator extends EventEmitter {
306
329
 
307
330
  /** Dispatch subtasks to the Claude Code pool. */
308
331
  async _dispatch(task) {
332
+ assertCLILegacyMutationAllowed("Orchestrator._dispatch");
309
333
  this.emit("agents:dispatched", { task, count: task.subtasks.length });
310
334
  this._log(
311
335
  `Dispatching ${task.subtasks.length} subtask(s) to ${this._router.summary().length} agent backend(s)`,
@@ -320,6 +344,7 @@ export class Orchestrator extends EventEmitter {
320
344
 
321
345
  /** Run CI command and retry loop. */
322
346
  async _ciLoop(task) {
347
+ assertCLILegacyMutationAllowed("Orchestrator._ciLoop");
323
348
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
324
349
  task.status = TASK_STATUS.CI_CHECKING;
325
350
  this.emit("ci:checking", { task, attempt });
@@ -398,6 +423,7 @@ export class Orchestrator extends EventEmitter {
398
423
 
399
424
  /** Execute CI command and parse results. */
400
425
  _runCI(cwd) {
426
+ assertCLILegacyMutationAllowed("Orchestrator._runCI");
401
427
  try {
402
428
  const output = _deps.execSync(this.ciCommand, {
403
429
  cwd,
@@ -465,6 +491,7 @@ export class Orchestrator extends EventEmitter {
465
491
  * the caller has already seen via task:complete / task:failed events.
466
492
  */
467
493
  _pruneTasks() {
494
+ assertCLILegacyMutationAllowed("Orchestrator._pruneTasks");
468
495
  if (this._tasks.size <= this.maxTasks) return;
469
496
  for (const [id, t] of this._tasks) {
470
497
  if (this._tasks.size <= this.maxTasks) break;
@@ -478,6 +505,7 @@ export class Orchestrator extends EventEmitter {
478
505
  }
479
506
 
480
507
  async _cronTick() {
508
+ assertCLILegacyMutationAllowed("Orchestrator._cronTick");
481
509
  this.emit("cron:tick", { at: new Date().toISOString() });
482
510
  // Override this method or listen to the event to add input source polling
483
511
  }
@@ -0,0 +1,512 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import {
3
+ compileGraphDefinition,
4
+ graphDigest,
5
+ } from "../graph-kernel/compiler.js";
6
+ import { createGraphAuthorityBinding } from "../graph-kernel/authority.js";
7
+ import { createRuntimeGraphCutoverAuthorityResolver } from "../graph-kernel/cutover-authority-resolver.js";
8
+ import { GraphEventStore } from "../graph-kernel/event-store.js";
9
+ import { GraphKernel } from "../graph-kernel/runtime.js";
10
+
11
+ function graphError(code, message, details = {}) {
12
+ const error = new Error(message);
13
+ error.name = "SchedulerGraphAuthorityError";
14
+ error.code = code;
15
+ Object.assign(error, details);
16
+ return error;
17
+ }
18
+
19
+ function id(value, prefix) {
20
+ const text = String(value || "").trim();
21
+ if (/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$/u.test(text)) return text;
22
+ return `${prefix}-${createHash("sha256")
23
+ .update(text, "utf8")
24
+ .digest("hex")
25
+ .slice(0, 32)}`;
26
+ }
27
+
28
+ function definitionFor(context) {
29
+ const { occurrence, job } = context;
30
+ const maxAttempts = Math.max(
31
+ 1,
32
+ Number(job.retryPolicy?.maxAttempts ?? job.maxAttempts) || 3,
33
+ );
34
+ return compileGraphDefinition({
35
+ schemaVersion: 1,
36
+ id: id(`scheduler:${job.kind}:${job.id}`, "scheduler-graph"),
37
+ revision: Math.max(1, Number(job.revision) || 1),
38
+ nodes: [
39
+ {
40
+ id: "dispatch",
41
+ kind: "task",
42
+ dependsOn: [],
43
+ inputs: [],
44
+ outputs: [],
45
+ effectClass: "external",
46
+ idempotencyKey: `scheduler:${occurrence.id}:${occurrence.jobRevision}`,
47
+ retryLimit: Math.max(0, maxAttempts - 1),
48
+ },
49
+ ],
50
+ edges: [],
51
+ loops: [],
52
+ subgraphCalls: [],
53
+ budget: { turns: maxAttempts },
54
+ allowedCapabilities: [],
55
+ metadata: {
56
+ originSurface: "scheduler",
57
+ occurrenceId: occurrence.id,
58
+ jobRevision: occurrence.jobRevision,
59
+ jobKind: job.kind,
60
+ },
61
+ });
62
+ }
63
+
64
+ export function schedulerGraphAuthorityMode(env = process.env) {
65
+ const value = String(env.CHAINLESSCHAIN_GRAPH_SCHEDULER || "legacy")
66
+ .trim()
67
+ .toLowerCase();
68
+ if (!["legacy", "shadow", "canonical"].includes(value)) {
69
+ throw graphError(
70
+ "CC_GRAPH_AUTHORITY_MODE_INVALID",
71
+ "CHAINLESSCHAIN_GRAPH_SCHEDULER must be legacy, shadow, or canonical",
72
+ );
73
+ }
74
+ return value;
75
+ }
76
+
77
+ export class SchedulerOccurrenceGraphAuthority {
78
+ constructor({
79
+ mode = undefined,
80
+ authorityResolver = undefined,
81
+ optIn = false,
82
+ eventStore = new GraphEventStore(),
83
+ now = Date.now,
84
+ createId = randomUUID,
85
+ writerLeaseTtlMs = 24 * 60 * 60 * 1000,
86
+ } = {}) {
87
+ mode = mode === undefined ? schedulerGraphAuthorityMode() : mode;
88
+ if (!["legacy", "shadow", "canonical"].includes(mode)) {
89
+ throw graphError(
90
+ "CC_GRAPH_AUTHORITY_MODE_INVALID",
91
+ "scheduler Graph authority mode is invalid",
92
+ );
93
+ }
94
+ this.mode = mode;
95
+ this.authorityResolver =
96
+ authorityResolver ||
97
+ createRuntimeGraphCutoverAuthorityResolver({
98
+ surface: "scheduler",
99
+ entryId: "cli-scheduler",
100
+ fallbackMode: mode,
101
+ });
102
+ this.optIn = optIn === true;
103
+ this.eventStore = eventStore;
104
+ this.resultStore = eventStore.rolloutStore;
105
+ this.now = now;
106
+ this.createId = createId;
107
+ this.writerLeaseTtlMs = writerLeaseTtlMs;
108
+ this.active = new Map();
109
+ this.comparisons = new Map();
110
+ }
111
+
112
+ _modeFor(runKey) {
113
+ const resolved =
114
+ typeof this.authorityResolver === "function"
115
+ ? this.authorityResolver({ runKey, optIn: this.optIn })
116
+ : this.authorityResolver.resolve({ runKey, optIn: this.optIn });
117
+ const mode = typeof resolved === "string" ? resolved : resolved?.mode;
118
+ if (!["legacy", "shadow", "canonical"].includes(mode)) {
119
+ throw graphError(
120
+ "CC_GRAPH_AUTHORITY_MODE_INVALID",
121
+ "scheduler Graph authority resolver returned an invalid mode",
122
+ );
123
+ }
124
+ return mode;
125
+ }
126
+
127
+ runtimeClaims() {
128
+ return Object.freeze({
129
+ originSurface: "scheduler",
130
+ surface: "scheduler",
131
+ execution: "real",
132
+ persistence: "durable",
133
+ isolated: true,
134
+ terminalEvidence: true,
135
+ authorityModes: Object.freeze(["shadow", "canonical"]),
136
+ featureGated: true,
137
+ });
138
+ }
139
+
140
+ _resultThread(runId) {
141
+ return `scheduler-result:${createHash("sha256")
142
+ .update(runId, "utf8")
143
+ .digest("hex")}`;
144
+ }
145
+
146
+ _resultReceipt(runId, { allowMissing = false } = {}) {
147
+ let events;
148
+ try {
149
+ events = this.resultStore.read(this._resultThread(runId));
150
+ } catch (error) {
151
+ if (allowMissing && error?.code === "CC_ROLLOUT_THREAD_NOT_FOUND") {
152
+ return null;
153
+ }
154
+ throw graphError(
155
+ "CC_SCHEDULER_GRAPH_RECEIPT_MISSING",
156
+ "scheduler Graph result receipt is missing",
157
+ { cause: error },
158
+ );
159
+ }
160
+ const receipt = [...events]
161
+ .reverse()
162
+ .find((event) => event.event_type === "scheduler.result.committed");
163
+ if (
164
+ !receipt ||
165
+ graphDigest(receipt.payload?.record, "cc.scheduler.adapter-result/v1") !==
166
+ receipt.payload?.outputDigest
167
+ ) {
168
+ throw graphError(
169
+ "CC_SCHEDULER_GRAPH_RECEIPT_FORGED",
170
+ "scheduler Graph result receipt is corrupt or forged",
171
+ );
172
+ }
173
+ return Object.freeze({
174
+ record: receipt.payload.record,
175
+ outputDigest: receipt.payload.outputDigest,
176
+ receiptDigest: receipt.hash,
177
+ });
178
+ }
179
+
180
+ _kernel(runId, generation, authoritySource) {
181
+ const writerId = id(
182
+ `scheduler:${runId}:writer:${process.pid}:${generation}`,
183
+ "scheduler-writer",
184
+ );
185
+ const writerLeaseId = id(
186
+ `scheduler:${runId}:lease:${this.createId()}`,
187
+ "scheduler-lease",
188
+ );
189
+ return {
190
+ kernel: new GraphKernel({
191
+ eventStore: this.eventStore,
192
+ now: this.now,
193
+ writerId,
194
+ writerLeaseId,
195
+ authoritySource,
196
+ authorityGeneration: generation,
197
+ writerLeaseTtlMs: this.writerLeaseTtlMs,
198
+ }),
199
+ writerId,
200
+ writerLeaseId,
201
+ };
202
+ }
203
+
204
+ begin(context) {
205
+ const runId = id(`scheduler:${context.occurrence.id}`, "scheduler-run");
206
+ const compiled = definitionFor(context);
207
+ let events = [];
208
+ try {
209
+ events = this.eventStore.read(runId);
210
+ } catch (error) {
211
+ if (error?.code !== "CC_ROLLOUT_THREAD_NOT_FOUND") throw error;
212
+ }
213
+ const previous = [...events]
214
+ .reverse()
215
+ .find((event) => event.payload?.state?.authority)?.payload
216
+ .state.authority;
217
+ const mode = previous?.authorityMode || this._modeFor(runId);
218
+ if (mode === "legacy") return null;
219
+ const generation = previous ? Number(previous.authorityGeneration) + 1 : 1;
220
+ const source = mode === "shadow" ? "graph_kernel_shadow" : "graph_kernel";
221
+ const holder = this._kernel(runId, generation, source);
222
+ let projection;
223
+ if (!events.length) {
224
+ projection = holder.kernel.startRun(compiled, {
225
+ runId,
226
+ originSurface: "scheduler",
227
+ occurrenceRef: {
228
+ jobRevision: String(context.occurrence.jobRevision),
229
+ occurrenceId: String(context.occurrence.id),
230
+ idempotencyKey: String(
231
+ context.occurrence.idempotencyKey || context.occurrence.id,
232
+ ),
233
+ },
234
+ });
235
+ } else {
236
+ const latest = events.at(-1);
237
+ projection = holder.kernel.recoverRun(runId, {
238
+ authority: createGraphAuthorityBinding({
239
+ ...previous,
240
+ logicalRunId: runId,
241
+ originSurface: "scheduler",
242
+ authorityMode: mode,
243
+ authoritySource: source,
244
+ authorityGeneration: generation,
245
+ writerId: holder.writerId,
246
+ writerLeaseId: holder.writerLeaseId,
247
+ writerLeaseExpiresAt: new Date(
248
+ this.now() + this.writerLeaseTtlMs,
249
+ ).toISOString(),
250
+ eventHead: latest.hash,
251
+ }),
252
+ });
253
+ if (projection.revisionDigest !== compiled.revisionDigest) {
254
+ throw graphError(
255
+ "CC_GRAPH_OCCURRENCE_CONFLICT",
256
+ "scheduler occurrence Graph revision changed during recovery",
257
+ );
258
+ }
259
+ }
260
+ if (projection.status === "succeeded") {
261
+ const accepted = projection.attempts.find(
262
+ (attempt) => attempt.status === "accepted",
263
+ );
264
+ const outputDigest = accepted?.terminalEvidence?.outputDigest;
265
+ const receipt = this._resultReceipt(runId);
266
+ if (!outputDigest || receipt.outputDigest !== outputDigest) {
267
+ throw graphError(
268
+ "CC_SCHEDULER_GRAPH_RECEIPT_FORGED",
269
+ "scheduler Graph terminal evidence does not match its result receipt",
270
+ );
271
+ }
272
+ if (mode === "shadow") {
273
+ this.comparisons.set(context.occurrence.id, {
274
+ authorityMode: mode,
275
+ outputDigest,
276
+ projection,
277
+ });
278
+ }
279
+ return Object.freeze({
280
+ runId,
281
+ authorityMode: mode,
282
+ alreadySettled: mode === "canonical",
283
+ projection,
284
+ result: receipt.record,
285
+ });
286
+ }
287
+ if (projection.status === "reconciliation_required") {
288
+ const receipt = this._resultReceipt(runId, { allowMissing: true });
289
+ if (!receipt || projection.reconciliationEffectIds.length !== 1) {
290
+ throw graphError(
291
+ "CC_GRAPH_RECONCILIATION_REQUIRED",
292
+ "scheduler occurrence has an unknown effect requiring adjudication",
293
+ { graphRunId: runId },
294
+ );
295
+ }
296
+ holder.kernel.reconcileEffect(runId, {
297
+ effectId: projection.reconciliationEffectIds[0],
298
+ decision: "committed",
299
+ receipt: { receiptDigest: receipt.receiptDigest },
300
+ auditDecisionId: `scheduler-result-receipt:${receipt.outputDigest.slice(
301
+ 7,
302
+ 39,
303
+ )}`,
304
+ });
305
+ projection = holder.kernel.getRun(runId);
306
+ }
307
+ const durableResult = this._resultReceipt(runId, { allowMissing: true });
308
+ const recoverableAttempt = projection.attempts.find(
309
+ (attempt) => attempt.nodeId === "dispatch" && attempt.status === "active",
310
+ );
311
+ if (durableResult && recoverableAttempt) {
312
+ const settlementAttempt =
313
+ recoverableAttempt.authorityGeneration ===
314
+ projection.authorityGeneration &&
315
+ recoverableAttempt.writerId === projection.writerId
316
+ ? recoverableAttempt
317
+ : holder.kernel.resumeAttempt(runId, recoverableAttempt.id, {
318
+ resumedAttemptId: `scheduler-recovery-attempt:${this.createId()}`,
319
+ leaseId: `scheduler-recovery-lease:${this.createId()}`,
320
+ ttlMs: this.writerLeaseTtlMs,
321
+ reason:
322
+ "durable Scheduler result recovered after writer takeover",
323
+ });
324
+ holder.kernel.settleAttempt(runId, {
325
+ attemptId: settlementAttempt.id,
326
+ leaseId: settlementAttempt.leaseId,
327
+ fence: settlementAttempt.fence,
328
+ outcome: "succeeded",
329
+ evidence: { outputDigest: durableResult.outputDigest },
330
+ usage: { turns: 1 },
331
+ });
332
+ projection = holder.kernel.getRun(runId);
333
+ if (mode === "shadow") {
334
+ this.comparisons.set(context.occurrence.id, {
335
+ authorityMode: mode,
336
+ outputDigest: durableResult.outputDigest,
337
+ projection,
338
+ });
339
+ }
340
+ return Object.freeze({
341
+ runId,
342
+ authorityMode: mode,
343
+ alreadySettled: mode === "canonical",
344
+ projection,
345
+ result: durableResult.record,
346
+ });
347
+ }
348
+ if (
349
+ ["failed", "cancelled", "blocked", "deadlocked"].includes(
350
+ projection.status,
351
+ )
352
+ ) {
353
+ throw graphError(
354
+ "CC_GRAPH_RUN_TERMINAL",
355
+ `scheduler occurrence Graph is terminal: ${projection.status}`,
356
+ );
357
+ }
358
+ if (projection.phase === "open") {
359
+ holder.kernel.registerAgent(runId, {
360
+ agentId: "scheduler-adapter",
361
+ capacity: 1,
362
+ resident: true,
363
+ });
364
+ holder.kernel.sealRun(runId);
365
+ }
366
+ const attempt = holder.kernel.assignNode(
367
+ runId,
368
+ "dispatch",
369
+ "scheduler-adapter",
370
+ {
371
+ ttlMs: this.writerLeaseTtlMs,
372
+ leaseId: id(
373
+ `scheduler-attempt:${context.occurrence.id}:${context.occurrence.fence}`,
374
+ "scheduler-attempt-lease",
375
+ ),
376
+ grant: {
377
+ schedulerOwnerId: context.occurrence.ownerId || null,
378
+ schedulerFence: context.occurrence.fence,
379
+ schedulerAttempt: context.occurrence.attempt,
380
+ },
381
+ },
382
+ );
383
+ const effect = holder.kernel.beginEffect(runId, {
384
+ effectId: id(`scheduler-effect:${attempt.id}`, "scheduler-effect"),
385
+ attemptId: attempt.id,
386
+ leaseId: attempt.leaseId,
387
+ fence: attempt.fence,
388
+ idempotencyKey: attempt.effectIdempotencyKey,
389
+ operationDigest: graphDigest(
390
+ {
391
+ occurrenceId: context.occurrence.id,
392
+ jobRevision: context.occurrence.jobRevision,
393
+ authority: context.authority,
394
+ },
395
+ "cc.scheduler.graph-operation/v1",
396
+ ),
397
+ });
398
+ this.active.set(context.occurrence.id, {
399
+ runId,
400
+ authorityMode: mode,
401
+ ...holder,
402
+ attempt,
403
+ effect,
404
+ });
405
+ if (durableResult) {
406
+ const settled = this.settleSuccess(context, durableResult.record);
407
+ if (mode === "shadow") {
408
+ this.comparisons.set(context.occurrence.id, {
409
+ authorityMode: mode,
410
+ outputDigest: durableResult.outputDigest,
411
+ projection: settled,
412
+ });
413
+ }
414
+ return Object.freeze({
415
+ runId,
416
+ authorityMode: mode,
417
+ alreadySettled: mode === "canonical",
418
+ projection: settled,
419
+ result: durableResult.record,
420
+ });
421
+ }
422
+ return Object.freeze({
423
+ runId,
424
+ authorityMode: mode,
425
+ alreadySettled: false,
426
+ projection,
427
+ });
428
+ }
429
+
430
+ settleSuccess(context, result) {
431
+ const outputDigest = graphDigest(
432
+ result ?? null,
433
+ "cc.scheduler.adapter-result/v1",
434
+ );
435
+ const comparison = this.comparisons.get(context.occurrence.id);
436
+ if (comparison) {
437
+ this.comparisons.delete(context.occurrence.id);
438
+ if (comparison.outputDigest !== outputDigest) {
439
+ throw graphError(
440
+ "CC_SCHEDULER_GRAPH_SHADOW_DIVERGENCE",
441
+ "scheduler shadow result diverged from persisted Graph evidence",
442
+ );
443
+ }
444
+ return comparison.projection;
445
+ }
446
+ const active = this.active.get(context.occurrence.id);
447
+ if (!active) {
448
+ throw graphError(
449
+ "CC_GRAPH_ATTEMPT_MISSING",
450
+ "scheduler Graph attempt is not active",
451
+ );
452
+ }
453
+ const threadId = this._resultThread(active.runId);
454
+ this.resultStore.start({
455
+ threadId,
456
+ title: `Scheduler Graph result ${active.runId}`,
457
+ metadata: { kind: "scheduler_graph_result", graphRunId: active.runId },
458
+ });
459
+ const resultEvents = this.resultStore.read(threadId);
460
+ const receipt = this.resultStore.append({
461
+ threadId,
462
+ eventType: "scheduler.result.committed",
463
+ idempotencyKey: `scheduler-result:${active.runId}`,
464
+ payload: { outputDigest, record: result ?? null },
465
+ expectedRevision: resultEvents.at(-1)?.event_seq,
466
+ expectedHeadHash: resultEvents.at(-1)?.hash,
467
+ });
468
+ active.kernel.settleEffect(active.runId, {
469
+ effectId: active.effect.id,
470
+ attemptId: active.attempt.id,
471
+ leaseId: active.attempt.leaseId,
472
+ fence: active.attempt.fence,
473
+ outcome: "committed",
474
+ receipt: { receiptDigest: receipt.hash },
475
+ });
476
+ active.kernel.settleAttempt(active.runId, {
477
+ attemptId: active.attempt.id,
478
+ leaseId: active.attempt.leaseId,
479
+ fence: active.attempt.fence,
480
+ outcome: "succeeded",
481
+ evidence: { outputDigest },
482
+ usage: { turns: 1 },
483
+ });
484
+ this.active.delete(context.occurrence.id);
485
+ return active.kernel.getRun(active.runId);
486
+ }
487
+
488
+ settleFailure(context, error) {
489
+ const active = this.active.get(context.occurrence.id);
490
+ if (!active) return null;
491
+ const known = error?.outcomeKnown === true;
492
+ active.kernel.settleEffect(active.runId, {
493
+ effectId: active.effect.id,
494
+ attemptId: active.attempt.id,
495
+ leaseId: active.attempt.leaseId,
496
+ fence: active.attempt.fence,
497
+ outcome: known ? "failed" : "unknown",
498
+ });
499
+ if (known) {
500
+ active.kernel.settleAttempt(active.runId, {
501
+ attemptId: active.attempt.id,
502
+ leaseId: active.attempt.leaseId,
503
+ fence: active.attempt.fence,
504
+ outcome: "failed",
505
+ error: error?.message || String(error),
506
+ usage: { turns: 1 },
507
+ });
508
+ }
509
+ this.active.delete(context.occurrence.id);
510
+ return active.kernel.getRun(active.runId);
511
+ }
512
+ }