chainlesschain 0.165.10 → 0.166.1

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/completions/_cc +2 -1
  2. package/completions/cc.bash +2 -2
  3. package/completions/cc.fish +2 -2
  4. package/completions/cc.ps1 +2 -1
  5. package/package.json +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-DoxapYEM.js → AIOps-DwdhBUBc.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-DyiHvT2O.js → ActionButton-Dd1lBEeo.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-CAX06POB.js → Analytics-DuGuuI36.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-JXxcyn0R.js → AppLayout-CvHpSs3M.js} +5 -5
  10. package/src/assets/web-panel/assets/{Artifacts-40nZDb9N.js → Artifacts-BU9F3wJh.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-B_wc8Kcq.js → Audit-DK_n_WFm.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-CReWOiQY.js → BackgroundAgents-qKsxF5tv.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-sXrv9fE6.js → Backup-JS58pSyV.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-CHWmIERI.js → BaseInput-gGl6Ray1.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-DgQrMZCb.js → Chat-B2FZNq3U.js} +6 -6
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Clpgj0fi.js → ChatBubbleRenderer-CZS_bLAr.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-DmRwzt3e.js → Checkbox-tsI0TE22.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-tllAfrrc.js → Codegen-D5kqhfAr.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-CA_wqwEp.js → Col-DdN1TrqS.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-DQ_szKAv.js → Community-DgbEeh6V.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-CjkqX60k.js → Compact-FIm-fRB_.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-CfDNkDex.js → Compliance-B-N0pudf.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-PINc6CPv.js → Cowork-CuMafBpi.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-snYq4WCj.js → Cron-BTwzNFHR.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-CKR7he4B.js → Crosschain-DRoYbLOd.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-Bp5xJSbE.js → DID-CPhnNkz_.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-Dn-y6txl.js → Dashboard-DJQftix2.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-D0uEeunr.js → Dropdown-PSAH1Kfy.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-DIhjyeNw.js → EmailListRenderer-PVRqeMiZ.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D2Pv1Hnb.js → FamilyGuardDashboard-CYtnjqjl.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D6oSp4P4.js → Federation-_-53kTDz.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-s6bzlfQs.js → FormItemContext-DTQ4qGuE.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-B_NTgGP9.js → GenericCardRenderer-ON_NfX8k.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-Dk1lCoBr.js → Git-DUc3w_Bf.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-xOnLBQzd.js → Governance-CktsJ2ku.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-BFVHy-0I.js → Inference-4wUHQvju.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-BXzITB9_.js → KnowledgeGraph-Dq4saPnZ.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-BD2M4NPu.js → Logs-Btb50m5s.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-Cre8P8HG.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-awpllI_9.js → Marketplace-D3rSncxx.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-tL0IgbIX.js → McpTools-Bc6Mori_.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CrptLGSN.js → Memory-C-ottUdN.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-DZX-l_BS.js → MobileBridge-C0DITBmP.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-O6cr0Nal.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-dQ5-FjpQ.js → Mtc-B_MXKXvY.js} +6 -6
  46. package/src/assets/web-panel/assets/{MtcAudit-U0nDxDlG.js → MtcAudit-BDkUqWIT.js} +5 -5
  47. package/src/assets/web-panel/assets/{Multisig-D1PpAtiq.js → Multisig-BaxNWm8c.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-phZr6nyZ.js → NLProgramming-UD2GndZc.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-BPzSSUrX.js → Notes-pU7wtMwB.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-AypFEc7p.js → NotificationSettings-BIs6ULr3.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-S3k1qjT-.js → OrderTableRenderer-0NuumnfG.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-BvdQXFPR.js → Organization-C9o-n2lq.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-CUz_jbQC.js → Overflow-CEvMXxCS.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-C0xQ7H_2.js → P2P-C3gQMTK3.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DJKMjfB8.js → PdhVaultBrowser-D1LVpBOr.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-dkMtmDwK.js → Permissions-Dj5nIi0Y.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-CyHE7fnn.js → PersonalDataHub-uiLYuFcu.js} +6 -6
  58. package/src/assets/web-panel/assets/{Pipeline-_dU0Nwy3.js → Pipeline-CIrmF89x.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-fqLyg57f.js → Privacy-B3K1CUBa.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-COybCr5d.js → ProjectInit-C_wCZ0zW.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-B4DngMZW.js → ProjectSettings-iCitfuNJ.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-D0bMwUBm.js → Projects-BwimeXkW.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-Ba-7WNA8.js → Providers-BLpepgr6.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-X-I8dDMT.js → QrScannerModal-DPy8tjXV.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BCUP0a90.js → QuickAsk-CRq8VhID.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-DtFNmiQZ.js → Recommend-CirlWIiK.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-INR5CIAI.js → RemoteSession-nlnJlKXO.js} +3 -3
  68. package/src/assets/web-panel/assets/{Reputation-B6NfaCc6.js → Reputation-B5aaxee5.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-Dmz76txh.js → Row-lzsTQZlq.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-B7qyFCea.js → RssFeed-C41AzjgC.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-Bi6eS0oY.js → Search-1Hxx3TZ3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-D9_xim1L.js → Security-8VqwRxAp.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-PI1O-uYU.js → Services-DCm0HHAD.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-B8BrJnk8.js → Skeleton-D6w5gpmW.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-DvSm92dJ.js → Skills-Bw_pUTJB.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-BWyhCoRo.js → Sla-BkMj8Dxu.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-BL9H27jl.js → SpeechSettings-BOmLqW44.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-B7r--6yN.js → SyncSettings-2xKSqFDO.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-sc64p2Jt.js → Tasks-BPAnzVau.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-DEK55RVb.js → Templates-CcOGWgZz.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-DElr8R1l.js → Tenant-CAyzzQWN.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-BywaLBgz.js → Terminal-Daagerkm.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-B5NcgLyS.js → TimelineRenderer-1jGbMj7I.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-COFYqr6A.js → Tokens-CYQ-FQju.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-CfnVS3ij.js → Trigger-C70zRwuR.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-Bz94Gu5k.js → Trust-CeqXfiX_.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-Be10drSk.js → UkeySign-D0j6m1bU.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-CUB_cMem.js → VideoEditing-DFHpM7Yd.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-DxBJJuvG.js → Wallet-BVC2J0Yx.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-BZx5lwT8.js → WebAuthn-BceIN2Gn.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-B4sJikPT.js → WorkflowEditor-Bgeb-i-S.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-Wl-95AgM.js → chat-BmMBqgvz.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DUSwYVCg.js → colors-sjRzwnyw.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-DkKRDHcU.js → compact-item-DNt6m2bM.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-B5nAVC_Y.js → createContext-DELaLit3.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-Ct8o3bu_.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-rtotsRlA.js → hasIn-dfwk9O8x.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B_KDhTdt.js → index-1w7dha_a.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-C7kGJlSA.js → index-6bjBUhoH.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CN2LNCWW.js → index-B0wkOqE9.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CAtnIdx_.js → index-B4Z4HZcf.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-D7zQADRc.js → index-B7qiZc2Z.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DoBh4Ezg.js → index-BLbvXsxf.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-mwPG3TJQ.js → index-BMnvNNEd.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Ba8raWtd.js → index-BSB9Gin8.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CJWpTdCW.js → index-BXJ68ObJ.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DCCTgytM.js → index-Bs-mWOWt.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-D7Nx-jzS.js → index-BvIQ9sZa.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DUS7KK-i.js → index-BzddvOOb.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-X36Wyd1S.js → index-C2Sxf7yC.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-btxpIsXs.js → index-CAIn5cS9.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CskW4gDB.js → index-CLSqyAcE.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CUDraKtq.js → index-Cbu3-zFd.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Cv38Cwx0.js → index-Clrqtycd.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DupOVIEb.js → index-CpVt6M_8.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-yt994jkW.js → index-CtfYPnsY.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-JWQxvZ4x.js → index-CujMHspH.js} +1 -1
  118. package/src/assets/web-panel/assets/index-D685kO6L.js +1 -0
  119. package/src/assets/web-panel/assets/{index-Bj6mJ7tw.js → index-DC6FlHlP.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DQhlLyT6.js → index-DFOYbzg-.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DTlIRMqX.js +1 -0
  122. package/src/assets/web-panel/assets/{index-BMHNKa11.js → index-DV8q_Hki.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-C3lcOYkZ.js → index-DX3wwu3G.js} +3 -3
  124. package/src/assets/web-panel/assets/{index-CUqLWyY0.js → index-DY2G1Th2.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-cKc70R9h.js → index-DlYL8VP8.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-1J_Q-Ovw.js → index-DnQOc5wo.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CDWNrtvg.js → index-Du62m6pG.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-03w73yRM.js → index-LMfsEdLk.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-YANfaEyE.js → index-OC3qYV4-.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Dnbdqjxz.js → index-Rt-fym5b.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DfNeBiyO.js → index-WpEDoyTv.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-INU8TpRu.js → index-aj9ObF2R.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-CAdTY3kv.js → index-dAF9qRVa.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BxAMRZR0.js → index-dpDeFZNt.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CbqotoPt.js → index-fNwu9CU_.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-Ch5SqZaK.js → index-vCQ3l6DX.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-Ck8wTHsR.js → initDefaultProps-DUt9Xj8y.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-teBWI8ni.js → motion-DdiFPnv7.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-BdxzRStQ.js → move-BJ2VH7Y2.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DMpcDDsk.js → mtc-parser-BCnX6oOJ.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-BwkyHyWr.js → omit-CyHxlDLV.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-SlaxZUQd.js → pickAttrs-BJiGW3bY.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BlEZZ3cs.js → placementArrow-DhJ9Rhx8.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-Cl5uK6S5.js → responsiveObserve-C6zpL9bC.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-LlOJWbeE.js → slide-DCbMFRF-.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-DxbwIpQR.js → statusUtils-CNtVLsIq.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-G_P9gils.js → styleChecker-Z078OtUc.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-BDS7KDuK.js → useFlexGapSupport-w4RVmcGs.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-Xx3R_4Qk.js → useFs-D4Xw1XRt.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-ChOtRWax.js → usePersonalDataHub-Bnbd1PgY.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-CAUrMwRC.js → vnode-DSOQxMFN.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-Choqv7b5.js → zoom-DNPE1Wca.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +3 -3
  155. package/src/command-manifest.json +1 -1
  156. package/src/commands/agent.js +1 -1
  157. package/src/commands/graph.js +100 -0
  158. package/src/commands/orchestrate.js +85 -18
  159. package/src/commands/serve.js +39 -0
  160. package/src/commands/team.js +2 -0
  161. package/src/data/changelog.json +27 -1
  162. package/src/generated/cc-agent-protocol.schema.json +2013 -0
  163. package/src/lib/app-server/bounded-queue.js +87 -0
  164. package/src/lib/app-server/cli-agent-kernel-adapter.js +309 -0
  165. package/src/lib/app-server/protocol.js +125 -0
  166. package/src/lib/app-server/rollout-store.js +603 -0
  167. package/src/lib/app-server/server.js +922 -0
  168. package/src/lib/app-server/sqlite-rollout-store.js +315 -0
  169. package/src/lib/app-server/stdio-transport.js +118 -0
  170. package/src/lib/codex-app-server-adapter.js +249 -0
  171. package/src/lib/graph-kernel/adapters.js +238 -0
  172. package/src/lib/graph-kernel/compiler.js +1443 -0
  173. package/src/lib/graph-kernel/eval.js +207 -0
  174. package/src/lib/graph-kernel/event-store.js +101 -0
  175. package/src/lib/graph-kernel/index.js +7 -0
  176. package/src/lib/graph-kernel/runtime.js +3788 -0
  177. package/src/lib/graph-kernel/trace-reducer.js +409 -0
  178. package/src/lib/graph-kernel/trigger-adapter.js +183 -0
  179. package/src/lib/orchestrator.js +2 -1
  180. package/src/lib/record-replay/index.js +1 -0
  181. package/src/lib/record-replay/skill-recorder.js +386 -0
  182. package/src/lib/webhook-security.js +159 -0
  183. package/src/repl/agent-repl.js +5 -4
  184. package/src/repl/prompt-interactions.js +11 -1
  185. package/src/assets/web-panel/assets/MarkdownRenderer-CDSwkj7Y.js +0 -1
  186. package/src/assets/web-panel/assets/MobileProjects-krNyADYi.js +0 -1
  187. package/src/assets/web-panel/assets/devWarning-DFO12EfA.js +0 -1
  188. package/src/assets/web-panel/assets/index-DaDlUWea.js +0 -1
  189. package/src/assets/web-panel/assets/index-xn89TjWJ.js +0 -1
@@ -0,0 +1,409 @@
1
+ import { graphDigest } from "./compiler.js";
2
+
3
+ function clone(value) {
4
+ return value == null ? value : JSON.parse(JSON.stringify(value));
5
+ }
6
+
7
+ function latestState(events, throughSeq = Number.MAX_SAFE_INTEGER) {
8
+ return [...events]
9
+ .filter(
10
+ (event) =>
11
+ Number(event.seq) <= throughSeq && event.payload?.state?.version === 1,
12
+ )
13
+ .sort((left, right) => left.seq - right.seq)
14
+ .at(-1)?.payload?.state;
15
+ }
16
+
17
+ function mapFromEntries(entries) {
18
+ return new Map(entries || []);
19
+ }
20
+
21
+ function durationMs(attempt) {
22
+ const start = Date.parse(attempt.createdAt);
23
+ const end = Date.parse(attempt.updatedAt || attempt.createdAt);
24
+ return Math.max(0, end - start);
25
+ }
26
+
27
+ function criticalPath(definition, attempts) {
28
+ const compensationNodeIds = new Set(
29
+ [
30
+ ...definition.nodes.map((node) => node.compensationNodeId),
31
+ ...definition.edges
32
+ .filter((edge) => edge.kind === "compensation")
33
+ .map((edge) => edge.to),
34
+ ].filter((nodeId) => typeof nodeId === "string"),
35
+ );
36
+ const forwardNodes = definition.nodes.filter(
37
+ (node) => !compensationNodeIds.has(node.id),
38
+ );
39
+ const nodes = new Map(forwardNodes.map((node) => [node.id, node]));
40
+ const duration = new Map(
41
+ forwardNodes.map((node) => [
42
+ node.id,
43
+ [
44
+ ...attempts
45
+ .filter((attempt) => attempt.nodeId === node.id)
46
+ .reduce((iterations, attempt) => {
47
+ const key = JSON.stringify(attempt.iterationPath || []);
48
+ iterations.set(
49
+ key,
50
+ Math.max(iterations.get(key) || 0, durationMs(attempt)),
51
+ );
52
+ return iterations;
53
+ }, new Map())
54
+ .values(),
55
+ ].reduce((total, value) => total + value, 0),
56
+ ]),
57
+ );
58
+ const dependencies = new Map(
59
+ forwardNodes.map((node) => [
60
+ node.id,
61
+ new Set(node.dependsOn.filter((nodeId) => nodes.has(nodeId))),
62
+ ]),
63
+ );
64
+ for (const edge of definition.edges) {
65
+ if (
66
+ edge.kind !== "compensation" &&
67
+ nodes.has(edge.to) &&
68
+ nodes.has(edge.from)
69
+ ) {
70
+ dependencies.get(edge.to).add(edge.from);
71
+ }
72
+ }
73
+ const remaining = new Set(nodes.keys());
74
+ const order = [];
75
+ while (remaining.size) {
76
+ const ready = [...remaining]
77
+ .filter((id) =>
78
+ [...dependencies.get(id)].every((parent) => order.includes(parent)),
79
+ )
80
+ .sort();
81
+ if (!ready.length) break;
82
+ for (const id of ready) {
83
+ remaining.delete(id);
84
+ order.push(id);
85
+ }
86
+ }
87
+ const longest = new Map();
88
+ const predecessor = new Map();
89
+ for (const id of order) {
90
+ let bestParent = null;
91
+ let best = 0;
92
+ for (const parent of dependencies.get(id)) {
93
+ if ((longest.get(parent) || 0) > best) {
94
+ best = longest.get(parent) || 0;
95
+ bestParent = parent;
96
+ }
97
+ }
98
+ longest.set(id, best + (duration.get(id) || 0));
99
+ predecessor.set(id, bestParent);
100
+ }
101
+ const end = [...longest.entries()].sort(
102
+ (left, right) => right[1] - left[1] || left[0].localeCompare(right[0]),
103
+ )[0];
104
+ const path = [];
105
+ let cursor = end?.[0] || null;
106
+ while (cursor) {
107
+ path.unshift(cursor);
108
+ cursor = predecessor.get(cursor) || null;
109
+ }
110
+ return Object.freeze({
111
+ nodeIds: Object.freeze(path),
112
+ durationMs: end?.[1] || 0,
113
+ nodeDurations: Object.freeze(Object.fromEntries(duration)),
114
+ });
115
+ }
116
+
117
+ function redactState(state, includeContent) {
118
+ const output = clone(state);
119
+ if (includeContent) return output;
120
+ output.messages = (output.messages || []).map(([id, message]) => [
121
+ id,
122
+ {
123
+ ...message,
124
+ payload: undefined,
125
+ payloadRef: message.payloadDigest,
126
+ },
127
+ ]);
128
+ output.humanTasks = (output.humanTasks || []).map(([id, task]) => [
129
+ id,
130
+ {
131
+ ...task,
132
+ operation: undefined,
133
+ operationRef: task.operationDigest,
134
+ },
135
+ ]);
136
+ return output;
137
+ }
138
+
139
+ export function reduceGraphTrace(
140
+ events,
141
+ { throughSeq = Number.MAX_SAFE_INTEGER, includeContent = false } = {},
142
+ ) {
143
+ const ordered = [...events]
144
+ .filter((event) => Number(event.seq) <= throughSeq)
145
+ .sort((left, right) => left.seq - right.seq);
146
+ const rawState = latestState(ordered, throughSeq);
147
+ if (!rawState) {
148
+ const error = new Error("Graph trace contains no runtime state");
149
+ error.code = "CC_GRAPH_TRACE_STATE_MISSING";
150
+ throw error;
151
+ }
152
+ const state = redactState(rawState, includeContent);
153
+ const nodeStates = mapFromEntries(state.nodeStates);
154
+ const attempts = [...mapFromEntries(state.attempts).values()];
155
+ const artifacts = [...mapFromEntries(state.artifacts).values()];
156
+ const effects = [...mapFromEntries(state.effects).values()];
157
+ const messages = [...mapFromEntries(state.messages).values()];
158
+ const handoffs = [...mapFromEntries(state.handoffs).values()];
159
+ const humanTasks = [...mapFromEntries(state.humanTasks).values()];
160
+ const agents = [...mapFromEntries(state.agents).values()];
161
+ const loopStates = [...mapFromEntries(state.loopStates).values()].sort(
162
+ (left, right) => left.regionId.localeCompare(right.regionId),
163
+ );
164
+ const iterationFrames = [
165
+ ...mapFromEntries(state.iterationFrames).values(),
166
+ ].sort(
167
+ (left, right) =>
168
+ left.regionId.localeCompare(right.regionId) ||
169
+ left.iterationPath.join(".").localeCompare(right.iterationPath.join(".")),
170
+ );
171
+ const subgraphRuns = [...mapFromEntries(state.subgraphRuns).values()].sort(
172
+ (left, right) => left.nodeId.localeCompare(right.nodeId),
173
+ );
174
+ const definition = state.definition;
175
+ const compensationForNode = new Map([
176
+ ...definition.nodes
177
+ .filter((node) => node.compensationNodeId)
178
+ .map((node) => [node.compensationNodeId, node.id]),
179
+ ...definition.edges
180
+ .filter((edge) => edge.kind === "compensation")
181
+ .map((edge) => [edge.to, edge.from]),
182
+ ]);
183
+ const compensationByNode = new Map(
184
+ [...compensationForNode].map(([targetId, sourceId]) => [
185
+ sourceId,
186
+ targetId,
187
+ ]),
188
+ );
189
+ const taskNodes = definition.nodes.map((node) => ({
190
+ id: node.id,
191
+ kind: node.kind,
192
+ status: nodeStates.get(node.id)?.status || "unknown",
193
+ blockedRoot: nodeStates.get(node.id)?.blockedRoot || null,
194
+ acceptedAttemptId: nodeStates.get(node.id)?.acceptedAttemptId || null,
195
+ attemptIds: nodeStates.get(node.id)?.attemptIds || [],
196
+ iterationPath: nodeStates.get(node.id)?.iterationPath || [],
197
+ writeSet: node.writeSet || [],
198
+ workspaceIsolation: node.workspaceIsolation || null,
199
+ compensationNodeId:
200
+ node.compensationNodeId || compensationByNode.get(node.id) || null,
201
+ compensationForNodeId: compensationForNode.get(node.id) || null,
202
+ }));
203
+ const dependencyEdges = [
204
+ ...definition.nodes.flatMap((node) =>
205
+ node.dependsOn.map((parent) => ({
206
+ id: `dependency:${parent}:${node.id}`,
207
+ from: parent,
208
+ to: node.id,
209
+ kind: "control",
210
+ when: "success",
211
+ })),
212
+ ),
213
+ ...definition.edges,
214
+ ];
215
+ const compensationEdgeKeys = new Set(
216
+ dependencyEdges
217
+ .filter((edge) => edge.kind === "compensation")
218
+ .map((edge) => `${edge.from}\0${edge.to}`),
219
+ );
220
+ for (const node of definition.nodes) {
221
+ if (
222
+ !node.compensationNodeId ||
223
+ compensationEdgeKeys.has(`${node.id}\0${node.compensationNodeId}`)
224
+ ) {
225
+ continue;
226
+ }
227
+ dependencyEdges.push({
228
+ id: `compensation:${node.id}:${node.compensationNodeId}`,
229
+ from: node.id,
230
+ to: node.compensationNodeId,
231
+ kind: "compensation",
232
+ when: "always",
233
+ });
234
+ }
235
+ const artifactEdges = artifacts.flatMap((artifact) => [
236
+ {
237
+ from: artifact.producerNodeId,
238
+ to: artifact.id,
239
+ kind: "produced",
240
+ digest: artifact.digest,
241
+ },
242
+ ...(artifact.consumerNodeIds || []).map((consumer) => ({
243
+ from: artifact.id,
244
+ to: consumer,
245
+ kind: "consumed",
246
+ digest: artifact.digest,
247
+ })),
248
+ ]);
249
+ // A sender-side API return does not prove model-visible delivery. Only
250
+ // read/processed messages become delivery edges in the semantic trace.
251
+ const messageEdges = messages
252
+ .filter((message) => ["read", "processed"].includes(message.status))
253
+ .map((message) => ({
254
+ from: message.fromAttemptId,
255
+ to: `agent:${message.toAgentId}`,
256
+ kind: "model_visible_message",
257
+ messageId: message.id,
258
+ causationId: message.causationId,
259
+ correlationId: message.correlationId,
260
+ status: message.status,
261
+ }));
262
+ const agentTree = agents.map((agent) => ({
263
+ id: agent.id,
264
+ status: agent.status,
265
+ resident: agent.resident,
266
+ capacity: agent.capacity,
267
+ assignments: attempts
268
+ .filter((attempt) => attempt.agentId === agent.id)
269
+ .map((attempt) => attempt.id),
270
+ }));
271
+ const timeline = ordered.map((event) => ({
272
+ seq: event.seq,
273
+ timestamp: event.timestamp,
274
+ type: event.type,
275
+ hash: event.hash,
276
+ details: clone(event.payload?.details || null),
277
+ }));
278
+ const projection = {
279
+ schema: "chainlesschain.graph-trace-projection/v1",
280
+ runId: state.id,
281
+ throughSeq: ordered.at(-1)?.seq || 0,
282
+ eventHeadHash: ordered.at(-1)?.hash || null,
283
+ definitionId: definition.id,
284
+ graphRevision: state.graphRevision,
285
+ revisionDigest: state.revisionDigest,
286
+ phase: state.phase,
287
+ status: state.status,
288
+ compensation: clone(state.compensation || null),
289
+ agentTree,
290
+ taskGraph: { nodes: taskNodes, edges: dependencyEdges },
291
+ artifactGraph: { artifacts, edges: artifactEdges },
292
+ effects,
293
+ messageGraph: { messages, edges: messageEdges },
294
+ attempts,
295
+ handoffs,
296
+ humanTasks,
297
+ iterationGraph: {
298
+ loops: loopStates,
299
+ frames: iterationFrames,
300
+ attempts: attempts.map((attempt) => ({
301
+ id: attempt.id,
302
+ nodeId: attempt.nodeId,
303
+ iterationPath: attempt.iterationPath || [],
304
+ attempt: attempt.attempt || 1,
305
+ status: attempt.status,
306
+ })),
307
+ },
308
+ subgraphGraph: {
309
+ runs: subgraphRuns,
310
+ edges: subgraphRuns.map((relation) => ({
311
+ from: relation.nodeId,
312
+ to: `run:${relation.childRunId}`,
313
+ kind: "subgraph_call",
314
+ revisionDigest: relation.revisionDigest,
315
+ status: relation.status,
316
+ })),
317
+ },
318
+ criticalPath: criticalPath(definition, attempts),
319
+ timeline,
320
+ };
321
+ projection.projectionDigest = graphDigest(
322
+ projection,
323
+ "cc.graph.trace-projection/v1",
324
+ );
325
+ return Object.freeze(clone(projection));
326
+ }
327
+
328
+ export function timeTravelGraphTrace(events, throughSeq, options = {}) {
329
+ return reduceGraphTrace(events, { ...options, throughSeq });
330
+ }
331
+
332
+ export function diffGraphTrace(left, right) {
333
+ const leftNodes = new Map(
334
+ left.taskGraph.nodes.map((node) => [node.id, node]),
335
+ );
336
+ const rightNodes = new Map(
337
+ right.taskGraph.nodes.map((node) => [node.id, node]),
338
+ );
339
+ const nodeIds = [
340
+ ...new Set([...leftNodes.keys(), ...rightNodes.keys()]),
341
+ ].sort();
342
+ const nodes = nodeIds
343
+ .map((id) => {
344
+ const before = leftNodes.get(id) || null;
345
+ const after = rightNodes.get(id) || null;
346
+ if (JSON.stringify(before) === JSON.stringify(after)) return null;
347
+ return { id, before, after };
348
+ })
349
+ .filter(Boolean);
350
+ const leftArtifacts = new Map(
351
+ left.artifactGraph.artifacts.map((artifact) => [
352
+ artifact.id,
353
+ artifact.digest,
354
+ ]),
355
+ );
356
+ const rightArtifacts = new Map(
357
+ right.artifactGraph.artifacts.map((artifact) => [
358
+ artifact.id,
359
+ artifact.digest,
360
+ ]),
361
+ );
362
+ const artifactIds = [
363
+ ...new Set([...leftArtifacts.keys(), ...rightArtifacts.keys()]),
364
+ ].sort();
365
+ const artifacts = artifactIds
366
+ .map((id) => {
367
+ const before = leftArtifacts.get(id) || null;
368
+ const after = rightArtifacts.get(id) || null;
369
+ return before === after ? null : { id, before, after };
370
+ })
371
+ .filter(Boolean);
372
+ return Object.freeze({
373
+ schema: "chainlesschain.graph-trace-diff/v1",
374
+ from: {
375
+ runId: left.runId,
376
+ throughSeq: left.throughSeq,
377
+ projectionDigest: left.projectionDigest,
378
+ },
379
+ to: {
380
+ runId: right.runId,
381
+ throughSeq: right.throughSeq,
382
+ projectionDigest: right.projectionDigest,
383
+ },
384
+ nodes: Object.freeze(nodes.map(Object.freeze)),
385
+ artifacts: Object.freeze(artifacts.map(Object.freeze)),
386
+ });
387
+ }
388
+
389
+ export function locateBlockedRoot(projection, nodeId) {
390
+ const node = projection.taskGraph.nodes.find((entry) => entry.id === nodeId);
391
+ if (!node) return null;
392
+ const chain = [];
393
+ let cursor = node;
394
+ const seen = new Set();
395
+ while (cursor && !seen.has(cursor.id)) {
396
+ seen.add(cursor.id);
397
+ chain.push(cursor.id);
398
+ if (!cursor.blockedRoot || cursor.blockedRoot === cursor.id) break;
399
+ const next = projection.taskGraph.nodes.find(
400
+ (entry) => entry.id === cursor.blockedRoot,
401
+ );
402
+ if (!next) break;
403
+ cursor = next;
404
+ }
405
+ return Object.freeze({
406
+ root: chain.at(-1) || null,
407
+ chain: Object.freeze(chain),
408
+ });
409
+ }
@@ -0,0 +1,183 @@
1
+ import { createHash } from "node:crypto";
2
+ import { MemoryRolloutStore } from "../app-server/rollout-store.js";
3
+
4
+ const JOURNAL_THREAD_ID = "scheduler-graph-dispatch";
5
+
6
+ function dispatchKey(occurrence) {
7
+ const jobRevision = String(occurrence?.jobRevision || "").trim();
8
+ const occurrenceId = String(
9
+ occurrence?.occurrenceId || occurrence?.idempotencyKey || "",
10
+ ).trim();
11
+ if (!jobRevision || !occurrenceId) {
12
+ const error = new Error(
13
+ "scheduler dispatch requires jobRevision and occurrence identity",
14
+ );
15
+ error.code = "CC_GRAPH_OCCURRENCE_INVALID";
16
+ throw error;
17
+ }
18
+ return `${jobRevision}\0${occurrenceId}`;
19
+ }
20
+
21
+ function keyDigest(key) {
22
+ return createHash("sha256").update(key).digest("hex");
23
+ }
24
+
25
+ export class SchedulerGraphDispatchJournal {
26
+ constructor({ store = new MemoryRolloutStore() } = {}) {
27
+ this.store = store;
28
+ this.store.start({
29
+ threadId: JOURNAL_THREAD_ID,
30
+ title: "Scheduler to Graph dispatch journal",
31
+ metadata: { kind: "scheduler_graph_dispatch" },
32
+ });
33
+ }
34
+
35
+ append(key, phase, payload) {
36
+ const digest = keyDigest(key);
37
+ return this.store.append({
38
+ threadId: JOURNAL_THREAD_ID,
39
+ eventType: `dispatch.${phase}`,
40
+ idempotencyKey: `dispatch:${digest}:${phase}`,
41
+ payload: { keyDigest: digest, phase, ...payload },
42
+ });
43
+ }
44
+
45
+ read(key) {
46
+ const digest = keyDigest(key);
47
+ return this.store
48
+ .read(JOURNAL_THREAD_ID)
49
+ .filter((event) => event.payload?.keyDigest === digest)
50
+ .map((event) => event.payload);
51
+ }
52
+ }
53
+
54
+ export class SchedulerGraphTriggerAdapter {
55
+ constructor({ kernel, journal = new SchedulerGraphDispatchJournal() } = {}) {
56
+ if (!kernel)
57
+ throw new TypeError(
58
+ "SchedulerGraphTriggerAdapter requires a GraphKernel",
59
+ );
60
+ this.kernel = kernel;
61
+ this.journal = journal;
62
+ }
63
+
64
+ dispatch(occurrence, compiledGraph, options = {}) {
65
+ const key = dispatchKey(occurrence);
66
+ const digest = keyDigest(key);
67
+ const runId = options.runId || `graph-run-${digest.slice(0, 32)}`;
68
+ const journalEntries = this.journal.read(key);
69
+ const existing = journalEntries.find((entry) => entry.phase === "accepted");
70
+ if (existing) {
71
+ let run;
72
+ try {
73
+ run = this.kernel.getRun(existing.runId);
74
+ } catch {
75
+ run = this.kernel.recoverRun(existing.runId);
76
+ }
77
+ return Object.freeze({
78
+ occurrenceStatus: "succeeded",
79
+ dispatchStatus: "accepted",
80
+ graphRun: run,
81
+ replayed: true,
82
+ });
83
+ }
84
+ const pending = [...journalEntries]
85
+ .reverse()
86
+ .find((entry) => entry.phase === "pending");
87
+ if (pending) {
88
+ try {
89
+ const graphRun = this.kernel.recoverRun(pending.runId);
90
+ if (graphRun.revisionDigest !== compiledGraph.revisionDigest) {
91
+ const error = new Error(
92
+ "pending scheduler dispatch is bound to a different GraphRevision",
93
+ );
94
+ error.code = "CC_GRAPH_OCCURRENCE_CONFLICT";
95
+ throw error;
96
+ }
97
+ this.journal.append(key, "accepted", {
98
+ runId: graphRun.id,
99
+ graphRevision: graphRun.graphRevision,
100
+ revisionDigest: graphRun.revisionDigest,
101
+ });
102
+ return Object.freeze({
103
+ occurrenceStatus: "succeeded",
104
+ dispatchStatus: "accepted",
105
+ graphRun,
106
+ replayed: true,
107
+ recoveredAfterCrash: true,
108
+ });
109
+ } catch (error) {
110
+ if (
111
+ ![
112
+ "CC_GRAPH_RECOVERY_UNAVAILABLE",
113
+ "CC_ROLLOUT_THREAD_NOT_FOUND",
114
+ ].includes(error?.code)
115
+ ) {
116
+ throw error;
117
+ }
118
+ }
119
+ }
120
+ this.journal.append(key, "pending", {
121
+ runId,
122
+ jobRevision: occurrence.jobRevision,
123
+ occurrenceId: occurrence.occurrenceId || occurrence.idempotencyKey,
124
+ definitionDigest: compiledGraph.revisionDigest,
125
+ });
126
+ try {
127
+ const graphRun = this.kernel.startRun(compiledGraph, {
128
+ ...options,
129
+ runId,
130
+ occurrenceRef: {
131
+ jobRevision: occurrence.jobRevision,
132
+ occurrenceId: occurrence.occurrenceId || occurrence.idempotencyKey,
133
+ idempotencyKey: occurrence.idempotencyKey || occurrence.occurrenceId,
134
+ },
135
+ });
136
+ this.journal.append(key, "accepted", {
137
+ runId: graphRun.id,
138
+ graphRevision: graphRun.graphRevision,
139
+ revisionDigest: graphRun.revisionDigest,
140
+ });
141
+ // Scheduler success means only that the idempotent start/wake was
142
+ // durably admitted. GraphRun status remains a separate state machine.
143
+ return Object.freeze({
144
+ occurrenceStatus: "succeeded",
145
+ dispatchStatus: "accepted",
146
+ graphRun,
147
+ replayed: false,
148
+ });
149
+ } catch (error) {
150
+ this.journal.append(key, "failed", {
151
+ runId,
152
+ code: error?.code || "CC_GRAPH_DISPATCH_FAILED",
153
+ });
154
+ throw error;
155
+ }
156
+ }
157
+
158
+ status(occurrence) {
159
+ const key = dispatchKey(occurrence);
160
+ const entries = this.journal.read(key);
161
+ const accepted = [...entries]
162
+ .reverse()
163
+ .find((entry) => entry.phase === "accepted");
164
+ if (!accepted) {
165
+ return Object.freeze({
166
+ occurrenceStatus: entries.some((entry) => entry.phase === "failed")
167
+ ? "failed"
168
+ : "pending",
169
+ graphRun: null,
170
+ });
171
+ }
172
+ let graphRun;
173
+ try {
174
+ graphRun = this.kernel.getRun(accepted.runId);
175
+ } catch {
176
+ graphRun = this.kernel.recoverRun(accepted.runId);
177
+ }
178
+ return Object.freeze({
179
+ occurrenceStatus: "succeeded",
180
+ graphRun,
181
+ });
182
+ }
183
+ }
@@ -162,6 +162,7 @@ export class Orchestrator extends EventEmitter {
162
162
  priority: opts.priority || 2,
163
163
  cwd: opts.cwd || this.cwd,
164
164
  context: opts.context || "",
165
+ dataPolicy: opts.dataPolicy || null,
165
166
  runCI: opts.runCI !== false,
166
167
  notify: opts.notify !== false,
167
168
  status: TASK_STATUS.PENDING,
@@ -293,7 +294,7 @@ export class Orchestrator extends EventEmitter {
293
294
  this.emit("task:decomposed", { task, subtasks });
294
295
  this._log(`Decomposed into ${subtasks.length} subtask(s)`);
295
296
  return subtasks;
296
- } catch (_err) {
297
+ } catch {
297
298
  // Fallback: treat whole task as single subtask
298
299
  const fallback = [
299
300
  { id: "sub-1", description: task.description, context: task.context },
@@ -0,0 +1 @@
1
+ export * from "./skill-recorder.js";