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
@@ -0,0 +1,754 @@
1
+ import { 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 { GraphEventStore } from "../graph-kernel/event-store.js";
8
+ import { GraphKernel } from "../graph-kernel/runtime.js";
9
+
10
+ const TERMINAL = new Set([
11
+ "succeeded",
12
+ "failed",
13
+ "partial",
14
+ "cancelled",
15
+ "blocked",
16
+ "deadlocked",
17
+ "budget_exhausted",
18
+ "compensated",
19
+ "compensation_failed",
20
+ ]);
21
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
22
+
23
+ function runtimeError(code, message, details = {}) {
24
+ const error = new Error(message);
25
+ error.name = "AppServerGraphRuntimeError";
26
+ error.code = code;
27
+ Object.assign(error, details);
28
+ return error;
29
+ }
30
+
31
+ function evidence(value) {
32
+ const source = value?.terminalEvidence || {};
33
+ const terminal = {};
34
+ if (DIGEST.test(String(source.outputDigest || ""))) {
35
+ terminal.outputDigest = source.outputDigest;
36
+ }
37
+ if (source.commit) terminal.commit = String(source.commit);
38
+ if (Array.isArray(source.artifactIds) && source.artifactIds.length) {
39
+ terminal.artifactIds = source.artifactIds.map(String);
40
+ }
41
+ if (Array.isArray(source.testReceiptIds) && source.testReceiptIds.length) {
42
+ terminal.testReceiptIds = source.testReceiptIds.map(String);
43
+ }
44
+ if (Object.keys(terminal).length === 0) {
45
+ throw runtimeError(
46
+ "CC_GRAPH_TERMINAL_EVIDENCE_REQUIRED",
47
+ "Graph node executor did not return immutable terminal evidence",
48
+ );
49
+ }
50
+ return terminal;
51
+ }
52
+
53
+ function usage(value) {
54
+ const source = value?.usage || {};
55
+ return {
56
+ turns: Math.max(0, Number(source.turns) || 1),
57
+ tokens: Math.max(
58
+ 0,
59
+ Number(source.tokens) ||
60
+ Number(source.input_tokens || 0) + Number(source.output_tokens || 0),
61
+ ),
62
+ costUsd: Math.max(0, Number(source.costUsd) || 0),
63
+ wallMs: Math.max(0, Number(source.wallMs) || 0),
64
+ };
65
+ }
66
+
67
+ function nodeInput(inputs, nodeId) {
68
+ const value = inputs?.[nodeId];
69
+ if (typeof value === "string") return { prompt: value };
70
+ if (value && typeof value === "object" && !Array.isArray(value)) {
71
+ return { ...value, prompt: String(value.prompt || value.input || "") };
72
+ }
73
+ return { prompt: "" };
74
+ }
75
+
76
+ /**
77
+ * Host-owned Graph executor used by fixed App Server capabilities. GraphKernel
78
+ * owns ready/attempt/effect/terminal state; the injected executor owns only a
79
+ * single real Agent turn and must return immutable evidence.
80
+ */
81
+ export class AppServerGraphRuntime {
82
+ constructor({
83
+ rolloutStore,
84
+ eventStore = rolloutStore
85
+ ? new GraphEventStore({ rolloutStore })
86
+ : new GraphEventStore(),
87
+ executeNode,
88
+ now = Date.now,
89
+ createId = randomUUID,
90
+ onEvent = null,
91
+ writerLeaseTtlMs = 24 * 60 * 60 * 1000,
92
+ } = {}) {
93
+ if (typeof executeNode !== "function") {
94
+ throw new TypeError("AppServerGraphRuntime requires executeNode()");
95
+ }
96
+ this.eventStore = eventStore;
97
+ this.rolloutStore = eventStore.rolloutStore;
98
+ this.executeNode = executeNode;
99
+ this.now = now;
100
+ this.createId = createId;
101
+ this.onEvent = typeof onEvent === "function" ? onEvent : null;
102
+ this.writerLeaseTtlMs = writerLeaseTtlMs;
103
+ this.runs = new Map();
104
+ this.drives = new Map();
105
+ this.active = new Map();
106
+ }
107
+
108
+ _requestThread(runId) {
109
+ return `graph-request:${graphDigest(
110
+ runId,
111
+ "cc.app-server.graph-run-id/v1",
112
+ ).slice(7)}`;
113
+ }
114
+
115
+ _persistRequest(runId, request) {
116
+ const threadId = this._requestThread(runId);
117
+ this.rolloutStore.start({
118
+ threadId,
119
+ title: `Graph request ${runId}`,
120
+ metadata: { kind: "graph_run_request", graphRunId: runId },
121
+ });
122
+ const events = this.rolloutStore.read(threadId);
123
+ this.rolloutStore.append({
124
+ threadId,
125
+ eventType: "graph.request.committed",
126
+ idempotencyKey: `graph-request:${runId}`,
127
+ payload: request,
128
+ expectedRevision: events.at(-1)?.event_seq,
129
+ expectedHeadHash: events.at(-1)?.hash,
130
+ });
131
+ }
132
+
133
+ _readRequest(runId) {
134
+ let events;
135
+ try {
136
+ events = this.rolloutStore.read(this._requestThread(runId));
137
+ } catch (error) {
138
+ throw runtimeError(
139
+ "CC_GRAPH_REQUEST_RECEIPT_MISSING",
140
+ `Graph run has no durable request receipt: ${runId}`,
141
+ { cause: error },
142
+ );
143
+ }
144
+ const receipt = [...events]
145
+ .reverse()
146
+ .find((event) => event.event_type === "graph.request.committed");
147
+ if (!receipt?.payload?.definition || !receipt?.payload?.inputs) {
148
+ throw runtimeError(
149
+ "CC_GRAPH_REQUEST_RECEIPT_FORGED",
150
+ `Graph run request receipt is incomplete: ${runId}`,
151
+ );
152
+ }
153
+ return receipt.payload;
154
+ }
155
+
156
+ runtimeClaims() {
157
+ return Object.freeze({
158
+ originSurface: "desktop",
159
+ surface: "desktop",
160
+ execution: "real",
161
+ persistence: "durable",
162
+ isolated: true,
163
+ terminalEvidence: true,
164
+ authorityModes: Object.freeze(["shadow", "canonical"]),
165
+ featureGated: true,
166
+ });
167
+ }
168
+
169
+ _emit(runId, type, payload = {}) {
170
+ try {
171
+ this.onEvent?.({ type, runId, ...payload });
172
+ } catch {
173
+ // Observability never owns execution authority.
174
+ }
175
+ }
176
+
177
+ _newKernel({ runId, generation = 1, authoritySource = "graph_kernel" }) {
178
+ const writerId = `app-server:${runId}:writer:${process.pid}:${generation}`;
179
+ const writerLeaseId = `app-server:${runId}:lease:${this.createId()}`;
180
+ const kernel = new GraphKernel({
181
+ eventStore: this.eventStore,
182
+ now: this.now,
183
+ writerId,
184
+ writerLeaseId,
185
+ authoritySource,
186
+ authorityGeneration: generation,
187
+ writerLeaseTtlMs: this.writerLeaseTtlMs,
188
+ });
189
+ return { kernel, writerId, writerLeaseId, generation };
190
+ }
191
+
192
+ start({
193
+ definition,
194
+ runId = this.createId(),
195
+ inputs = {},
196
+ originSurface = "desktop",
197
+ agentCapacity = 1,
198
+ authorityMode = "canonical",
199
+ } = {}) {
200
+ if (!["shadow", "canonical"].includes(authorityMode)) {
201
+ throw runtimeError(
202
+ "CC_GRAPH_AUTHORITY_MODE_UNSUPPORTED",
203
+ "App Server Graph execution accepts shadow or canonical authority",
204
+ );
205
+ }
206
+ const compiled = compileGraphDefinition(definition);
207
+ const id = String(runId);
208
+ const request = {
209
+ definition: compiled.definition,
210
+ inputs: { ...inputs },
211
+ originSurface,
212
+ agentCapacity: Math.max(1, Number(agentCapacity) || 1),
213
+ authorityMode,
214
+ };
215
+ this._persistRequest(id, request);
216
+ if (this.runs.has(id)) {
217
+ const existing = this.runs.get(id);
218
+ if (existing.compiled.revisionDigest !== compiled.revisionDigest) {
219
+ throw runtimeError(
220
+ "CC_GRAPH_RUN_CONFLICT",
221
+ "Graph run id is already bound to another revision",
222
+ );
223
+ }
224
+ return this.status(id);
225
+ }
226
+ let persisted = [];
227
+ try {
228
+ persisted = this.eventStore.read(id);
229
+ } catch (error) {
230
+ if (error?.code !== "CC_ROLLOUT_THREAD_NOT_FOUND") throw error;
231
+ }
232
+ if (persisted.length) {
233
+ const recovered = this._recover(id);
234
+ const projection = recovered.kernel.getRun(id);
235
+ if (projection.revisionDigest !== compiled.revisionDigest) {
236
+ throw runtimeError(
237
+ "CC_GRAPH_RUN_CONFLICT",
238
+ "persisted Graph run is bound to another revision",
239
+ );
240
+ }
241
+ if (projection.authorityMode !== authorityMode) {
242
+ throw runtimeError(
243
+ "CC_GRAPH_MIGRATION_REQUIRED",
244
+ "persisted Graph run authority mode cannot change without a migration saga",
245
+ );
246
+ }
247
+ recovered.compiled = compiled;
248
+ recovered.inputs = { ...inputs };
249
+ return projection;
250
+ }
251
+ const holder = this._newKernel({
252
+ runId: id,
253
+ authoritySource:
254
+ authorityMode === "shadow" ? "graph_kernel_shadow" : "graph_kernel",
255
+ });
256
+ const projection = holder.kernel.startRun(compiled, {
257
+ runId: id,
258
+ originSurface,
259
+ });
260
+ holder.kernel.registerAgent(id, {
261
+ agentId: "app-server-agent",
262
+ capacity: Math.max(1, Number(agentCapacity) || 1),
263
+ resident: true,
264
+ });
265
+ holder.kernel.sealRun(id);
266
+ this.runs.set(id, {
267
+ ...holder,
268
+ runId: id,
269
+ compiled,
270
+ inputs: { ...inputs },
271
+ });
272
+ this._emit(id, "graph/run-started", { projection });
273
+ return this.status(id);
274
+ }
275
+
276
+ run(options = {}) {
277
+ const projection = this.start(options);
278
+ if (projection.authorityMode === "shadow") {
279
+ return Promise.resolve(this.status(projection.id));
280
+ }
281
+ const settled = this._drive(projection.id);
282
+ if (options.waitForCompletion === true) return settled;
283
+ return Promise.resolve(projection);
284
+ }
285
+
286
+ resume(runId, { waitForCompletion = false } = {}) {
287
+ const id = String(runId || "").trim();
288
+ if (!id) {
289
+ throw runtimeError(
290
+ "CC_GRAPH_RUN_ID_REQUIRED",
291
+ "Graph resume requires a durable run id",
292
+ );
293
+ }
294
+ const request = this._readRequest(id);
295
+ return this.run({
296
+ ...request,
297
+ runId: id,
298
+ waitForCompletion: waitForCompletion === true,
299
+ });
300
+ }
301
+
302
+ _drive(runId) {
303
+ if (this.drives.has(runId)) return this.drives.get(runId);
304
+ const drive = this._driveLoop(runId).finally(() => {
305
+ this.drives.delete(runId);
306
+ });
307
+ drive.catch(() => {});
308
+ this.drives.set(runId, drive);
309
+ return drive;
310
+ }
311
+
312
+ async _driveLoop(runId) {
313
+ const entry = this.runs.get(runId);
314
+ if (!entry)
315
+ throw runtimeError("CC_GRAPH_RUN_NOT_FOUND", "Graph run missing");
316
+ const { kernel } = entry;
317
+ for (let steps = 0; steps < 10_000; steps += 1) {
318
+ const status = kernel.getRun(runId);
319
+ if (
320
+ TERMINAL.has(status.status) ||
321
+ status.status === "reconciliation_required"
322
+ ) {
323
+ this._emit(runId, "graph/run-settled", { projection: status });
324
+ return status;
325
+ }
326
+ const next = kernel
327
+ .readyNodes(runId)
328
+ .find((candidate) => candidate.dispatch !== "subgraph");
329
+ if (!next) return status;
330
+ await this._executeAttempt(entry, next.nodeId);
331
+ }
332
+ throw runtimeError(
333
+ "CC_GRAPH_DRIVE_LIMIT",
334
+ "Graph executor exceeded its bounded scheduling step limit",
335
+ );
336
+ }
337
+
338
+ async _executeAttempt(entry, nodeId) {
339
+ const { kernel } = entry;
340
+ const runId = entry.runId;
341
+ const attempt = kernel.assignNode(runId, nodeId, "app-server-agent", {
342
+ ttlMs: this.writerLeaseTtlMs,
343
+ leaseId: `app-server-attempt:${this.createId()}`,
344
+ grant: { executor: "agent_kernel", originSurface: "desktop" },
345
+ });
346
+ let effect = null;
347
+ if (attempt.effectIdempotencyKey) {
348
+ effect = kernel.beginEffect(runId, {
349
+ effectId: `app-server-effect:${this.createId()}`,
350
+ attemptId: attempt.id,
351
+ leaseId: attempt.leaseId,
352
+ fence: attempt.fence,
353
+ idempotencyKey: attempt.effectIdempotencyKey,
354
+ operationDigest: graphDigest(
355
+ { runId, nodeId, input: nodeInput(entry.inputs, nodeId) },
356
+ "cc.app-server.graph-operation/v1",
357
+ ),
358
+ });
359
+ }
360
+ const controller = new AbortController();
361
+ let releaseActive;
362
+ const done = new Promise((resolve) => {
363
+ releaseActive = resolve;
364
+ });
365
+ this.active.set(attempt.id, { controller, done });
366
+ this._emit(runId, "graph/node-started", { nodeId, attemptId: attempt.id });
367
+ try {
368
+ const result = await this.executeNode({
369
+ runId,
370
+ nodeId,
371
+ attempt,
372
+ input: nodeInput(entry.inputs, nodeId),
373
+ signal: controller.signal,
374
+ });
375
+ if (!result || !["succeeded", "completed"].includes(result.status)) {
376
+ const error = runtimeError(
377
+ "CC_GRAPH_EXECUTOR_FAILED",
378
+ result?.error || "Graph node executor did not succeed",
379
+ );
380
+ error.outcomeKnown = result?.outcomeKnown === true;
381
+ throw error;
382
+ }
383
+ const receipt = graphExecutorReceipt(result);
384
+ if (controller.signal.aborted) return kernel.getRun(runId);
385
+ if (effect) {
386
+ kernel.settleEffect(runId, {
387
+ effectId: effect.id,
388
+ attemptId: attempt.id,
389
+ leaseId: attempt.leaseId,
390
+ fence: attempt.fence,
391
+ outcome: "committed",
392
+ receipt: { receiptDigest: receipt.receiptDigest },
393
+ });
394
+ }
395
+ const settled = kernel.settleAttempt(runId, {
396
+ attemptId: attempt.id,
397
+ leaseId: attempt.leaseId,
398
+ fence: attempt.fence,
399
+ outcome: "succeeded",
400
+ evidence: receipt.terminalEvidence,
401
+ usage: receipt.usage,
402
+ });
403
+ this._emit(runId, "graph/node-settled", {
404
+ nodeId,
405
+ attemptId: attempt.id,
406
+ outcome: "succeeded",
407
+ });
408
+ return settled;
409
+ } catch (error) {
410
+ if (controller.signal.aborted) return kernel.getRun(runId);
411
+ if (effect) {
412
+ const known = error?.outcomeKnown === true;
413
+ kernel.settleEffect(runId, {
414
+ effectId: effect.id,
415
+ attemptId: attempt.id,
416
+ leaseId: attempt.leaseId,
417
+ fence: attempt.fence,
418
+ outcome: known ? "failed" : "unknown",
419
+ });
420
+ if (!known) {
421
+ this._emit(runId, "graph/node-reconciliation-required", {
422
+ nodeId,
423
+ attemptId: attempt.id,
424
+ error: error?.message || String(error),
425
+ });
426
+ return kernel.getRun(runId);
427
+ }
428
+ }
429
+ const settled = kernel.settleAttempt(runId, {
430
+ attemptId: attempt.id,
431
+ leaseId: attempt.leaseId,
432
+ fence: attempt.fence,
433
+ outcome: "failed",
434
+ error: error?.message || String(error),
435
+ });
436
+ this._emit(runId, "graph/node-settled", {
437
+ nodeId,
438
+ attemptId: attempt.id,
439
+ outcome: "failed",
440
+ });
441
+ return settled;
442
+ } finally {
443
+ this.active.delete(attempt.id);
444
+ releaseActive();
445
+ }
446
+ }
447
+
448
+ status(runId) {
449
+ const id = String(runId);
450
+ const entry = this.runs.get(id) || this._recover(id);
451
+ return entry.kernel.getRun(id);
452
+ }
453
+
454
+ _recover(runId) {
455
+ let events;
456
+ try {
457
+ events = this.eventStore.read(runId);
458
+ } catch (error) {
459
+ throw runtimeError(
460
+ "CC_GRAPH_RUN_NOT_FOUND",
461
+ `Graph run was not found: ${runId}`,
462
+ { cause: error },
463
+ );
464
+ }
465
+ const latest = events.at(-1);
466
+ const previous = [...events]
467
+ .reverse()
468
+ .find((event) => event.payload?.state?.authority)?.payload
469
+ .state.authority;
470
+ if (!previous || !latest) {
471
+ throw runtimeError(
472
+ "CC_GRAPH_RECOVERY_UNAVAILABLE",
473
+ `Graph run has no authority snapshot: ${runId}`,
474
+ );
475
+ }
476
+ const generation = Number(previous.authorityGeneration) + 1;
477
+ const authoritySource =
478
+ previous.authorityMode === "shadow"
479
+ ? "graph_kernel_shadow"
480
+ : "graph_kernel";
481
+ const holder = this._newKernel({
482
+ runId,
483
+ generation,
484
+ authoritySource,
485
+ });
486
+ const authority = createGraphAuthorityBinding({
487
+ ...previous,
488
+ authorityMode: previous.authorityMode,
489
+ authoritySource,
490
+ authorityGeneration: generation,
491
+ writerId: holder.writerId,
492
+ writerLeaseId: holder.writerLeaseId,
493
+ writerLeaseExpiresAt: new Date(
494
+ this.now() + this.writerLeaseTtlMs,
495
+ ).toISOString(),
496
+ eventHead: latest.hash,
497
+ });
498
+ holder.kernel.recoverRun(runId, { authority });
499
+ const request = this._readRequest(runId);
500
+ const entry = {
501
+ ...holder,
502
+ runId,
503
+ compiled: compileGraphDefinition(request.definition),
504
+ inputs: { ...request.inputs },
505
+ };
506
+ this.runs.set(runId, entry);
507
+ this._recoverReceiptedAttempts(entry);
508
+ return entry;
509
+ }
510
+
511
+ _executorReceipts(runId) {
512
+ let events;
513
+ try {
514
+ events = this.rolloutStore.read(`graph-executor:${runId}`);
515
+ } catch (error) {
516
+ if (error?.code === "CC_ROLLOUT_THREAD_NOT_FOUND") return new Map();
517
+ throw error;
518
+ }
519
+ const receipts = new Map();
520
+ for (const event of events) {
521
+ if (!event.event_type.startsWith("executor.")) continue;
522
+ const payload = event.payload || {};
523
+ if (
524
+ payload.runId !== runId ||
525
+ typeof payload.attemptId !== "string" ||
526
+ !["executor.succeeded", "executor.failed"].includes(event.event_type)
527
+ ) {
528
+ throw runtimeError(
529
+ "CC_GRAPH_EXECUTOR_RECEIPT_FORGED",
530
+ "Graph executor receipt does not match its run and attempt",
531
+ );
532
+ }
533
+ const status =
534
+ event.event_type === "executor.succeeded" ? "succeeded" : "failed";
535
+ if (
536
+ status === "succeeded" &&
537
+ !DIGEST.test(String(payload.outputDigest || ""))
538
+ ) {
539
+ throw runtimeError(
540
+ "CC_GRAPH_EXECUTOR_RECEIPT_FORGED",
541
+ "successful Graph executor receipt has no immutable output digest",
542
+ );
543
+ }
544
+ receipts.set(payload.attemptId, {
545
+ status,
546
+ nodeId: payload.nodeId,
547
+ outputDigest: payload.outputDigest,
548
+ error: payload.error,
549
+ receiptDigest: event.hash,
550
+ });
551
+ }
552
+ return receipts;
553
+ }
554
+
555
+ _latestState(runId) {
556
+ const event = [...this.eventStore.read(runId)]
557
+ .reverse()
558
+ .find((candidate) => candidate.payload?.state?.version === 1);
559
+ if (!event) {
560
+ throw runtimeError(
561
+ "CC_GRAPH_RECOVERY_UNAVAILABLE",
562
+ `Graph run has no recoverable state: ${runId}`,
563
+ );
564
+ }
565
+ return event.payload.state;
566
+ }
567
+
568
+ _recoverReceiptedAttempts(entry) {
569
+ const { kernel, runId } = entry;
570
+ const receipts = this._executorReceipts(runId);
571
+ if (receipts.size === 0) return kernel.getRun(runId);
572
+
573
+ let state = this._latestState(runId);
574
+ const attempts = new Map(state.attempts || []);
575
+ const receiptForAttempt = (attempt) => {
576
+ const visited = new Set();
577
+ let current = attempt;
578
+ while (current && !visited.has(current.id)) {
579
+ visited.add(current.id);
580
+ const receipt = receipts.get(current.id);
581
+ if (receipt) return receipt;
582
+ current = current.resumedFromAttemptId
583
+ ? attempts.get(current.resumedFromAttemptId)
584
+ : null;
585
+ }
586
+ return null;
587
+ };
588
+ const effectsByAttempt = new Map();
589
+ for (const [, effect] of state.effects || []) {
590
+ const values = effectsByAttempt.get(effect.attemptId) || [];
591
+ values.push(effect);
592
+ effectsByAttempt.set(effect.attemptId, values);
593
+ }
594
+ for (const [, attempt] of state.attempts || []) {
595
+ if (attempt.status !== "active") continue;
596
+ const receipt = receiptForAttempt(attempt);
597
+ if (!receipt || receipt.nodeId !== attempt.nodeId) continue;
598
+ const effects = effectsByAttempt.get(attempt.id) || [];
599
+ const expectedEffectStatus =
600
+ receipt.status === "succeeded" ? "committed" : "failed";
601
+ if (effects.some((effect) => effect.status !== expectedEffectStatus)) {
602
+ continue;
603
+ }
604
+ const authority = kernel.getRun(runId);
605
+ const settledAttempt =
606
+ attempt.authorityGeneration === authority.authorityGeneration &&
607
+ attempt.writerId === authority.writerId
608
+ ? attempt
609
+ : kernel.resumeAttempt(runId, attempt.id, {
610
+ resumedAttemptId: `app-server-recovery-attempt:${this.createId()}`,
611
+ leaseId: `app-server-recovery-lease:${this.createId()}`,
612
+ ttlMs: this.writerLeaseTtlMs,
613
+ reason:
614
+ "immutable executor receipt recovered after writer takeover",
615
+ });
616
+ kernel.settleAttempt(runId, {
617
+ attemptId: settledAttempt.id,
618
+ leaseId: settledAttempt.leaseId,
619
+ fence: settledAttempt.fence,
620
+ outcome: receipt.status,
621
+ evidence:
622
+ receipt.status === "succeeded"
623
+ ? { outputDigest: receipt.outputDigest }
624
+ : null,
625
+ error: receipt.error,
626
+ usage: { turns: 1 },
627
+ });
628
+ }
629
+
630
+ let projection = kernel.getRun(runId);
631
+ if (projection.status !== "reconciliation_required") return projection;
632
+ state = this._latestState(runId);
633
+ const effects = new Map(state.effects || []);
634
+ for (const effectId of projection.reconciliationEffectIds) {
635
+ const effect = effects.get(effectId);
636
+ const receipt = effect ? receipts.get(effect.attemptId) : null;
637
+ if (!effect || !receipt || receipt.nodeId !== effect.nodeId) continue;
638
+ const succeeded = receipt.status === "succeeded";
639
+ kernel.reconcileEffect(runId, {
640
+ effectId,
641
+ decision: succeeded ? "committed" : "failed",
642
+ receipt: succeeded ? { receiptDigest: receipt.receiptDigest } : null,
643
+ auditDecisionId: `executor-receipt:${receipt.receiptDigest.slice(7, 39)}`,
644
+ });
645
+ const retry = kernel.assignNode(
646
+ runId,
647
+ effect.nodeId,
648
+ "app-server-agent",
649
+ {
650
+ ttlMs: this.writerLeaseTtlMs,
651
+ leaseId: `app-server-recovery-attempt:${this.createId()}`,
652
+ grant: { executor: "agent_kernel_receipt_recovery" },
653
+ },
654
+ );
655
+ if (effect.idempotencyKey) {
656
+ kernel.beginEffect(runId, {
657
+ effectId: `app-server-recovery-effect:${this.createId()}`,
658
+ attemptId: retry.id,
659
+ leaseId: retry.leaseId,
660
+ fence: retry.fence,
661
+ idempotencyKey: effect.idempotencyKey,
662
+ operationDigest: effect.operationDigest,
663
+ });
664
+ }
665
+ kernel.settleAttempt(runId, {
666
+ attemptId: retry.id,
667
+ leaseId: retry.leaseId,
668
+ fence: retry.fence,
669
+ outcome: receipt.status,
670
+ evidence: succeeded ? { outputDigest: receipt.outputDigest } : null,
671
+ error: receipt.error,
672
+ usage: { turns: 1 },
673
+ });
674
+ projection = kernel.getRun(runId);
675
+ }
676
+ return projection;
677
+ }
678
+
679
+ async cancel(runId, reason = "cancelled by App Server client") {
680
+ const id = String(runId);
681
+ const entry = this.runs.get(id) || this._recover(id);
682
+ return entry.kernel.cancelRun(id, {
683
+ reason,
684
+ interrupt: async (attempt) => {
685
+ const active = this.active.get(attempt.id);
686
+ if (!active) return;
687
+ active.controller.abort(runtimeError("CC_GRAPH_CANCELLED", reason));
688
+ await active.done;
689
+ },
690
+ });
691
+ }
692
+
693
+ async reconcile(runId, input = {}) {
694
+ const id = String(runId);
695
+ const entry = this.runs.get(id) || this._recover(id);
696
+ const effect = entry.kernel
697
+ .effectState(id)
698
+ .find((candidate) => candidate.id === input.effectId);
699
+ if (!effect) {
700
+ throw runtimeError(
701
+ "CC_GRAPH_EFFECT_NOT_FOUND",
702
+ `Graph reconciliation effect was not found: ${input.effectId}`,
703
+ );
704
+ }
705
+ const terminalEvidence =
706
+ input.decision === "committed"
707
+ ? evidence({ terminalEvidence: input.terminalEvidence })
708
+ : null;
709
+ entry.kernel.reconcileEffect(id, input);
710
+ if (input.decision === "committed") {
711
+ const attempt = entry.kernel.assignNode(
712
+ id,
713
+ effect.nodeId,
714
+ "app-server-agent",
715
+ {
716
+ ttlMs: this.writerLeaseTtlMs,
717
+ leaseId: `app-server-reconcile-attempt:${this.createId()}`,
718
+ grant: {
719
+ executor: "audited_reconciliation_receipt",
720
+ auditDecisionId: input.auditDecisionId,
721
+ },
722
+ },
723
+ );
724
+ entry.kernel.settleAttempt(id, {
725
+ attemptId: attempt.id,
726
+ leaseId: attempt.leaseId,
727
+ fence: attempt.fence,
728
+ outcome: "succeeded",
729
+ evidence: terminalEvidence,
730
+ usage: { turns: 1 },
731
+ });
732
+ const drive = this._drive(id);
733
+ return input.waitForCompletion === true
734
+ ? await drive
735
+ : entry.kernel.getRun(id);
736
+ }
737
+ const drive = this._drive(id);
738
+ return input.waitForCompletion === true
739
+ ? await drive
740
+ : entry.kernel.getRun(id);
741
+ }
742
+ }
743
+
744
+ export function graphExecutorReceipt(value) {
745
+ const terminal = evidence(value);
746
+ return Object.freeze({
747
+ terminalEvidence: terminal,
748
+ receiptDigest:
749
+ value?.terminalEvidence?.eventDigest ||
750
+ terminal.outputDigest ||
751
+ graphDigest(terminal, "cc.app-server.graph-executor-receipt/v1"),
752
+ usage: usage(value),
753
+ });
754
+ }