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
@@ -17,7 +17,7 @@
17
17
 
18
18
  import fs from "fs";
19
19
  import path from "path";
20
- import { randomUUID } from "node:crypto";
20
+ import { createHash, randomUUID } from "node:crypto";
21
21
  import { fileURLToPath } from "url";
22
22
  import { TaskLeaseRegistry } from "../lib/agent-team/task-lease.js";
23
23
  import { TeamRunner } from "../lib/agent-team/team-runner.js";
@@ -32,6 +32,8 @@ import {
32
32
  computeTeamGraphRevisionDigest,
33
33
  projectTeamGraphCollaboration,
34
34
  } from "../lib/agent-team/team-graph-projection.js";
35
+ import { TeamGraphRuntimeAdapter } from "../lib/agent-team/team-graph-runtime-adapter.js";
36
+ import { createRuntimeGraphCutoverAuthorityResolver } from "../lib/graph-kernel/cutover-authority-resolver.js";
35
37
  import { resolveTeamTaskContract } from "../lib/agent-team/team-task-contract.js";
36
38
  import {
37
39
  TeamScopeLock,
@@ -326,6 +328,41 @@ function teamExecutionMode(options) {
326
328
  return "dry-run";
327
329
  }
328
330
 
331
+ export function teamGraphAuthorityMode(
332
+ options,
333
+ env = process.env,
334
+ { runKey = undefined, optIn = false, resolver = undefined } = {},
335
+ ) {
336
+ const executionMode = teamExecutionMode(options);
337
+ const configured = String(env.CHAINLESSCHAIN_GRAPH_CLI_TEAM || "")
338
+ .trim()
339
+ .toLowerCase();
340
+ if (configured && !["legacy", "shadow", "canonical"].includes(configured)) {
341
+ throw new Error(
342
+ "CHAINLESSCHAIN_GRAPH_CLI_TEAM must be legacy, shadow, or canonical",
343
+ );
344
+ }
345
+ const fallbackMode =
346
+ executionMode === "dry-run" ? "shadow" : configured || "legacy";
347
+ const authorityResolver =
348
+ resolver ||
349
+ createRuntimeGraphCutoverAuthorityResolver({
350
+ env,
351
+ surface: "cli_team",
352
+ entryId: "cli-team-local",
353
+ fallbackMode,
354
+ });
355
+ const resolved =
356
+ typeof authorityResolver === "function"
357
+ ? authorityResolver({ runKey, optIn })
358
+ : authorityResolver.resolve({ runKey, optIn, fallbackMode });
359
+ const mode = typeof resolved === "string" ? resolved : resolved?.mode;
360
+ if (!["legacy", "shadow", "canonical"].includes(mode)) {
361
+ throw new Error("Team Graph authority resolver returned an invalid mode");
362
+ }
363
+ return mode;
364
+ }
365
+
329
366
  function optionWasProvided(command, name) {
330
367
  const source = command?.getOptionValueSource?.(name);
331
368
  return source != null && source !== "default";
@@ -1008,8 +1045,23 @@ export function makeShellRunTask() {
1008
1045
  settle(terminationError);
1009
1046
  return;
1010
1047
  }
1011
- if (code === 0) settle(null, { code });
1012
- else {
1048
+ if (code === 0) {
1049
+ settle(null, {
1050
+ code,
1051
+ terminalEvidence: {
1052
+ outputDigest: `sha256:${createHash("sha256")
1053
+ .update(
1054
+ JSON.stringify({
1055
+ command,
1056
+ cwd: process.cwd(),
1057
+ exitCode: code,
1058
+ }),
1059
+ "utf8",
1060
+ )
1061
+ .digest("hex")}`,
1062
+ },
1063
+ });
1064
+ } else {
1013
1065
  const stderr = Buffer.concat(stderrChunks).toString("utf8");
1014
1066
  settle(new Error(safeProcessError(stderr, `command exited ${code}`)));
1015
1067
  }
@@ -1310,6 +1362,7 @@ function spawnAgentProcess(prompt, cwd, opts = {}) {
1310
1362
  return;
1311
1363
  }
1312
1364
  const result = { code };
1365
+ result.terminalEvidence = parser.terminalEvidence();
1313
1366
  if (sawStdout || summary.usage || summary.provider || summary.model) {
1314
1367
  if (summary.usage) result.usage = summary.usage;
1315
1368
  if (summary.provider) result.provider = summary.provider;
@@ -1994,6 +2047,10 @@ export function registerTeamCommand(program, { logger } = {}) {
1994
2047
  "--resume",
1995
2048
  "Restore progress from --state (completed tasks stay done; stale leases freed)",
1996
2049
  )
2050
+ .option(
2051
+ "--graph-canary-opt-in",
2052
+ "Opt this new Team run into an entry-scoped Graph canary",
2053
+ )
1997
2054
  .option("--json", "Emit the event stream as JSON lines")
1998
2055
  .option(
1999
2056
  "--otlp <file>",
@@ -2642,6 +2699,42 @@ export function registerTeamCommand(program, { logger } = {}) {
2642
2699
  (_, index) => `teammate-${index + 1}`,
2643
2700
  ),
2644
2701
  });
2702
+ const graphAuthorityMode =
2703
+ resumeSnapshot?.graphProjection?.authorityMode ||
2704
+ teamGraphAuthorityMode(options, process.env, {
2705
+ runKey: teamGraphRunId,
2706
+ optIn: options.graphCanaryOptIn === true,
2707
+ });
2708
+ let graphRuntime = null;
2709
+ const shadowDivergences = [];
2710
+ const recordShadowDivergence = (divergence) => {
2711
+ shadowDivergences.push(divergence);
2712
+ while (shadowDivergences.length > 256) shadowDivergences.shift();
2713
+ };
2714
+ if (["shadow", "canonical"].includes(graphAuthorityMode)) {
2715
+ graphRuntime = new TeamGraphRuntimeAdapter();
2716
+ graphRuntime.open({
2717
+ registry: reg,
2718
+ runId: teamGraphRunId,
2719
+ executionMode: executionContract.mode,
2720
+ worktree: options.worktree === true,
2721
+ teammates,
2722
+ budget: limits,
2723
+ authorityMode: graphAuthorityMode,
2724
+ dynamic: true,
2725
+ });
2726
+ if (graphAuthorityMode === "canonical") {
2727
+ reg = graphRuntime.bindRegistry(reg);
2728
+ mailbox = graphRuntime.bindMailbox(mailbox);
2729
+ } else {
2730
+ reg = graphRuntime.bindRegistry(reg, {
2731
+ onDivergence: recordShadowDivergence,
2732
+ });
2733
+ mailbox = graphRuntime.bindMailbox(mailbox, {
2734
+ onDivergence: recordShadowDivergence,
2735
+ });
2736
+ }
2737
+ }
2645
2738
  const settleGovernance = (key, status, extra = {}) => {
2646
2739
  const governanceKey = sessionTaskKeyFor(key);
2647
2740
  const unit = collaborationUnits.get(governanceKey);
@@ -2704,6 +2797,9 @@ export function registerTeamCommand(program, { logger } = {}) {
2704
2797
  revisionDigest: teamGraphRevisionDigest,
2705
2798
  authorityDigest: teamGraphAuthorityDigest,
2706
2799
  }),
2800
+ graphAuthorityMode,
2801
+ graphAuthority: graphRuntime?.status() || null,
2802
+ graphShadowDivergences: [...shadowDivergences],
2707
2803
  });
2708
2804
  };
2709
2805
 
@@ -2956,13 +3052,34 @@ export function registerTeamCommand(program, { logger } = {}) {
2956
3052
  realtimeMessaging: options.agent === true,
2957
3053
  scopeLock,
2958
3054
  recorder,
2959
- beforeTask: ({ key }) => {
2960
- settleGovernance(key, "running", {
2961
- startedAt: Date.now(),
2962
- });
3055
+ beforeTask: (context) => {
3056
+ const { key } = context;
3057
+ if (graphAuthorityMode === "canonical") {
3058
+ graphRuntime?.beforeTask(context);
3059
+ } else if (graphAuthorityMode === "shadow") {
3060
+ try {
3061
+ graphRuntime?.beforeTask(context);
3062
+ } catch (error) {
3063
+ recordShadowDivergence({
3064
+ phase: "assignment",
3065
+ key,
3066
+ code: error?.code || "CC_TEAM_GRAPH_SHADOW_DIVERGED",
3067
+ error: error?.message || String(error),
3068
+ });
3069
+ }
3070
+ }
2963
3071
  try {
3072
+ settleGovernance(key, "running", {
3073
+ startedAt: Date.now(),
3074
+ });
2964
3075
  persist();
2965
3076
  } catch (error) {
3077
+ try {
3078
+ graphRuntime?.abandonTask(key, error);
3079
+ } catch (canonicalError) {
3080
+ canonicalError.cause ||= error;
3081
+ throw canonicalError;
3082
+ }
2966
3083
  try {
2967
3084
  settleGovernance(key, "pending", {
2968
3085
  startedAt: null,
@@ -2973,6 +3090,38 @@ export function registerTeamCommand(program, { logger } = {}) {
2973
3090
  throw error;
2974
3091
  }
2975
3092
  },
3093
+ canonicalSettlement:
3094
+ graphAuthorityMode === "canonical" && graphRuntime
3095
+ ? (settlement) => graphRuntime.settleTask(settlement)
3096
+ : null,
3097
+ canonicalReady:
3098
+ graphAuthorityMode === "canonical" && graphRuntime
3099
+ ? ({ excludeKeys }) =>
3100
+ graphRuntime.nextReadyTaskKey({ excludeKeys })
3101
+ : null,
3102
+ shadowSettlement:
3103
+ graphAuthorityMode === "shadow" && graphRuntime
3104
+ ? (settlement) => graphRuntime.settleTask(settlement)
3105
+ : null,
3106
+ canonicalCancellation:
3107
+ graphAuthorityMode === "canonical" && graphRuntime
3108
+ ? ({ reason }) => graphRuntime.cancel(reason)
3109
+ : null,
3110
+ shadowCancellation:
3111
+ graphAuthorityMode === "shadow" && graphRuntime
3112
+ ? async ({ reason }) => {
3113
+ try {
3114
+ return await graphRuntime.cancel(reason);
3115
+ } catch (error) {
3116
+ recordShadowDivergence({
3117
+ phase: "run-cancel",
3118
+ code: error?.code || "CC_TEAM_GRAPH_SHADOW_DIVERGED",
3119
+ error: error?.message || String(error),
3120
+ });
3121
+ return null;
3122
+ }
3123
+ }
3124
+ : null,
2976
3125
  afterTask: ({ key, status, retry }) => {
2977
3126
  const governanceStatus =
2978
3127
  status === "completion-discarded" ||
@@ -3094,6 +3243,19 @@ export function registerTeamCommand(program, { logger } = {}) {
3094
3243
  }
3095
3244
  throw err;
3096
3245
  }
3246
+ if (graphRuntime) {
3247
+ const graphStatus = graphRuntime.finalize();
3248
+ summary.graphAuthorityMode = graphAuthorityMode;
3249
+ summary.graphRuntime = graphStatus;
3250
+ summary.graphShadowDivergences = [...shadowDivergences];
3251
+ if (
3252
+ graphAuthorityMode === "canonical" &&
3253
+ graphStatus.status !== "succeeded"
3254
+ ) {
3255
+ summary.success = false;
3256
+ summary.done = false;
3257
+ }
3258
+ }
3097
3259
  if (controlStore) {
3098
3260
  for (const request of controlStore.pending({
3099
3261
  anchor: controlCursor,
@@ -1,6 +1,19 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.166.7",
7
+ "cliVersions": ["0.166.6", "0.166.7"],
8
+ "date": "2026-08-28",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Added - cc CLI 0.166.7: authoritative Graph Kernel cutover",
13
+ "body": "> `chainlesschain` **0.166.6 -> 0.166.7** (release candidate,\n> 2026-08-28).\n\n- **Canonical execution authority**: CLI graph, Team, distributed-team,\n Cowork, Scheduler, and App Server entry points now resolve through the\n Graph Kernel cutover ledger instead of silently retaining parallel mutation\n paths.\n- **Durable fencing and recovery**: graph writers, leases, receipts, takeover,\n migration, and crash/resume flows are bound to persisted authority and\n checked-out source evidence so stale owners cannot resume mutations.\n- **Legacy containment**: retired runtimes retain explicitly read-only history\n access while unclassified or mutating legacy routes fail closed and report\n their canonical replacement targets.\n- **Release validation**: publication requires this exact candidate to pass\n Linux/Windows/macOS `CLI CI` and `CLI Strict Sandbox`, the Graph real-journey\n matrix, immutable package checks, and public-registry provenance readback."
14
+ }
15
+ ]
16
+ },
4
17
  {
5
18
  "productVersion": null,
6
19
  "cliVersion": "0.166.6",
@@ -3390,7 +3390,12 @@
3390
3390
  "thread/list",
3391
3391
  "thread/archive",
3392
3392
  "turn/start",
3393
- "turn/interrupt"
3393
+ "turn/interrupt",
3394
+ "graph/compile",
3395
+ "graph/run",
3396
+ "graph/status",
3397
+ "graph/cancel",
3398
+ "graph/reconcile"
3394
3399
  ]
3395
3400
  }
3396
3401
  }
@@ -325,6 +325,7 @@ export class TaskLeaseRegistry {
325
325
  attempts: t.metadata?.attempts || 0,
326
326
  lease: lease ? { ...lease } : null,
327
327
  assignee: t.assignee,
328
+ createdBy: t.createdBy ?? null,
328
329
  rev: t.rev,
329
330
  // Full metadata is exposed so executors can read user payload
330
331
  // (e.g. a task's shell `command` or agent `prompt`) — it carries the
@@ -1465,6 +1466,320 @@ export class TaskLeaseRegistry {
1465
1466
  return { ok: true, priorStatus };
1466
1467
  }
1467
1468
 
1469
+ /**
1470
+ * Repair the compatibility task view from a terminal canonical Graph node.
1471
+ * This exceptional path may correct a fail-closed recovery cancellation when
1472
+ * the immutable Graph ledger proves that the effect/attempt already settled.
1473
+ */
1474
+ applyCanonicalTaskProjection(
1475
+ key,
1476
+ {
1477
+ runId,
1478
+ nodeId,
1479
+ graphStatus,
1480
+ authorityGeneration,
1481
+ eventHead,
1482
+ revisionDigest,
1483
+ evidence = null,
1484
+ now = this._now(),
1485
+ } = {},
1486
+ ) {
1487
+ const terminalStatus =
1488
+ graphStatus === "succeeded"
1489
+ ? TASK_STATUS.COMPLETED
1490
+ : ["failed", "blocked", "cancelled"].includes(graphStatus)
1491
+ ? TASK_STATUS.CANCELLED
1492
+ : null;
1493
+ if (!terminalStatus) {
1494
+ return { ok: false, reason: "graph_not_terminal" };
1495
+ }
1496
+ if (
1497
+ !SAFE_HANDOFF_ID_PATTERN.test(String(runId || "")) ||
1498
+ !SAFE_HANDOFF_ID_PATTERN.test(String(nodeId || "")) ||
1499
+ !Number.isSafeInteger(Number(authorityGeneration)) ||
1500
+ Number(authorityGeneration) < 1 ||
1501
+ !SHA256_PATTERN.test(String(eventHead || "")) ||
1502
+ !SHA256_PATTERN.test(String(revisionDigest || ""))
1503
+ ) {
1504
+ return { ok: false, reason: "invalid_graph_binding" };
1505
+ }
1506
+ let cleanEvidence;
1507
+ try {
1508
+ cleanEvidence = cloneValue(evidence);
1509
+ } catch {
1510
+ return { ok: false, reason: "invalid_graph_evidence" };
1511
+ }
1512
+ const binding = {
1513
+ schema: "chainlesschain.team-graph-task-projection/v1",
1514
+ runId: String(runId),
1515
+ nodeId: String(nodeId),
1516
+ graphStatus,
1517
+ authorityGeneration: Number(authorityGeneration),
1518
+ eventHead: String(eventHead),
1519
+ revisionDigest: String(revisionDigest),
1520
+ evidence: cleanEvidence,
1521
+ };
1522
+ const projectionDigest = digestValue(binding);
1523
+ const id = this._byKey.get(key);
1524
+ const task = id ? this._tasks.get(id) : null;
1525
+ if (!task) return { ok: false, reason: "not_found" };
1526
+ const prior = task.metadata?.canonicalGraphProjection || null;
1527
+ if (prior?.projectionDigest === projectionDigest) {
1528
+ return {
1529
+ ok: true,
1530
+ idempotent: true,
1531
+ status: task.status,
1532
+ projectionDigest,
1533
+ };
1534
+ }
1535
+ if (
1536
+ prior &&
1537
+ (prior.runId !== binding.runId ||
1538
+ prior.nodeId !== binding.nodeId ||
1539
+ prior.revisionDigest !== binding.revisionDigest ||
1540
+ prior.graphStatus !== binding.graphStatus)
1541
+ ) {
1542
+ return { ok: false, reason: "graph_projection_conflict" };
1543
+ }
1544
+ const snapshot = this._tasks.snapshot();
1545
+ const stored = snapshot.tasks.find((candidate) => candidate.id === task.id);
1546
+ if (!stored || stored.rev !== task.rev) {
1547
+ return { ok: false, reason: "concurrent" };
1548
+ }
1549
+ const projectedAt = Number.isFinite(Number(now))
1550
+ ? Number(now)
1551
+ : this._now();
1552
+ const metadata = {
1553
+ ...stored.metadata,
1554
+ lease: null,
1555
+ canonicalGraphProjection: {
1556
+ ...binding,
1557
+ projectionDigest,
1558
+ projectedAt,
1559
+ },
1560
+ };
1561
+ delete metadata.adjudication;
1562
+ if (terminalStatus === TASK_STATUS.COMPLETED) {
1563
+ metadata.result = {
1564
+ canonicalGraph: true,
1565
+ terminalEvidence: cleanEvidence,
1566
+ };
1567
+ delete metadata.lastError;
1568
+ } else {
1569
+ metadata.lastError = `canonical Graph node settled ${graphStatus}`;
1570
+ }
1571
+ stored.status = terminalStatus;
1572
+ stored.assignee = null;
1573
+ stored.updatedAt = projectedAt;
1574
+ stored.rev += 1;
1575
+ stored.metadata = metadata;
1576
+ stored.history = [
1577
+ ...(stored.history || []),
1578
+ {
1579
+ ts: projectedAt,
1580
+ actor: "graph-kernel",
1581
+ action: "canonical-projection-repaired",
1582
+ changes: ["status", "assignee", "metadata"],
1583
+ graphStatus,
1584
+ projectionDigest,
1585
+ },
1586
+ ];
1587
+ this._tasks = SharedTaskList.restore(snapshot, { now: this._now });
1588
+ this._rebuildIndexes();
1589
+ if (terminalStatus === TASK_STATUS.COMPLETED) {
1590
+ for (const dependent of this._dependentsByKey.get(key) || []) {
1591
+ this._enqueueIfReady(dependent, projectedAt);
1592
+ }
1593
+ }
1594
+ return { ok: true, status: terminalStatus, projectionDigest };
1595
+ }
1596
+
1597
+ applyCanonicalHandoffProjection(
1598
+ key,
1599
+ { handoff: source, targetLease = null, now = this._now() } = {},
1600
+ ) {
1601
+ if (!source || typeof source !== "object") {
1602
+ return { ok: false, reason: "invalid_handoff_projection" };
1603
+ }
1604
+ const id = normalizedHandoffId(source.id, () => null);
1605
+ const fromHolder = normalizedHolder(source.fromHolder);
1606
+ const toHolder = normalizedHolder(source.toHolder);
1607
+ const revisionDigest = normalizedDigest(source.revisionDigest);
1608
+ const authorityDigest = normalizedDigest(source.authorityDigest);
1609
+ const artifactIds = normalizedArtifactIds(source.artifactIds);
1610
+ const status = String(source.status || "");
1611
+ const ttlMs = Number(source.ttlMs);
1612
+ if (
1613
+ !id ||
1614
+ !fromHolder ||
1615
+ !toHolder ||
1616
+ fromHolder === toHolder ||
1617
+ !revisionDigest ||
1618
+ !authorityDigest ||
1619
+ !artifactIds ||
1620
+ !TEAM_CUSTODY_HANDOFF_STATUSES.includes(status) ||
1621
+ !Number.isSafeInteger(ttlMs) ||
1622
+ ttlMs <= 0 ||
1623
+ ttlMs > MAX_HANDOFF_TTL_MS ||
1624
+ source.taskKey !== key ||
1625
+ typeof source.fromLeaseId !== "string" ||
1626
+ source.fromLeaseId.length === 0 ||
1627
+ !["string", "number"].includes(typeof source.fromFence)
1628
+ ) {
1629
+ return { ok: false, reason: "invalid_handoff_projection" };
1630
+ }
1631
+ let preconditions;
1632
+ let summary;
1633
+ try {
1634
+ preconditions = cloneValue(source.preconditions);
1635
+ summary = cloneValue(source.summary);
1636
+ } catch {
1637
+ return { ok: false, reason: "invalid_handoff_projection" };
1638
+ }
1639
+ const idempotencyKey = normalizedHandoffId(
1640
+ source.idempotencyKey,
1641
+ () => null,
1642
+ );
1643
+ if (!idempotencyKey) {
1644
+ return { ok: false, reason: "invalid_handoff_projection" };
1645
+ }
1646
+ const binding = {
1647
+ schema: TEAM_CUSTODY_HANDOFF_SCHEMA,
1648
+ id,
1649
+ taskKey: key,
1650
+ fromHolder,
1651
+ fromLeaseId: source.fromLeaseId,
1652
+ fromFence: source.fromFence,
1653
+ toHolder,
1654
+ revisionDigest,
1655
+ authorityDigest,
1656
+ artifactIds,
1657
+ preconditions,
1658
+ summary,
1659
+ idempotencyKey,
1660
+ ttlMs,
1661
+ };
1662
+ const bindingDigest = digestValue(binding);
1663
+ if (source.bindingDigest && source.bindingDigest !== bindingDigest) {
1664
+ return { ok: false, reason: "handoff_binding_conflict" };
1665
+ }
1666
+ let cleanTargetLease = null;
1667
+ if (status === "committed") {
1668
+ try {
1669
+ cleanTargetLease = cloneValue(targetLease || source.targetLease);
1670
+ } catch {
1671
+ return { ok: false, reason: "invalid_target_lease" };
1672
+ }
1673
+ if (
1674
+ !cleanTargetLease ||
1675
+ cleanTargetLease.holder !== toHolder ||
1676
+ typeof cleanTargetLease.leaseId !== "string" ||
1677
+ cleanTargetLease.leaseId.length === 0 ||
1678
+ !Number.isFinite(Number(cleanTargetLease.expiresAt))
1679
+ ) {
1680
+ return { ok: false, reason: "invalid_target_lease" };
1681
+ }
1682
+ }
1683
+ const taskId = this._byKey.get(key);
1684
+ const task = taskId ? this._tasks.get(taskId) : null;
1685
+ if (!task) return { ok: false, reason: "not_found" };
1686
+ const history = handoffHistory(task);
1687
+ const existing = history.find((entry) => entry.id === id);
1688
+ if (existing && existing.bindingDigest !== bindingDigest) {
1689
+ return { ok: false, reason: "handoff_binding_conflict" };
1690
+ }
1691
+ if (existing && existing.status !== status) {
1692
+ const transitions = {
1693
+ offered: new Set([
1694
+ "accepted",
1695
+ "rejected",
1696
+ "committed",
1697
+ "revoked",
1698
+ "expired",
1699
+ ]),
1700
+ accepted: new Set(["committed", "revoked", "expired"]),
1701
+ };
1702
+ if (!transitions[existing.status]?.has(status)) {
1703
+ return { ok: false, reason: "handoff_projection_regressed" };
1704
+ }
1705
+ }
1706
+ if (existing?.status === status) {
1707
+ return { ok: true, idempotent: true, handoff: cloneValue(existing) };
1708
+ }
1709
+ const projectedAt = Number.isFinite(Number(now))
1710
+ ? Number(now)
1711
+ : this._now();
1712
+ const projected = {
1713
+ ...(existing || binding),
1714
+ ...binding,
1715
+ bindingDigest,
1716
+ expiresAtMs: Number(source.expiresAtMs),
1717
+ status,
1718
+ offeredAt: Number(source.offeredAt),
1719
+ acceptedAt: source.acceptedAt == null ? null : Number(source.acceptedAt),
1720
+ rejectedAt: source.rejectedAt == null ? null : Number(source.rejectedAt),
1721
+ committedAt:
1722
+ source.committedAt == null ? null : Number(source.committedAt),
1723
+ revokedAt: source.revokedAt == null ? null : Number(source.revokedAt),
1724
+ expiredAt: source.expiredAt == null ? null : Number(source.expiredAt),
1725
+ targetStartedAt: existing?.targetStartedAt ?? null,
1726
+ targetSettledAt: existing?.targetSettledAt ?? null,
1727
+ targetSettlement: existing?.targetSettlement ?? null,
1728
+ reason:
1729
+ source.reason == null ? null : String(source.reason).slice(0, 1024),
1730
+ acceptedByAttempt: existing?.acceptedByAttempt ?? null,
1731
+ targetLease:
1732
+ status === "committed"
1733
+ ? cloneValue(existing?.targetLease || cleanTargetLease)
1734
+ : null,
1735
+ canonicalProjectedAt: projectedAt,
1736
+ updatedAt: Number(source.updatedAt) || projectedAt,
1737
+ };
1738
+ if (existing) {
1739
+ history[history.indexOf(existing)] = projected;
1740
+ } else {
1741
+ history.push(projected);
1742
+ while (history.length > MAX_HANDOFF_HISTORY) history.shift();
1743
+ }
1744
+ const snapshot = this._tasks.snapshot();
1745
+ const stored = snapshot.tasks.find((candidate) => candidate.id === task.id);
1746
+ if (!stored || stored.rev !== task.rev) {
1747
+ return { ok: false, reason: "concurrent" };
1748
+ }
1749
+ stored.rev += 1;
1750
+ stored.updatedAt = projectedAt;
1751
+ stored.metadata = { ...stored.metadata, custodyHandoffs: history };
1752
+ if (
1753
+ status === "committed" &&
1754
+ ![TASK_STATUS.COMPLETED, TASK_STATUS.CANCELLED].includes(stored.status)
1755
+ ) {
1756
+ stored.status = TASK_STATUS.IN_PROGRESS;
1757
+ stored.assignee = toHolder;
1758
+ stored.metadata.lease = cloneValue(projected.targetLease);
1759
+ } else if (
1760
+ status === "expired" &&
1761
+ stored.metadata?.lease?.leaseId === binding.fromLeaseId
1762
+ ) {
1763
+ stored.status = TASK_STATUS.PENDING;
1764
+ stored.assignee = null;
1765
+ stored.metadata.lease = null;
1766
+ }
1767
+ stored.history = [
1768
+ ...(stored.history || []),
1769
+ {
1770
+ ts: projectedAt,
1771
+ actor: "graph-kernel",
1772
+ action: "canonical-handoff-projected",
1773
+ changes: ["status", "assignee", "metadata"],
1774
+ handoffId: id,
1775
+ handoffStatus: status,
1776
+ },
1777
+ ];
1778
+ this._tasks = SharedTaskList.restore(snapshot, { now: this._now });
1779
+ this._rebuildIndexes();
1780
+ return { ok: true, handoff: cloneValue(projected) };
1781
+ }
1782
+
1468
1783
  /** Bind a pending adjudication to its immutable durable case evidence. */
1469
1784
  bindAdjudicationCase(key, { caseId, registryDigest, sideEffectDigest } = {}) {
1470
1785
  const id = this._byKey.get(key);
@@ -7,6 +7,7 @@
7
7
  * are never copied into parser state or returned to callers.
8
8
  */
9
9
 
10
+ import { createHash } from "node:crypto";
10
11
  import { TextDecoder } from "node:util";
11
12
 
12
13
  export const DEFAULT_TEAM_AGENT_MAX_LINE_BYTES = 1024 * 1024;
@@ -96,6 +97,7 @@ export class TeamAgentStreamParser {
96
97
  #tokenUsageEvents = 0;
97
98
  #usageByIdentity = new Map();
98
99
  #sawTerminalResult = false;
100
+ #terminalResultDigest = null;
99
101
  #finished = false;
100
102
  #failed = null;
101
103
  #finalSummary = null;
@@ -204,6 +206,16 @@ export class TeamAgentStreamParser {
204
206
  return this.#copyLiveSummary();
205
207
  }
206
208
 
209
+ /**
210
+ * Return an immutable digest of the exact terminal result record without
211
+ * retaining or exposing its prompt/result body.
212
+ */
213
+ terminalEvidence() {
214
+ return this.#terminalResultDigest
215
+ ? Object.freeze({ outputDigest: this.#terminalResultDigest })
216
+ : null;
217
+ }
218
+
207
219
  #copyLiveSummary() {
208
220
  return {
209
221
  provider: this.#provider,
@@ -291,6 +303,9 @@ export class TeamAgentStreamParser {
291
303
  }
292
304
  if (line.trim() === "") return;
293
305
 
306
+ const lineDigest = `sha256:${createHash("sha256")
307
+ .update(line, "utf8")
308
+ .digest("hex")}`;
294
309
  let event;
295
310
  try {
296
311
  event = JSON.parse(line);
@@ -345,6 +360,7 @@ export class TeamAgentStreamParser {
345
360
 
346
361
  if (event.type === "result") {
347
362
  this.#sawTerminalResult = true;
363
+ this.#terminalResultDigest = lineDigest;
348
364
  this.#lastResultProvider =
349
365
  typeof event.provider === "string" ? event.provider : this.#provider;
350
366
  this.#lastResultModel =