chainlesschain 0.166.2 → 0.166.4

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 (173) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-BnZ24WRk.js → AIOps-HcOh0ZbH.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-ivXY7MGb.js → ActionButton-DWjDqBhd.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-BQS4OD-k.js → Analytics-C6FS-y3W.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-wOBuOKTO.js → AppLayout-DCN5cldF.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-BYuC4nw-.js → Artifacts-Crd-KE8P.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BIeVfBt6.js → Audit-BexuTQZc.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-hIuyhmJ7.js → BackgroundAgents-Dydkh-b5.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-B6ohdgPQ.js → Backup-BYq21wMP.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-BzgYCw6h.js → BaseInput-CmNZP6yM.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CwahvZU1.js → Chat-J6bD0zCl.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-B-1IZ_k8.js → ChatBubbleRenderer-MEoaygnL.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-26EDP2x0.js → Checkbox-Ce-9vNmK.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-DYLw1Zvd.js → Codegen-zf7-Y-Eh.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DH_zAvD-.js → Col-D-TkY0FD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-DURrTXJu.js → Community-l300NA-1.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-CQyBqN0p.js → Compact-D-9Q_hxc.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-a0DfgKHD.js → Compliance-DAJ8lLiQ.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-C6fY_5Ke.js → Cowork-xmzZ967S.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DOwmpbTe.js → Cron-CeGqO5W4.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DEPOIEUs.js → Crosschain-DXN0AE-4.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DaKc-CEV.js → DID-CtIKASPr.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-C-0KLXq5.js → Dashboard-DqRwT8NX.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-CnsDukzr.js → Dropdown-ddIVljO1.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-Bi_ACD4N.js → EmailListRenderer-CcsFzV4y.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BZASpnx3.js → FamilyGuardDashboard-PnlAUGcG.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-43oTtzyp.js → Federation-BlmLuQrL.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-oyVadnkZ.js → FormItemContext-dDovBj1Y.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-Cwvfd6TZ.js → GenericCardRenderer-DTvGshFr.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Cgi2wvU0.js → Git-DuFR2xgA.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-l8TWDKZ0.js → Governance-9EaNcJuq.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-Dc8j6TaO.js → Inference-B-iYWH_r.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DgcO-Fwz.js → KnowledgeGraph-BGBaKiLX.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DjiZpiwa.js → Logs-G3wmXzfa.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-B5MFCi0N.js → MarkdownRenderer-hk0YwjTR.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BeDn1hFc.js → Marketplace-BNARBeAv.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-PGdVfWK6.js → McpTools-DST2cSSK.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-e76lY3a1.js → Memory-piwDLsVH.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-DKlQqot_.js → MobileBridge-D-W8zHdm.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-C4g6WOEr.js → MobileProjects-CwaYHlVP.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-1j3NpRQq.js → Mtc-C2dxnN7Q.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-DgwiVd1C.js → MtcAudit-BwPZsV3N.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-Dzg5lZZY.js → Multisig-CUt8w2al.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-D7GYhst-.js → NLProgramming-DwxErx27.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-Blcfvaic.js → Notes-B-mXAZ84.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-Dc4Y6vfr.js → NotificationSettings-Bd1fBAzd.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-CCInnavw.js +1 -0
  49. package/src/assets/web-panel/assets/{Organization-DBXq024L.js → Organization-DTTONYZT.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-CFPbdx1Y.js → Overflow-H6lCZ1rE.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-w7z61NR5.js → P2P-DyBZzeYW.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-B7eGGZOa.js → PdhVaultBrowser-jj7LhT04.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-Df5Cl50D.js → Permissions-B5nSQwsr.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-C-We7RF6.js → PersonalDataHub-CACaQtlY.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-B6fHPnKy.js → Pipeline-5y-DR_Bw.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-B85BdiIc.js → Privacy-BMSA3Ehd.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-CcOyazSe.js → ProjectInit-VCOj1dTa.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-BE53KfuU.js → ProjectSettings-CJaXO_iE.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-DOvMOoe_.js → Projects-C21-MQ3H.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-5l7sT9lq.js → Providers-DZ1FNKUR.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-DE37RXy4.js → QrScannerModal-6DKc9UBX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-BGmGCo7j.js → QuickAsk-Dyd0Ckrk.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-BFdx8Nrm.js → Recommend-CYW4-GJH.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-C1w-j_hB.js → RemoteSession-DLrfPy4F.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-BOvn-10y.js → Reputation-DfqPo1FI.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-db-a1YO9.js → Row-CR89H2x5.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-DeS43ZGM.js → RssFeed-B9QY7R-F.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-BaQYNfeb.js → Search-CUDnzu4w.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-yt1ESHDg.js → Security-CJ0CtM_Z.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-BcNqPUsS.js → Services-CyrQ6F5U.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-X3ceUQWf.js → Skeleton-DcwnKatQ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-DmYeax6C.js → Skills-BhKkYF3_.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-C_fdfbuJ.js → Sla-CWh-awh7.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-CDqohXXQ.js → SpeechSettings-BaUMNzx7.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-B25maYEY.js → SyncSettings-D1Ijwwxl.js} +2 -2
  76. package/src/assets/web-panel/assets/Tasks-DFqjHi3T.js +1 -0
  77. package/src/assets/web-panel/assets/{Templates-DUH0iuc4.js → Templates-Ct-9_ki3.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DrvhHf9T.js → Tenant-zBkgyilh.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-C2lJVYHA.js → Terminal-VVO2Hjfi.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-C1Hf_jYn.js → TimelineRenderer-CX9pIkx3.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-DniS1NpS.js → Tokens-DHaD6e_m.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-4jrcb8oA.js → Trigger-CFq9j3WV.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DiBte55w.js → Trust-DuF7gIYX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CZRtc4VB.js → UkeySign-DbuidXJX.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BtYGJDmg.js → VideoEditing-B8IA9_qE.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-D1nrTm7H.js → Wallet-DdCglSIK.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-DI91acpx.js → WebAuthn-CeteRsA8.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BtQjI50d.js → WorkflowEditor-DJhIbG__.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-I4A-f4FC.js → chat-srOi_Wef.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-QZkDkFVt.js → colors-HpVHsNGK.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item--FtCdzpr.js → compact-item-DsLhrqWe.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-CaIKIKxP.js → createContext-aOasIUuE.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-B_acr36n.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DLYUII6-.js → hasIn-D5BVMimS.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DGLHSCHM.js → index-B615KD2o.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-3rVtgqa2.js → index-BCp70IlO.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-Deg2S9ZJ.js → index-BD64r0Tx.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-yayaayEA.js → index-BGBvkNN3.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-B65QxJaG.js → index-BNbsjeEc.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BxPoPofq.js → index-BTwDhhvl.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-C3PnIEOH.js → index-BigtYchO.js} +1 -1
  102. package/src/assets/web-panel/assets/index-BnLYpdox.js +1 -0
  103. package/src/assets/web-panel/assets/{index-BLGJmgmx.js → index-Bu6TVdgQ.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CL4c5D6G.js → index-C4tPtHU0.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Du2wUavy.js → index-CGVHW0nF.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DA_TPdzX.js → index-CQEoGqMG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Ch0IFpGy.js → index-CQXp_uNd.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CBtII-nl.js → index-CSxJ4oRd.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-21I79XSf.js → index-CUUs12L9.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DAuf8r5o.js → index-CVp_dHCs.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Bs0qPPFb.js → index-ChGUPEwS.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DVitI3UQ.js → index-CvhVCHk-.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DK2r6Bv7.js → index-D1xZMQrN.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Ooo_5jHo.js → index-D2XRXkZU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DJrd_CR3.js → index-DQ5j1VKg.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CXaeZCRP.js → index-DRCIPsdm.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CQ7OBHka.js → index-DV4y5rUj.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-eTqL91aV.js → index-DcLBzIiI.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CisYjy88.js → index-DiXsis7m.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-D4CXFU-w.js → index-Dpj-rEoV.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BebTT7iR.js → index-Dum_r_oY.js} +1 -1
  122. package/src/assets/web-panel/assets/index-Dzmwsl_v.js +1 -0
  123. package/src/assets/web-panel/assets/{index-vfiDxdN2.js → index-LSz0ZOB8.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Ygi2rYL1.js → index-Ow3SRXRX.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-hfiZ-i2b.js → index-P6IMLmLT.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CgMm85BY.js → index-V0gpVTbS.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-0DYBQ-6e.js → index-b0Y0hDhX.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BGWSmE3G.js → index-dPFzlII1.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-OQPIS_am.js → index-fZnlPk7H.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BkJgWW_L.js → index-kYqi6zYp.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BvdwNnHC.js → index-lFOfvZDn.js} +3 -3
  132. package/src/assets/web-panel/assets/{index-BcgtvJbC.js → index-q--LtRh9.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-D2xETCkj.js → index-vQ6jy8Ew.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-DDkTvw8k.js → initDefaultProps-1NU9yNpr.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-fkr96tN5.js → motion-BZk2hQ6c.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-CGBV0SV2.js → move-BNvublME.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DAsCliFt.js → mtc-parser-DWk5BUoL.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BM8PMmKN.js → omit-DztYxX3x.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-C6SdWoTK.js → pickAttrs-DURL8mtg.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BG0EVu-d.js → placementArrow-B820R56z.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-L10IvfYC.js → responsiveObserve-DUAkGJL1.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-TddIkbrn.js → slide-uZQeNSo6.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-FlveF2Yn.js → statusUtils-CGR1wFVq.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-BrXRyebg.js → styleChecker-BIIPOMsQ.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-B7_oiDXZ.js → useFlexGapSupport-rIB9c0g2.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-CQYeRYWb.js → useFs-CrJe1BJi.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-DspIkhVi.js → usePersonalDataHub-DyEoD3Qm.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-BCwmwMAW.js → vnode-CjohPxI0.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-B0cEGluV.js → zoom-C5POL1_6.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/team.js +165 -53
  152. package/src/data/changelog.json +26 -0
  153. package/src/gateways/ws/remote-session-protocol.js +20 -15
  154. package/src/generated/cc-agent-protocol.schema.json +67 -1
  155. package/src/lib/agent-team/task-lease.js +718 -6
  156. package/src/lib/agent-team/team-graph-projection.js +303 -0
  157. package/src/lib/agent-team/team-message-bridge.js +83 -5
  158. package/src/lib/agent-team/team-message-tools.js +34 -1
  159. package/src/lib/agent-team/team-runner.js +1131 -9
  160. package/src/lib/agent-team/team-session-message-adapter.js +720 -0
  161. package/src/lib/app-server/cli-agent-kernel-adapter.js +1 -0
  162. package/src/lib/app-server/protocol.js +44 -8
  163. package/src/lib/app-server/server.js +8 -11
  164. package/src/lib/approval-grant-ledger.js +187 -0
  165. package/src/lib/remote-approval-bridge.js +8 -12
  166. package/src/lib/remote-approval-decision.js +87 -0
  167. package/src/lib/session-message-fabric.js +265 -3
  168. package/src/runtime/headless-stream.js +184 -19
  169. package/src/assets/web-panel/assets/OrderTableRenderer-dgM87XIn.js +0 -1
  170. package/src/assets/web-panel/assets/Tasks-3ILwauYw.js +0 -1
  171. package/src/assets/web-panel/assets/devWarning-D7qVrkrO.js +0 -1
  172. package/src/assets/web-panel/assets/index-D9Y_ZwZn.js +0 -1
  173. package/src/assets/web-panel/assets/index-D_cPes4G.js +0 -1
@@ -24,8 +24,14 @@ import { TeamRunner } from "../lib/agent-team/team-runner.js";
24
24
  import { TeamWorktreeCoordinator } from "../lib/agent-team/team-worktree.js";
25
25
  import { TeamBudget } from "../lib/agent-team/team-budget.js";
26
26
  import { TeamMailbox } from "../lib/agent-team/team-mailbox.js";
27
+ import { TeamSessionMessageAdapter } from "../lib/agent-team/team-session-message-adapter.js";
27
28
  import { TeamAgentStreamParser } from "../lib/agent-team/team-agent-stream.js";
28
29
  import { TeamMessageBridge } from "../lib/agent-team/team-message-bridge.js";
30
+ import {
31
+ computeTeamGraphAuthorityDigest,
32
+ computeTeamGraphRevisionDigest,
33
+ projectTeamGraphCollaboration,
34
+ } from "../lib/agent-team/team-graph-projection.js";
29
35
  import { resolveTeamTaskContract } from "../lib/agent-team/team-task-contract.js";
30
36
  import {
31
37
  TeamScopeLock,
@@ -1371,6 +1377,8 @@ export function makeAgentRunTask(opts = {}) {
1371
1377
  sendMessage = null,
1372
1378
  messageAuthority = null,
1373
1379
  recipientState = null,
1380
+ requestFollowupWake = null,
1381
+ requestHandoff = null,
1374
1382
  mailbox = null,
1375
1383
  budgetReservation = null,
1376
1384
  signal = null,
@@ -1395,7 +1403,7 @@ export function makeAgentRunTask(opts = {}) {
1395
1403
  );
1396
1404
  return spawnAgent(buildTeamAgentPrompt(prompt, { inbox }), process.cwd(), {
1397
1405
  ...effectiveContract,
1398
- sessionId: opts.sessionIdForTask?.(key) || null,
1406
+ sessionId: opts.sessionIdForTask?.(key, task) || null,
1399
1407
  signal,
1400
1408
  ...(mailbox && holder
1401
1409
  ? {
@@ -1405,6 +1413,8 @@ export function makeAgentRunTask(opts = {}) {
1405
1413
  sendMessage,
1406
1414
  assertAuthority: messageAuthority,
1407
1415
  recipientState,
1416
+ requestFollowupWake,
1417
+ requestHandoff,
1408
1418
  onMutation: opts.onMailboxMutation,
1409
1419
  durable: opts.mailboxDurable === true,
1410
1420
  },
@@ -2160,8 +2170,17 @@ export function registerTeamCommand(program, { logger } = {}) {
2160
2170
  return;
2161
2171
  }
2162
2172
  const ttlMs = limits.ttlMs;
2173
+ const stateId = resumeSnapshot?.stateId || `team_state_${randomUUID()}`;
2174
+ const messageStatePath = options.state
2175
+ ? `${options.state}.${stateId}.messages.json`
2176
+ : null;
2163
2177
  let reg;
2164
- let mailbox = new TeamMailbox();
2178
+ let mailbox = options.state
2179
+ ? new TeamSessionMessageAdapter({
2180
+ statePath: messageStatePath,
2181
+ teamId: stateId,
2182
+ })
2183
+ : new TeamMailbox();
2165
2184
  let budget = new TeamBudget({
2166
2185
  maxTasks: limits.maxTasks,
2167
2186
  maxTokens: limits.maxTokens,
@@ -2181,7 +2200,32 @@ export function registerTeamCommand(program, { logger } = {}) {
2181
2200
  const isV2 = snap && snap.version >= 2 && snap.registry;
2182
2201
  reg = TaskLeaseRegistry.restore(isV2 ? snap.registry : snap);
2183
2202
  if (isV2) {
2184
- if (snap.mailbox) mailbox = TeamMailbox.restore(snap.mailbox);
2203
+ if (snap.mailbox?.authority === "session-message-fabric") {
2204
+ if (
2205
+ !sameFilesystemPath(
2206
+ path.resolve(snap.mailbox.statePath),
2207
+ path.resolve(messageStatePath),
2208
+ )
2209
+ ) {
2210
+ throw new Error(
2211
+ "Team message authority path does not match the trusted state identity",
2212
+ );
2213
+ }
2214
+ mailbox = TeamSessionMessageAdapter.restore(snap.mailbox, {
2215
+ statePath: messageStatePath,
2216
+ teamId: stateId,
2217
+ });
2218
+ } else if (snap.mailbox && options.state) {
2219
+ mailbox = TeamSessionMessageAdapter.migrateLegacy(
2220
+ snap.mailbox,
2221
+ {
2222
+ statePath: messageStatePath,
2223
+ teamId: stateId,
2224
+ },
2225
+ );
2226
+ } else if (snap.mailbox) {
2227
+ mailbox = TeamMailbox.restore(snap.mailbox);
2228
+ }
2185
2229
  budget = TeamBudget.restore(snap.budget, {
2186
2230
  // Resume flags may only tighten prior caps; omitted flags keep
2187
2231
  // the persisted authority.
@@ -2285,6 +2329,11 @@ export function registerTeamCommand(program, { logger } = {}) {
2285
2329
  }),
2286
2330
  ]),
2287
2331
  );
2332
+ const sessionTaskKeyFor = (key, task = reg.getTask(key)) =>
2333
+ task?.metadata?.teamFollowup?.sessionTaskKey || key;
2334
+ const taskContractFor = (key, task = reg.getTask(key)) =>
2335
+ taskContracts.get(key) ||
2336
+ taskContracts.get(sessionTaskKeyFor(key, task));
2288
2337
  if ((options.agent || options.exec) && !options.worktree) {
2289
2338
  const isolatedTask = reg
2290
2339
  .list()
@@ -2352,7 +2401,6 @@ export function registerTeamCommand(program, { logger } = {}) {
2352
2401
  );
2353
2402
  }
2354
2403
  }
2355
- const stateId = resumeSnapshot?.stateId || `team_state_${randomUUID()}`;
2356
2404
  let controlCursor = resumeSnapshot?.controlCursor || null;
2357
2405
  let adjudicationCursor = resumeSnapshot?.adjudicationCursor || null;
2358
2406
  let adjudicationRunId = resumeSnapshot?.adjudicationRunId || null;
@@ -2531,37 +2579,40 @@ export function registerTeamCommand(program, { logger } = {}) {
2531
2579
  checkpointRequired:
2532
2580
  options.agent === true || options.managedCheckpoint === true,
2533
2581
  worktreeRequired: options.worktree === true,
2534
- units: reg.list().map((task) => ({
2535
- key: task.key,
2536
- branch: options.worktree
2537
- ? priorUnits.get(task.key)?.branch ||
2538
- branchPlanner.branchFor(task.key)
2539
- : null,
2540
- worktreePath: options.worktree
2541
- ? priorUnits.get(task.key)?.worktreePath || null
2542
- : null,
2543
- sessionId: options.agent
2544
- ? priorUnits.get(task.key)?.sessionId ||
2545
- _deps.collaborationStore.createSessionId(runId, task.key)
2546
- : null,
2547
- status:
2548
- String(task.status || "").toLowerCase() === "completed"
2549
- ? "completed"
2550
- : "pending",
2551
- permissionMode: taskContracts.get(task.key)?.permissionMode,
2552
- resourceBudget: {
2553
- maxTurns: taskContracts.get(task.key)?.maxTurns,
2554
- maxCostUsd: taskContracts.get(task.key)?.maxBudgetUsd,
2555
- maxTokens: taskContracts.get(task.key)?.maxTokens,
2556
- maxWallMs: taskContracts.get(task.key)?.maxWallMs,
2557
- },
2558
- checkpointRequired:
2559
- taskContracts.get(task.key)?.checkpointRequired === true ||
2560
- options.managedCheckpoint === true,
2561
- worktreeRequired:
2562
- taskContracts.get(task.key)?.worktreeRequired === true,
2563
- scopePaths: task.metadata?.scopePaths || [],
2564
- })),
2582
+ units: reg
2583
+ .list()
2584
+ .filter((task) => !task.metadata?.teamFollowup)
2585
+ .map((task) => ({
2586
+ key: task.key,
2587
+ branch: options.worktree
2588
+ ? priorUnits.get(task.key)?.branch ||
2589
+ branchPlanner.branchFor(task.key)
2590
+ : null,
2591
+ worktreePath: options.worktree
2592
+ ? priorUnits.get(task.key)?.worktreePath || null
2593
+ : null,
2594
+ sessionId: options.agent
2595
+ ? priorUnits.get(task.key)?.sessionId ||
2596
+ _deps.collaborationStore.createSessionId(runId, task.key)
2597
+ : null,
2598
+ status:
2599
+ String(task.status || "").toLowerCase() === "completed"
2600
+ ? "completed"
2601
+ : "pending",
2602
+ permissionMode: taskContracts.get(task.key)?.permissionMode,
2603
+ resourceBudget: {
2604
+ maxTurns: taskContracts.get(task.key)?.maxTurns,
2605
+ maxCostUsd: taskContracts.get(task.key)?.maxBudgetUsd,
2606
+ maxTokens: taskContracts.get(task.key)?.maxTokens,
2607
+ maxWallMs: taskContracts.get(task.key)?.maxWallMs,
2608
+ },
2609
+ checkpointRequired:
2610
+ taskContracts.get(task.key)?.checkpointRequired === true ||
2611
+ options.managedCheckpoint === true,
2612
+ worktreeRequired:
2613
+ taskContracts.get(task.key)?.worktreeRequired === true,
2614
+ scopePaths: task.metadata?.scopePaths || [],
2615
+ })),
2565
2616
  });
2566
2617
  } catch (err) {
2567
2618
  (log.error || console.error)(
@@ -2573,8 +2624,27 @@ export function registerTeamCommand(program, { logger } = {}) {
2573
2624
  const collaborationUnits = new Map(
2574
2625
  collaborationRun.units.map((unit) => [unit.key, unit]),
2575
2626
  );
2627
+ const teamGraphRunId =
2628
+ resumeSnapshot?.graphProjection?.runId || `team:${stateId}`;
2629
+ const teamGraphRevisionDigest =
2630
+ resumeSnapshot?.graphProjection?.revisionDigest ||
2631
+ computeTeamGraphRevisionDigest(reg);
2632
+ const teamGraphAuthorityDigest =
2633
+ resumeSnapshot?.graphProjection?.authorityDigest ||
2634
+ computeTeamGraphAuthorityDigest({
2635
+ stateId,
2636
+ permissionMode: options.agent ? permissionMode : "default",
2637
+ worktreeRequired: options.worktree === true,
2638
+ checkpointRequired:
2639
+ options.agent === true || options.managedCheckpoint === true,
2640
+ holders: Array.from(
2641
+ { length: Math.min(teammates, Math.max(1, reg.list().length)) },
2642
+ (_, index) => `teammate-${index + 1}`,
2643
+ ),
2644
+ });
2576
2645
  const settleGovernance = (key, status, extra = {}) => {
2577
- const unit = collaborationUnits.get(key);
2646
+ const governanceKey = sessionTaskKeyFor(key);
2647
+ const unit = collaborationUnits.get(governanceKey);
2578
2648
  let sideEffects = null;
2579
2649
  if (unit?.sessionId) {
2580
2650
  try {
@@ -2587,7 +2657,7 @@ export function registerTeamCommand(program, { logger } = {}) {
2587
2657
  }
2588
2658
  const updated = _deps.collaborationStore.updateUnit(
2589
2659
  collaborationRun.id,
2590
- key,
2660
+ governanceKey,
2591
2661
  {
2592
2662
  status,
2593
2663
  ...extra,
@@ -2595,7 +2665,7 @@ export function registerTeamCommand(program, { logger } = {}) {
2595
2665
  },
2596
2666
  { returnUnit: true },
2597
2667
  );
2598
- if (updated) collaborationUnits.set(key, updated);
2668
+ if (updated) collaborationUnits.set(governanceKey, updated);
2599
2669
  };
2600
2670
 
2601
2671
  // Persist a snapshot after each task settles so a crash mid-run is
@@ -2626,6 +2696,14 @@ export function registerTeamCommand(program, { logger } = {}) {
2626
2696
  adjudicationRunId,
2627
2697
  adjudicationCursor,
2628
2698
  execution: executionContract,
2699
+ graphProjection: projectTeamGraphCollaboration({
2700
+ runId: teamGraphRunId,
2701
+ mailbox,
2702
+ registry: reg,
2703
+ recipients: mailbox.status?.().recipients || [],
2704
+ revisionDigest: teamGraphRevisionDigest,
2705
+ authorityDigest: teamGraphAuthorityDigest,
2706
+ }),
2629
2707
  });
2630
2708
  };
2631
2709
 
@@ -2718,6 +2796,8 @@ export function registerTeamCommand(program, { logger } = {}) {
2718
2796
  sendMessage = null,
2719
2797
  messageAuthority = null,
2720
2798
  recipientState = null,
2799
+ requestFollowupWake = null,
2800
+ requestHandoff = null,
2721
2801
  mailbox: taskMailbox = null,
2722
2802
  budgetReservation = null,
2723
2803
  signal = null,
@@ -2728,7 +2808,7 @@ export function registerTeamCommand(program, { logger } = {}) {
2728
2808
  throw new Error(`task "${key}" has no \`prompt\` to --agent`);
2729
2809
  }
2730
2810
  const contract = applyBudgetReservation(
2731
- taskContracts.get(key),
2811
+ taskContractFor(key, task),
2732
2812
  budgetReservation,
2733
2813
  );
2734
2814
  return spawnAgent(
@@ -2743,7 +2823,9 @@ export function registerTeamCommand(program, { logger } = {}) {
2743
2823
  ? false
2744
2824
  : contract.checkpointRequired,
2745
2825
  managedCheckpoint,
2746
- sessionId: collaborationUnits.get(key)?.sessionId,
2826
+ sessionId: collaborationUnits.get(
2827
+ sessionTaskKeyFor(key, task),
2828
+ )?.sessionId,
2747
2829
  signal,
2748
2830
  ...(taskMailbox && holder
2749
2831
  ? {
@@ -2753,6 +2835,8 @@ export function registerTeamCommand(program, { logger } = {}) {
2753
2835
  sendMessage,
2754
2836
  assertAuthority: messageAuthority,
2755
2837
  recipientState,
2838
+ requestFollowupWake,
2839
+ requestHandoff,
2756
2840
  onMutation: persist,
2757
2841
  durable: Boolean(options.state),
2758
2842
  },
@@ -2775,9 +2859,10 @@ export function registerTeamCommand(program, { logger } = {}) {
2775
2859
  runTask = makeShellRunTask(log);
2776
2860
  } else if (options.agent)
2777
2861
  runTask = makeAgentRunTask({
2778
- contractForTask: (key) => taskContracts.get(key),
2862
+ contractForTask: (key, task) => taskContractFor(key, task),
2779
2863
  worktreeEnabled: false,
2780
- sessionIdForTask: (key) => collaborationUnits.get(key)?.sessionId,
2864
+ sessionIdForTask: (key, task) =>
2865
+ collaborationUnits.get(sessionTaskKeyFor(key, task))?.sessionId,
2781
2866
  onMailboxMutation: persist,
2782
2867
  mailboxDurable: Boolean(options.state),
2783
2868
  });
@@ -2838,7 +2923,7 @@ export function registerTeamCommand(program, { logger } = {}) {
2838
2923
  }
2839
2924
  const binding = adjudicationBindingFor(
2840
2925
  task,
2841
- collaborationUnits.get(key) || null,
2926
+ collaborationUnits.get(sessionTaskKeyFor(key, task)) || null,
2842
2927
  );
2843
2928
  const opened = adjudicationStore.openCase(binding, {
2844
2929
  anchor: adjudicationCursor,
@@ -2865,7 +2950,7 @@ export function registerTeamCommand(program, { logger } = {}) {
2865
2950
  runTask,
2866
2951
  budget,
2867
2952
  budgetForTask: options.agent
2868
- ? (task) => taskContracts.get(task.key)
2953
+ ? (task) => taskContractFor(task.key, task)
2869
2954
  : () => ({ reserveUsage: false }),
2870
2955
  mailbox,
2871
2956
  realtimeMessaging: options.agent === true,
@@ -2895,9 +2980,14 @@ export function registerTeamCommand(program, { logger } = {}) {
2895
2980
  ? "pending"
2896
2981
  : retry
2897
2982
  ? "pending"
2898
- : status;
2983
+ : options.agent === true && status === "completed"
2984
+ ? "running"
2985
+ : status;
2899
2986
  settleGovernance(key, governanceStatus, {
2900
- endedAt: governanceStatus === "pending" ? null : Date.now(),
2987
+ endedAt:
2988
+ governanceStatus === "pending" || governanceStatus === "running"
2989
+ ? null
2990
+ : Date.now(),
2901
2991
  });
2902
2992
  ensureTaskAdjudicationCase(key);
2903
2993
  persist();
@@ -2905,6 +2995,14 @@ export function registerTeamCommand(program, { logger } = {}) {
2905
2995
  onLeaseChanged: () => {
2906
2996
  persist();
2907
2997
  },
2998
+ onFollowupMutation: () => {
2999
+ persist();
3000
+ },
3001
+ onHandoffMutation: () => {
3002
+ persist();
3003
+ },
3004
+ graphRevisionDigest: teamGraphRevisionDigest,
3005
+ graphAuthorityDigest: teamGraphAuthorityDigest,
2908
3006
  onEvent: (e) => {
2909
3007
  if (options.json) console.log(JSON.stringify(e));
2910
3008
  else if (e.type === "task:claimed")
@@ -3011,18 +3109,32 @@ export function registerTeamCommand(program, { logger } = {}) {
3011
3109
  persist();
3012
3110
  let governanceFailed = false;
3013
3111
  try {
3014
- // Reconcile only units whose authoritative registry state differs.
3015
- // Per-task hooks already durably settled the common path.
3112
+ // Follow-up wake tasks are new lease-bound turns in the same durable
3113
+ // collaboration session/unit as their source task. Aggregate every
3114
+ // such turn before making the unit terminal; otherwise the first
3115
+ // completed turn would freeze governance before a later follow-up.
3116
+ const tasksByGovernanceKey = new Map(
3117
+ [...collaborationUnits.keys()].map((key) => [key, []]),
3118
+ );
3016
3119
  for (const task of reg.list()) {
3017
- const state = String(task.status || "").toLowerCase();
3120
+ const governanceKey = sessionTaskKeyFor(task.key, task);
3121
+ tasksByGovernanceKey.get(governanceKey)?.push(task);
3122
+ }
3123
+ for (const [key, tasks] of tasksByGovernanceKey) {
3124
+ const states = tasks.map((task) =>
3125
+ String(task.status || "").toLowerCase(),
3126
+ );
3018
3127
  const status =
3019
- state === "completed"
3128
+ states.length > 0 &&
3129
+ states.every((state) => state === "completed")
3020
3130
  ? "completed"
3021
- : state === "cancelled" || state === "pending"
3131
+ : states.some(
3132
+ (state) => state === "cancelled" || state === "pending",
3133
+ )
3022
3134
  ? "cancelled"
3023
3135
  : "failed";
3024
- if (collaborationUnits.get(task.key)?.status === status) continue;
3025
- settleGovernance(task.key, status, {
3136
+ if (collaborationUnits.get(key)?.status === status) continue;
3137
+ settleGovernance(key, status, {
3026
3138
  endedAt: Date.now(),
3027
3139
  });
3028
3140
  }
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.166.4",
7
+ "cliVersions": ["0.1.4", "0.2.3", "0.166.3", "0.166.4"],
8
+ "date": "2026-08-26",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Added - cc CLI 0.166.4 + Agent Protocol 0.1.4 + Agent SDKs 0.2.3: canonical stream event inventory",
13
+ "body": "> `chainlesschain` **0.166.3 -> 0.166.4**,\n> `@chainlesschain/agent-protocol` **0.1.3 -> 0.1.4**,\n> `@chainlesschain/agent-sdk` **0.2.2 -> 0.2.3**, and\n> `chainlesschain-agent-sdk` **0.2.2 -> 0.2.3** (release candidate,\n> 2026-08-26).\n\n- **One event discriminator inventory**: the canonical JSON Schema now owns\n all currently emitted Agent stdout event types, including Hook, subagent,\n recovery, budget, structured-result, and interaction rejection events.\n- **Generated cross-language contract**: TypeScript and Python receive the\n event literal inventory, envelope type, and validator; Kotlin and Swift\n receive generated event enums and typed envelopes from the same definition.\n- **Forward compatibility retained**: SDK transports continue to preserve\n unknown future events. The new known-event guard is opt-in and does not turn\n additive provider/runtime events into transport failures.\n- **Shared conformance**: legal and illegal event envelopes run through the\n protocol, TypeScript SDK, and Python SDK validators; generated-output drift,\n invalid metadata, and explicit non-JSON values fail the release gate.\n- **Release validation**: publication requires this exact candidate to pass\n Agent Protocol and Python SDK conformance, Linux/Windows/macOS `CLI CI` and\n `CLI Strict Sandbox`, and the IDE extension matrix before immutable OIDC\n release tags are created."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "productVersion": null,
19
+ "cliVersion": "0.166.3",
20
+ "cliVersions": ["0.1.2", "0.2.2", "0.166.2", "0.166.3"],
21
+ "date": "2026-08-25",
22
+ "title": "",
23
+ "sections": [
24
+ {
25
+ "heading": "Added - cc CLI 0.166.3 + Agent Protocol 0.1.2 + Agent SDKs 0.2.2: scoped approvals and durable team authority",
26
+ "body": "> `chainlesschain` **0.166.2 -> 0.166.3**,\n> `@chainlesschain/agent-protocol` **0.1.1 -> 0.1.2**,\n> `@chainlesschain/agent-sdk` **0.2.1 -> 0.2.2**, and\n> `chainlesschain-agent-sdk` **0.2.1 -> 0.2.2** (release candidate,\n> 2026-08-25).\n\n- **Canonical approval contract**: the protocol package exports schema-derived\n JavaScript validators and deterministic TypeScript/Python bindings for\n `acceptOnce`, `acceptForTurn`, `acceptForSession`, `decline`, and `cancel`.\n Shared valid/invalid fixtures keep the protocol, both SDKs, and CLI App\n Server on one wire contract.\n- **Fail-closed, exactly scoped grants**: approval responses bind the request,\n requested permission, tool, arguments, working directory, and policy digest.\n Turn grants stay in memory; session grants become effective only after a\n tamper-evident authority event is persisted and verified. Expired, corrupt,\n mismatched, widened, or persistence-failed grants never silently authorize a\n call.\n- **N-1 SDK compatibility**: boolean callbacks normalize to one-shot canonical\n decisions with the request binding, while direct boolean responses retain\n the legacy wire for older callers. Invalid or throwing callbacks decline\n safely in both TypeScript and Python.\n- **Durable Team messaging and custody**: state-backed Team runs now use the\n `SessionMessageFabric` authority for bounded cross-process delivery,\n offline/reconnect, receipts, fencing, dead letters, rate limits, and legacy\n mailbox migration. Idle follow-up turns and offer/accept/commit handoffs keep\n stable message identity while transferring attempt/lease custody explicitly.\n- **Release validation**: publication requires the exact release commit to pass\n Agent Protocol and Python SDK conformance, Linux/Windows/macOS `CLI CI` and\n `CLI Strict Sandbox`, and the desktop E2E matrix before immutable OIDC tags\n are created."
27
+ }
28
+ ]
29
+ },
4
30
  {
5
31
  "productVersion": null,
6
32
  "cliVersion": "0.166.2",
@@ -17,6 +17,10 @@ import {
17
17
  } from "../../lib/agent-authority.js";
18
18
  import { hasCompleteInteractionBinding } from "../../lib/interaction-binding.js";
19
19
  import { REMOTE_MEMBERSHIP_NOT_ACTIVE_CODE } from "../../lib/remote-membership-coordinator.js";
20
+ import {
21
+ REMOTE_APPROVAL_DECISION_CAPABILITY,
22
+ requireRemoteApprovalDecision,
23
+ } from "../../lib/remote-approval-decision.js";
20
24
 
21
25
  const CLIENT_EVENT_SCOPES = Object.freeze({
22
26
  prompt: "prompt",
@@ -918,7 +922,14 @@ export async function handleRemoteSessionPublish(
918
922
  // fail-safe). The envelope also feeds `describeAuthorityChain` provenance
919
923
  // into the audit trail below.
920
924
  let approvalEnvelope = null;
925
+ let approvalDecision = null;
921
926
  if (message.event.type === "approval.resolve") {
927
+ approvalDecision = requireRemoteApprovalDecision(message.event, {
928
+ requireCanonical:
929
+ member.capabilities?.includes(
930
+ REMOTE_APPROVAL_DECISION_CAPABILITY,
931
+ ) === true,
932
+ });
922
933
  approvalEnvelope = {
923
934
  origin: ORIGIN.REMOTE,
924
935
  authenticated: true,
@@ -934,8 +945,7 @@ export async function handleRemoteSessionPublish(
934
945
  }
935
946
  : {}),
936
947
  };
937
- const approved = message.event.answer ?? message.event.approved;
938
- if (approved === true || approved === "true" || approved === "yes") {
948
+ if (approvalDecision.approved) {
939
949
  assertCanApprove(approvalEnvelope);
940
950
  if (session.hostPrincipalId) {
941
951
  requireRemoteApprovalRequest(server, session, message.event);
@@ -974,10 +984,7 @@ export async function handleRemoteSessionPublish(
974
984
  } else if (
975
985
  session.hostPrincipalId &&
976
986
  message.event.type === "approval.resolve" &&
977
- (message.event.answer === true ||
978
- message.event.answer === "true" ||
979
- message.event.answer === "yes" ||
980
- message.event.approved === true)
987
+ approvalDecision.approved
981
988
  ) {
982
989
  throw new Error(
983
990
  "Server-hosted remote approval is disabled until its dispatch path consumes a durable lease",
@@ -995,17 +1002,12 @@ export async function handleRemoteSessionPublish(
995
1002
  message.event.type === "approval.resolve" &&
996
1003
  !serverHosted
997
1004
  ) {
998
- const rawDecision = message.event.answer ?? message.event.approved;
999
- const approved =
1000
- rawDecision === true ||
1001
- rawDecision === "true" ||
1002
- rawDecision === "yes";
1003
1005
  const request = requireRemoteApprovalRequest(
1004
1006
  server,
1005
1007
  session,
1006
1008
  message.event,
1007
1009
  );
1008
- if (approved) {
1010
+ if (approvalDecision.approved) {
1009
1011
  approvalLease = server
1010
1012
  ._requireRemoteMembershipCoordinator()
1011
1013
  .createApprovalLease({
@@ -1046,7 +1048,8 @@ export async function handleRemoteSessionPublish(
1046
1048
  ? {
1047
1049
  requestId:
1048
1050
  message.event.requestId || message.event.approvalId,
1049
- approved: message.event.answer ?? message.event.approved,
1051
+ approved: approvalDecision.approved,
1052
+ decisionKind: approvalDecision.kind,
1050
1053
  // Log-safe provenance: which principal/session/authority.
1051
1054
  authority: describeAuthorityChain(approvalEnvelope || {}),
1052
1055
  forwarded: true,
@@ -1098,6 +1101,7 @@ export async function handleRemoteSessionPublish(
1098
1101
  membershipAuthority: membership.authorityVersion,
1099
1102
  sessionEpoch: membership.sessionEpoch,
1100
1103
  membershipEpoch: membership.membershipEpoch,
1104
+ memberCapabilities: [...(member.capabilities || [])],
1101
1105
  }
1102
1106
  : {}),
1103
1107
  event: message.event,
@@ -1131,7 +1135,8 @@ export async function handleRemoteSessionPublish(
1131
1135
  action: "control.approval",
1132
1136
  detail: {
1133
1137
  requestId: message.event.requestId || message.event.approvalId,
1134
- approved: message.event.answer ?? message.event.approved,
1138
+ approved: approvalDecision.approved,
1139
+ decisionKind: approvalDecision.kind,
1135
1140
  // Log-safe provenance: which principal/session/authority approved.
1136
1141
  authority: describeAuthorityChain(approvalEnvelope || {}),
1137
1142
  },
@@ -1139,7 +1144,7 @@ export async function handleRemoteSessionPublish(
1139
1144
  await handleSessionAnswer(server, message.id, ws, {
1140
1145
  ...controlMessage,
1141
1146
  requestId: message.event.requestId || message.event.approvalId,
1142
- answer: message.event.answer ?? message.event.approved,
1147
+ answer: approvalDecision.approved,
1143
1148
  // Echoed approval binding (if any): the host interaction gate rejects
1144
1149
  // a verdict whose binding doesn't match the pending request.
1145
1150
  binding: message.event.binding ?? null,
@@ -14,7 +14,8 @@
14
14
  "durable_human_task",
15
15
  "bounded_transport",
16
16
  "graph_effect_receipts",
17
- "deterministic_trace"
17
+ "deterministic_trace",
18
+ "agent_stream_events"
18
19
  ]
19
20
  },
20
21
  "oneOf": [
@@ -1782,6 +1783,71 @@
1782
1783
  }
1783
1784
  }
1784
1785
  },
1786
+ "AgentStreamEventType": {
1787
+ "enum": [
1788
+ "approval_request",
1789
+ "approval_resolved",
1790
+ "checkpoint",
1791
+ "compaction",
1792
+ "compaction-degraded",
1793
+ "compaction_usage_unknown",
1794
+ "cost_budget_exhausted",
1795
+ "elicitation_complete",
1796
+ "elicitation_deferred",
1797
+ "feedback_ack",
1798
+ "hook_progress",
1799
+ "hook_response",
1800
+ "hook_started",
1801
+ "iteration_budget_exhausted",
1802
+ "iteration_warning",
1803
+ "plan_update",
1804
+ "question_request",
1805
+ "question_resolved",
1806
+ "question_response_rejected",
1807
+ "raw",
1808
+ "recovery_degraded",
1809
+ "remote_control",
1810
+ "result",
1811
+ "resume_ack",
1812
+ "session_error",
1813
+ "slash_command_result",
1814
+ "stream_event",
1815
+ "stream_retry",
1816
+ "structured_result",
1817
+ "subagent_completed",
1818
+ "subagent_progress",
1819
+ "subagent_started",
1820
+ "system",
1821
+ "token_usage",
1822
+ "tool_result",
1823
+ "tool_use",
1824
+ "user"
1825
+ ]
1826
+ },
1827
+ "AgentStreamEventEnvelope": {
1828
+ "type": "object",
1829
+ "required": [
1830
+ "type"
1831
+ ],
1832
+ "properties": {
1833
+ "type": {
1834
+ "$ref": "#/$defs/AgentStreamEventType"
1835
+ },
1836
+ "seq": {
1837
+ "type": "integer",
1838
+ "minimum": 1
1839
+ },
1840
+ "trace_id": {
1841
+ "type": "string",
1842
+ "minLength": 1,
1843
+ "maxLength": 128,
1844
+ "pattern": "^[A-Za-z0-9._:-]+$"
1845
+ }
1846
+ },
1847
+ "additionalProperties": {
1848
+ "$ref": "#/$defs/JsonValue"
1849
+ }
1850
+ },
1785
1851
  "InitializeParams": {
1786
1852
  "type": "object",
1787
1853
  "additionalProperties": false,