chainlesschain 0.162.188 → 0.162.193

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 (337) hide show
  1. package/README.md +61 -11
  2. package/bin/chainlesschain.js +7 -52
  3. package/completions/_cc +209 -0
  4. package/completions/cc.bash +18 -0
  5. package/completions/cc.fish +13 -0
  6. package/completions/cc.ps1 +226 -0
  7. package/package.json +10 -2
  8. package/src/assets/web-panel/assets/{AIOps-Brr1LVcE.js → AIOps-DBLkaTje.js} +1 -1
  9. package/src/assets/web-panel/assets/{ActionButton-DQU74DKG.js → ActionButton-BAy-Qebo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Analytics-CYp9178y.js → Analytics-Dfb1Mlau.js} +3 -3
  11. package/src/assets/web-panel/assets/{AppLayout-DW4SCYsW.js → AppLayout-BbFkN8m0.js} +5 -5
  12. package/src/assets/web-panel/assets/{Artifacts-CYlD_ed1.js → Artifacts-kM4-cEEH.js} +1 -1
  13. package/src/assets/web-panel/assets/{Audit-CWl1rZOi.js → Audit-BSQfYWf3.js} +1 -1
  14. package/src/assets/web-panel/assets/{BackgroundAgents-BOR-LPsa.js → BackgroundAgents-CWDbI_fG.js} +1 -1
  15. package/src/assets/web-panel/assets/{Backup-DLpG7j1X.js → Backup-BxLPbq_Q.js} +1 -1
  16. package/src/assets/web-panel/assets/{BaseInput-B35K9wdr.js → BaseInput-DuIbdrp6.js} +1 -1
  17. package/src/assets/web-panel/assets/{Chat-CwUJb9gB.js → Chat-NEmjGahU.js} +5 -5
  18. package/src/assets/web-panel/assets/{ChatBubbleRenderer-1v6aMS1m.js → ChatBubbleRenderer-DfJEo-5_.js} +1 -1
  19. package/src/assets/web-panel/assets/{Checkbox-pi3-tPNW.js → Checkbox-CaoeG3Ns.js} +1 -1
  20. package/src/assets/web-panel/assets/{Codegen-FyNF35eL.js → Codegen-BFf_g3xY.js} +1 -1
  21. package/src/assets/web-panel/assets/{Col-tGt_JDEr.js → Col-CNOd8mdQ.js} +1 -1
  22. package/src/assets/web-panel/assets/{Community-CC7LonQX.js → Community-BhpDqz-i.js} +1 -1
  23. package/src/assets/web-panel/assets/{Compact-BGXrHHjE.js → Compact-CQ42T7Z6.js} +1 -1
  24. package/src/assets/web-panel/assets/{Compliance-DSW0TBZ8.js → Compliance-DI5PcLMN.js} +1 -1
  25. package/src/assets/web-panel/assets/{Cowork-Bhk7rbvE.js → Cowork-wYYZe0wR.js} +3 -3
  26. package/src/assets/web-panel/assets/{Cron-DxyiQ2NZ.js → Cron-Dlq03DD_.js} +2 -2
  27. package/src/assets/web-panel/assets/{Crosschain-B2ZkxHok.js → Crosschain-BzqS8PP3.js} +1 -1
  28. package/src/assets/web-panel/assets/{DID-yOJV99eJ.js → DID-It55Yem7.js} +2 -2
  29. package/src/assets/web-panel/assets/{Dashboard-CKsttz7D.js → Dashboard-9HkH6oxn.js} +2 -2
  30. package/src/assets/web-panel/assets/{Dropdown-CVFldXSL.js → Dropdown-00e2YWRB.js} +1 -1
  31. package/src/assets/web-panel/assets/{EmailListRenderer-Bufv638J.js → EmailListRenderer-By-ugRDL.js} +1 -1
  32. package/src/assets/web-panel/assets/{FamilyGuardDashboard-4ncjoIjL.js → FamilyGuardDashboard-C396yu5m.js} +1 -1
  33. package/src/assets/web-panel/assets/{Federation-DsknEDoX.js → Federation-BME5sbZY.js} +1 -1
  34. package/src/assets/web-panel/assets/{FormItemContext-Cqe5jWXA.js → FormItemContext-B4TEZCr-.js} +1 -1
  35. package/src/assets/web-panel/assets/{GenericCardRenderer-NAJaFKxc.js → GenericCardRenderer-_9CX9ieY.js} +1 -1
  36. package/src/assets/web-panel/assets/{Git-CszKQpnl.js → Git-BrS6WVSr.js} +2 -2
  37. package/src/assets/web-panel/assets/{Governance-BXGodXi6.js → Governance-BMdCWnKF.js} +1 -1
  38. package/src/assets/web-panel/assets/{Inference-CkoYuG2c.js → Inference-Bcp3vzcA.js} +1 -1
  39. package/src/assets/web-panel/assets/{KnowledgeGraph-DFlEr_T0.js → KnowledgeGraph-DlLuqGY5.js} +1 -1
  40. package/src/assets/web-panel/assets/{Logs-CVaENddA.js → Logs-D-W_6x09.js} +2 -2
  41. package/src/assets/web-panel/assets/MarkdownRenderer-DElGPxCZ.js +1 -0
  42. package/src/assets/web-panel/assets/{Marketplace-CDlLT0fw.js → Marketplace-Dzn2guvI.js} +1 -1
  43. package/src/assets/web-panel/assets/{McpTools-DdwOyszN.js → McpTools-uPict-KL.js} +6 -6
  44. package/src/assets/web-panel/assets/{Memory-DKQnkKuG.js → Memory-BCw43kOb.js} +2 -2
  45. package/src/assets/web-panel/assets/{MobileBridge-DGseqlzJ.js → MobileBridge-DmV8Wv7F.js} +1 -1
  46. package/src/assets/web-panel/assets/{MobileProjects-COBbEOlj.js → MobileProjects-C-HaCmSM.js} +1 -1
  47. package/src/assets/web-panel/assets/{Mtc-O61Vwyli.js → Mtc-C6jxJ34Y.js} +5 -5
  48. package/src/assets/web-panel/assets/{MtcAudit-Dw2SyasS.js → MtcAudit-Za8ExwhQ.js} +5 -5
  49. package/src/assets/web-panel/assets/{Multisig-hSu_l8kf.js → Multisig-KKDbuEgb.js} +3 -3
  50. package/src/assets/web-panel/assets/{NLProgramming-CX1Epurr.js → NLProgramming-Dj97zbCk.js} +1 -1
  51. package/src/assets/web-panel/assets/{Notes-R9xX8o8_.js → Notes-DBXvMraU.js} +4 -4
  52. package/src/assets/web-panel/assets/{NotificationSettings-jtSNLCuK.js → NotificationSettings-DOxITLYl.js} +1 -1
  53. package/src/assets/web-panel/assets/OrderTableRenderer-7DVjZwMM.js +1 -0
  54. package/src/assets/web-panel/assets/{Organization-Pu2WO-U3.js → Organization-D1i73mjb.js} +4 -4
  55. package/src/assets/web-panel/assets/{Overflow-BjnqUyFp.js → Overflow-kW6Q3rvg.js} +1 -1
  56. package/src/assets/web-panel/assets/{P2P-jjkvz44c.js → P2P-C-v_8p2v.js} +2 -2
  57. package/src/assets/web-panel/assets/PdhVaultBrowser-tUbbY64W.js +7 -0
  58. package/src/assets/web-panel/assets/{Permissions-D4yDpivd.js → Permissions-DkHxEZ58.js} +4 -4
  59. package/src/assets/web-panel/assets/{PersonalDataHub-0qsL6iH1.js → PersonalDataHub-DWuMPGrK.js} +5 -5
  60. package/src/assets/web-panel/assets/{Pipeline-Cx7Ybrk2.js → Pipeline-30IYXWWm.js} +1 -1
  61. package/src/assets/web-panel/assets/{Privacy-PbfR_M_V.js → Privacy-DZNQ4RrH.js} +1 -1
  62. package/src/assets/web-panel/assets/{ProjectInit-CyV6Gsub.js → ProjectInit-De2MCElf.js} +2 -2
  63. package/src/assets/web-panel/assets/{ProjectSettings-C7KZ2Wdk.js → ProjectSettings-5uHk9wsC.js} +2 -2
  64. package/src/assets/web-panel/assets/{Projects-DQDjO-yK.js → Projects-XjDfrFLb.js} +1 -1
  65. package/src/assets/web-panel/assets/{Providers-DyFVBBMX.js → Providers-Bgwj6gcE.js} +1 -1
  66. package/src/assets/web-panel/assets/{QrScannerModal-CzB1BC9_.js → QrScannerModal-gKql9umv.js} +1 -1
  67. package/src/assets/web-panel/assets/{QuickAsk-Bk636mC1.js → QuickAsk-BWvmwkh7.js} +1 -1
  68. package/src/assets/web-panel/assets/{Recommend-DoWxHIT3.js → Recommend-Uok4hZPd.js} +1 -1
  69. package/src/assets/web-panel/assets/{RemoteSession-oOVIv9wq.js → RemoteSession-DLJzTk9a.js} +3 -3
  70. package/src/assets/web-panel/assets/{Reputation-BucoReGG.js → Reputation-ZVwIPMSO.js} +1 -1
  71. package/src/assets/web-panel/assets/{Row-DzmOdJU7.js → Row-CN04HxWR.js} +1 -1
  72. package/src/assets/web-panel/assets/{RssFeed-C1tK7KGU.js → RssFeed-BdSrEG4g.js} +3 -3
  73. package/src/assets/web-panel/assets/{Search-CSnInOqk.js → Search-5PwVd0IR.js} +1 -1
  74. package/src/assets/web-panel/assets/{Security-dlejr15l.js → Security-DdBo4zjN.js} +3 -3
  75. package/src/assets/web-panel/assets/{Services-BioPZuNh.js → Services-D3letU7M.js} +2 -2
  76. package/src/assets/web-panel/assets/{Skeleton-DWMibwpC.js → Skeleton--Jb83f1v.js} +1 -1
  77. package/src/assets/web-panel/assets/{Skills-BAAnx1B2.js → Skills-Bg-CulHX.js} +1 -1
  78. package/src/assets/web-panel/assets/{Sla-jWNp4hNO.js → Sla-7QOa7S-X.js} +1 -1
  79. package/src/assets/web-panel/assets/{SpeechSettings-y5kqKha-.js → SpeechSettings-DQwppjRw.js} +1 -1
  80. package/src/assets/web-panel/assets/{SyncSettings-B9GNsc3e.js → SyncSettings-dNPQGL-s.js} +2 -2
  81. package/src/assets/web-panel/assets/{Tasks-BDBYKRen.js → Tasks-Ggs-Z48q.js} +1 -1
  82. package/src/assets/web-panel/assets/{Templates-DRiE5eaN.js → Templates-78TYHgRO.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tenant-BGlAvExF.js → Tenant-xHwwv9vO.js} +1 -1
  84. package/src/assets/web-panel/assets/{Terminal-B8uzrbNY.js → Terminal-BJXSJfm4.js} +2 -2
  85. package/src/assets/web-panel/assets/{TimelineRenderer-Df48iveY.js → TimelineRenderer-fLbjRhJw.js} +1 -1
  86. package/src/assets/web-panel/assets/{Tokens-CcmHndN6.js → Tokens-oMSBSBmB.js} +1 -1
  87. package/src/assets/web-panel/assets/{Trigger-DPkWxmQ2.js → Trigger-CfnY_wX_.js} +1 -1
  88. package/src/assets/web-panel/assets/{Trust-DTb5a5AV.js → Trust-AdyTgYKO.js} +1 -1
  89. package/src/assets/web-panel/assets/{UkeySign-CBmg5vch.js → UkeySign-C5K_81dS.js} +1 -1
  90. package/src/assets/web-panel/assets/{VideoEditing-B0mZrz4O.js → VideoEditing-vcGVDqki.js} +1 -1
  91. package/src/assets/web-panel/assets/{Wallet-Bxs7_mpd.js → Wallet-hhOc3hlY.js} +4 -4
  92. package/src/assets/web-panel/assets/{WebAuthn-C8x3cMxU.js → WebAuthn-CVloC11s.js} +3 -3
  93. package/src/assets/web-panel/assets/{WorkflowEditor-DPrNznrP.js → WorkflowEditor-CYeE32R5.js} +1 -1
  94. package/src/assets/web-panel/assets/{chat-D3bYWu7S.js → chat-CNROR5bN.js} +1 -1
  95. package/src/assets/web-panel/assets/{colors-DY-PwMu4.js → colors-Cjx-cnwU.js} +1 -1
  96. package/src/assets/web-panel/assets/{compact-item-LDk10Kw6.js → compact-item-DOIfelvD.js} +1 -1
  97. package/src/assets/web-panel/assets/{createContext-C-2MZnFq.js → createContext-DfA7UZ8u.js} +1 -1
  98. package/src/assets/web-panel/assets/devWarning-ChcCBGs7.js +1 -0
  99. package/src/assets/web-panel/assets/{hasIn-BQIBjcnB.js → hasIn-BMSCzcfM.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CQVb2dWp.js → index-5-HXgOX5.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BdXnYMCZ.js → index-AWg-0M1S.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cx6D_dx2.js → index-B4iYzpkL.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-_HRO_cIu.js → index-B5Udeb_6.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DlRYqt3S.js → index-B7gf77CJ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BrnRO9yE.js → index-BEMwBBHk.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-VCh5zNJo.js → index-BM1y_9hM.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BRI3ngNg.js → index-BUonmKSE.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C3GNvExG.js → index-BbQ2eQ8H.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DSvo_bp0.js → index-BemJ2u_E.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-L6qixyLc.js → index-BolaOQxx.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BI4KgcYC.js → index-BxOk9vkG.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CY4KnaO9.js → index-By61ojUx.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-L3smcoQX.js → index-C2K9SNVX.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BX2b9Orc.js → index-C3L5gdiD.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Cz4b6Z_7.js → index-C7xn0Nub.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-COG61sRv.js → index-CAnvhwg6.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-C7FC8cP2.js → index-CEKMcOyU.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BN-xdSWZ.js → index-CNC5onm4.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DY2FIrmz.js → index-CVL27kXC.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CiTvBAr-.js → index-CVm1_i3t.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DhRt9cYJ.js → index-CdYBye8B.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B5pgtZnY.js → index-ClNMrqEY.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-7xKu7Fns.js → index-Cs6l7uRu.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-D4K1weKc.js → index-CshQbilz.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-k7C_oDCO.js → index-Cyweh0Hy.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D3Oq-DLL.js → index-DBpWXFed.js} +3 -3
  127. package/src/assets/web-panel/assets/{index-DYyLJPlF.js → index-DHtpHZAQ.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Dh-tkpKQ.js → index-DLmn0BoK.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-8JC9BJa1.js → index-DPAWBrMf.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Dd2Km97U.js → index-DjEsxO5h.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-KFZO_lcx.js → index-FBc_CJBd.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DTIZpPtG.js → index-Icdoqmzt.js} +1 -1
  133. package/src/assets/web-panel/assets/index-Q2IajL54.js +1 -0
  134. package/src/assets/web-panel/assets/index-bRkHgOMc.js +1 -0
  135. package/src/assets/web-panel/assets/{index-lmm9p-jm.js → index-dCd8cSUq.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-HasPt4-h.js → index-m2vG9gG_.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-CaslYch6.js → index-mTpHoEzr.js} +1 -1
  138. package/src/assets/web-panel/assets/{index-CbR6ROOa.js → index-ti_lnTWl.js} +1 -1
  139. package/src/assets/web-panel/assets/{initDefaultProps-zQPSHf2C.js → initDefaultProps-Bu8k7H1Y.js} +1 -1
  140. package/src/assets/web-panel/assets/{motion-CKCStGVk.js → motion-s3iVK41k.js} +1 -1
  141. package/src/assets/web-panel/assets/{move-BufVDGYF.js → move-B6B-E5Jz.js} +1 -1
  142. package/src/assets/web-panel/assets/{mtc-parser-DcaFxy5D.js → mtc-parser-BiYgTidA.js} +1 -1
  143. package/src/assets/web-panel/assets/{omit-EScpkGdo.js → omit-pU1RdUDA.js} +1 -1
  144. package/src/assets/web-panel/assets/{pickAttrs-72hG_qfT.js → pickAttrs-Cdoq_SeM.js} +1 -1
  145. package/src/assets/web-panel/assets/{placementArrow-CMFWiH20.js → placementArrow-DIuvAn2K.js} +1 -1
  146. package/src/assets/web-panel/assets/{responsiveObserve-DKQHS41p.js → responsiveObserve-8w16YR2D.js} +1 -1
  147. package/src/assets/web-panel/assets/{slide-QVAFHTIQ.js → slide-VZ01cZe3.js} +1 -1
  148. package/src/assets/web-panel/assets/{statusUtils-DIz38e2G.js → statusUtils-lh8YMN8Z.js} +1 -1
  149. package/src/assets/web-panel/assets/{styleChecker-zK5cyLby.js → styleChecker-CmDyreec.js} +1 -1
  150. package/src/assets/web-panel/assets/{useFlexGapSupport-DhZngk62.js → useFlexGapSupport-hiJWMU5y.js} +1 -1
  151. package/src/assets/web-panel/assets/{useFs-BvV2cvkg.js → useFs-Thnu-Iaj.js} +1 -1
  152. package/src/assets/web-panel/assets/{usePersonalDataHub-CRmxb9l3.js → usePersonalDataHub-LBdOxjwY.js} +1 -1
  153. package/src/assets/web-panel/assets/{vnode-CgQIbobP.js → vnode-Cg6lFY_X.js} +1 -1
  154. package/src/assets/web-panel/assets/{zoom-D4XrrO0R.js → zoom-DVfsR1YO.js} +1 -1
  155. package/src/assets/web-panel/index.html +1 -1
  156. package/src/cli-help.js +181 -0
  157. package/src/command-help-index.json +181 -0
  158. package/src/command-manifest.json +1107 -175
  159. package/src/command-surface-policy.js +197 -0
  160. package/src/commands/agent.js +98 -33
  161. package/src/commands/artifacts.js +400 -2
  162. package/src/commands/background-session.js +41 -3
  163. package/src/commands/checkpoint-managed.js +1059 -0
  164. package/src/commands/checkpoint-restore-recovery.js +1476 -0
  165. package/src/commands/checkpoint.js +950 -22
  166. package/src/commands/compact.js +101 -25
  167. package/src/commands/config.js +506 -20
  168. package/src/commands/doctor.js +4 -1
  169. package/src/commands/hub.js +1 -1
  170. package/src/commands/mcp.js +688 -24
  171. package/src/commands/pack.js +16 -2
  172. package/src/commands/plugin.js +20 -12
  173. package/src/commands/session-mcp-recovery.js +218 -0
  174. package/src/commands/session.js +470 -110
  175. package/src/commands/setup.js +36 -10
  176. package/src/commands/skill.js +181 -110
  177. package/src/commands/status.js +21 -5
  178. package/src/commands/team-distributed.js +3324 -0
  179. package/src/commands/team.js +1130 -74
  180. package/src/commands/update.js +68 -6
  181. package/src/constants.js +11 -0
  182. package/src/data/changelog.json +26 -0
  183. package/src/gateways/ws/action-protocol.js +10 -0
  184. package/src/gateways/ws/session-protocol.js +555 -27
  185. package/src/gateways/ws/ws-agent-handler.js +541 -14
  186. package/src/gateways/ws/ws-session-gateway.js +129 -22
  187. package/src/gateways/ws/ws-session-state.js +431 -0
  188. package/src/harness/background-task-manager.js +233 -36
  189. package/src/harness/jsonl-session-store.js +2551 -167
  190. package/src/harness/mcp-client.js +802 -61
  191. package/src/harness/prompt-compressor.js +227 -27
  192. package/src/harness/session-index.js +89 -38
  193. package/src/harness/session-list-index.js +254 -0
  194. package/src/harness/structured-handoff.js +410 -0
  195. package/src/lazy-dispatch.js +747 -84
  196. package/src/lib/__tests__/logger.test.js +50 -2
  197. package/src/lib/advisor-runtime.js +1047 -0
  198. package/src/lib/agent-core.js +2 -0
  199. package/src/lib/agent-sandbox.js +120 -26
  200. package/src/lib/agent-session-export.js +20 -0
  201. package/src/lib/agent-team/task-lease.js +271 -3
  202. package/src/lib/agent-team/team-adjudication.js +1501 -0
  203. package/src/lib/agent-team/team-budget.js +4 -1
  204. package/src/lib/agent-team/team-control-store.js +582 -0
  205. package/src/lib/agent-team/team-distributed-queue.js +5246 -0
  206. package/src/lib/agent-team/team-process-checkpoint.js +211 -0
  207. package/src/lib/agent-team/team-runner.js +543 -24
  208. package/src/lib/agent-team/team-worktree.js +1403 -95
  209. package/src/lib/artifact-store.js +131 -8
  210. package/src/lib/background-agent-supervisor.js +185 -13
  211. package/src/lib/background-interaction-journal.js +37 -9
  212. package/src/lib/background-launch-profile.js +1058 -0
  213. package/src/lib/checkpoint-restore-already-completed-controller.js +902 -0
  214. package/src/lib/checkpoint-restore-orchestrator.js +987 -0
  215. package/src/lib/checkpoint-restore-partial-rollback-controller.js +1953 -0
  216. package/src/lib/checkpoint-restore-recovery-controller.js +689 -0
  217. package/src/lib/checkpoint-restore-recovery.js +884 -0
  218. package/src/lib/checkpoint-restore-retention.js +126 -0
  219. package/src/lib/checkpoint-restore-saga.js +5079 -0
  220. package/src/lib/checkpoint-restore-session-recovery.js +1178 -0
  221. package/src/lib/checkpoint-restore-workspace-target-verifier.js +270 -0
  222. package/src/lib/checkpoint-store.js +1688 -97
  223. package/src/lib/checkpoint-timeline-authority.js +522 -0
  224. package/src/lib/checkpoint-timeline.js +642 -0
  225. package/src/lib/config-keys.js +18 -119
  226. package/src/lib/config-manager.js +446 -27
  227. package/src/lib/config-redaction.js +57 -0
  228. package/src/lib/config-schema.js +853 -0
  229. package/src/lib/cowork-mcp-tools.js +5 -0
  230. package/src/lib/cowork-task-runner.js +458 -63
  231. package/src/lib/delivery-coordinator.js +1234 -0
  232. package/src/lib/delivery-evidence.js +450 -0
  233. package/src/lib/doctor-checkup.js +199 -14
  234. package/src/lib/executable-path.js +34 -0
  235. package/src/lib/fatal-handler.js +16 -0
  236. package/src/lib/file-checkpoint.js +4909 -186
  237. package/src/lib/file-lines.js +125 -0
  238. package/src/lib/headless-config-command.js +16 -5
  239. package/src/lib/hook-runner.cjs +139 -38
  240. package/src/lib/hooks-v2-workspace-context.js +10 -0
  241. package/src/lib/impacted-gate-selector.js +424 -0
  242. package/src/lib/interaction-adapter.js +62 -0
  243. package/src/lib/jsonl-session-store.js +1 -35
  244. package/src/lib/logger.js +66 -14
  245. package/src/lib/managed-checkpoint-render.js +60 -0
  246. package/src/lib/managed-tool-checkpoint.js +194 -0
  247. package/src/lib/mcp-call-ledger-store.js +1069 -0
  248. package/src/lib/mcp-call-ledger.js +747 -0
  249. package/src/lib/mcp-client.js +5 -0
  250. package/src/lib/mcp-conflict-scheduler.js +468 -0
  251. package/src/lib/mcp-effect-contract.js +102 -0
  252. package/src/lib/mcp-headers-helper-trust.js +145 -0
  253. package/src/lib/mcp-headers-helper.js +616 -0
  254. package/src/lib/mcp-host-recovery-runtime.js +131 -0
  255. package/src/lib/mcp-ledger-recovery-admission.js +1065 -0
  256. package/src/lib/mcp-recovery-adjudication.js +443 -0
  257. package/src/lib/output-context.js +86 -0
  258. package/src/lib/packer/file-identity.js +170 -0
  259. package/src/lib/packer/index.js +3 -0
  260. package/src/lib/packer/native-update-state.js +277 -0
  261. package/src/lib/packer/pack-update-applier.js +1983 -136
  262. package/src/lib/packer/pack-update-checker.js +34 -0
  263. package/src/lib/packer/pack-update-downloader.js +875 -86
  264. package/src/lib/packer/pack-update-signature.js +86 -0
  265. package/src/lib/packer/pkg-config-generator.js +6 -0
  266. package/src/lib/paths.js +65 -10
  267. package/src/lib/plan-mode.js +831 -14
  268. package/src/lib/plan-persistence.js +540 -0
  269. package/src/lib/plugin-runtime/hooks.js +227 -69
  270. package/src/lib/plugin-runtime/plugin-options.js +189 -44
  271. package/src/lib/pr-automation-policy.js +146 -8
  272. package/src/lib/process-execution-broker/credential-agent.js +7 -0
  273. package/src/lib/process-execution-broker/index.js +491 -13
  274. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +28 -1
  275. package/src/lib/process-execution-broker/linux-generic-bwrap.js +28 -4
  276. package/src/lib/process-execution-broker/platform-sandbox.js +92 -70
  277. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  278. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  279. package/src/lib/process-execution-broker/windows-sandbox.cs +284 -19
  280. package/src/lib/process-execution-broker/workspace-transaction.js +4459 -0
  281. package/src/lib/project-instructions.js +165 -29
  282. package/src/lib/project-mcp-trust.js +67 -0
  283. package/src/lib/public-ide-capability-manifest.js +272 -0
  284. package/src/lib/public-ide-capability-validation.js +351 -0
  285. package/src/lib/secret-store.js +267 -43
  286. package/src/lib/secure-file-identity.js +433 -0
  287. package/src/lib/secure-fs.js +1089 -0
  288. package/src/lib/security-audit.js +58 -0
  289. package/src/lib/service-manager.js +34 -13
  290. package/src/lib/session-budget-runtime.js +1452 -0
  291. package/src/lib/session-host-snapshot.js +388 -0
  292. package/src/lib/session-message-provenance.js +429 -0
  293. package/src/lib/session-projection.js +804 -0
  294. package/src/lib/session-resource-budget.js +1495 -0
  295. package/src/lib/settings-hooks.cjs +138 -22
  296. package/src/lib/settings-loader.cjs +25 -2
  297. package/src/lib/side-effect-ledger-store.js +45 -23
  298. package/src/lib/skill-execution-identity.js +217 -0
  299. package/src/lib/skill-loader.js +299 -18
  300. package/src/lib/sub-agent-context.js +236 -28
  301. package/src/lib/sub-agent-registry.js +5 -0
  302. package/src/lib/subagent-contract.js +94 -0
  303. package/src/lib/todo-manager.js +185 -18
  304. package/src/lib/todo-persistence.js +417 -0
  305. package/src/lib/turn-binding-store.js +41 -23
  306. package/src/lib/turn-binding.js +160 -2
  307. package/src/lib/with-file-lock.js +165 -24
  308. package/src/lib/ws-chat-handler.js +21 -0
  309. package/src/program-base.js +18 -0
  310. package/src/repl/advisor-command.js +103 -0
  311. package/src/repl/agent-repl.js +2175 -146
  312. package/src/repl/btw-command.js +93 -10
  313. package/src/repl/clipboard-image.js +119 -0
  314. package/src/repl/config-summary.js +64 -108
  315. package/src/repl/prompt-editor.js +233 -0
  316. package/src/repl/prompt-interactions.js +344 -0
  317. package/src/repl/prompt-stash.js +354 -0
  318. package/src/repl/prompt-suggestions.js +312 -0
  319. package/src/repl/repl-keybindings.js +227 -0
  320. package/src/repl/session-recap.js +217 -0
  321. package/src/repl/slash-command-registry.js +22 -0
  322. package/src/repl/terminal-layout.js +88 -0
  323. package/src/runtime/agent-core.js +1630 -447
  324. package/src/runtime/coding-agent-contract-shared.cjs +13 -1
  325. package/src/runtime/coding-agent-managed-tool-policy.cjs +7 -2
  326. package/src/runtime/diagnostics.js +32 -13
  327. package/src/runtime/headless-runner.js +310 -118
  328. package/src/runtime/headless-stream.js +356 -95
  329. package/src/runtime/mcp-config.js +148 -14
  330. package/src/runtime/policies/agent-policy.js +14 -0
  331. package/src/runtime/status-diagnostics-lite.js +137 -0
  332. package/src/assets/web-panel/assets/MarkdownRenderer-7iWGwZ-r.js +0 -1
  333. package/src/assets/web-panel/assets/OrderTableRenderer-BU2Yqq5H.js +0 -1
  334. package/src/assets/web-panel/assets/PdhVaultBrowser-69ca_WeR.js +0 -7
  335. package/src/assets/web-panel/assets/devWarning-B4dXIJqD.js +0 -1
  336. package/src/assets/web-panel/assets/index-C-C7DaG6.js +0 -1
  337. package/src/assets/web-panel/assets/index-DkfWzWtd.js +0 -1
@@ -17,6 +17,7 @@
17
17
  */
18
18
 
19
19
  import { randomUUID } from "node:crypto";
20
+ import { isProxy } from "node:util/types";
20
21
  import {
21
22
  approvalBindingDigest,
22
23
  verifyApprovalBinding,
@@ -85,10 +86,17 @@ import {
85
86
  appendToolCallCompact as jsonlAppendToolCallCompact,
86
87
  appendLlmRetryCompact as jsonlAppendLlmRetryCompact,
87
88
  appendEvent as jsonlAppendEvent,
89
+ appendAuthorityEvent as jsonlAppendAuthorityEvent,
88
90
  readEvents as jsonlReadEvents,
89
- rebuildMessages as jsonlRebuildMessages,
91
+ readVerifiedEvents as jsonlReadVerifiedEvents,
92
+ readVerifiedProjection as jsonlReadVerifiedProjection,
93
+ findLatestEvent as jsonlFindLatestEvent,
90
94
  sessionExists as jsonlSessionExists,
91
95
  } from "../harness/jsonl-session-store.js";
96
+ import {
97
+ isVerifiedSessionHostSnapshot,
98
+ readSessionHostResumeState,
99
+ } from "../lib/session-host-snapshot.js";
92
100
  import { classifyStreamRetryReason } from "../lib/stream-retry.js";
93
101
  import {
94
102
  SideEffectLedger,
@@ -100,6 +108,11 @@ import {
100
108
  loadSideEffectLedger,
101
109
  persistSideEffectLedger,
102
110
  } from "../lib/side-effect-ledger-store.js";
111
+ import {
112
+ createSessionMcpLedgerSink,
113
+ formatMcpLedgerRecoveryNotice,
114
+ } from "../lib/mcp-call-ledger-store.js";
115
+ import { createMcpHostRecoveryRuntime } from "../lib/mcp-host-recovery-runtime.js";
103
116
  import { operationIdempotencyKey } from "../lib/idempotency.js";
104
117
  import { TurnBindingLog, createTurnBindingFeed } from "../lib/turn-binding.js";
105
118
  import { TURN_BINDING_EVENT } from "../lib/turn-binding-store.js";
@@ -111,6 +124,35 @@ import {
111
124
  } from "./session-slash-commands.js";
112
125
  import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
113
126
 
127
+ function invalidMcpRecoveryTransaction(capability, expected) {
128
+ const error = new TypeError(
129
+ `${capability} must ${expected} synchronously during MCP recovery`,
130
+ );
131
+ error.code = "CC_MCP_LEDGER_RECOVERY_TRANSACTION_INVALID";
132
+ return error;
133
+ }
134
+
135
+ function requireSynchronousRecoveryResult(value, capability) {
136
+ if (
137
+ value === null ||
138
+ value === undefined ||
139
+ (typeof value !== "object" && typeof value !== "function")
140
+ ) {
141
+ return value;
142
+ }
143
+ if (isProxy(value)) {
144
+ throw invalidMcpRecoveryTransaction(capability, "return a non-Proxy value");
145
+ }
146
+ if (typeof value.then === "function") {
147
+ // The async result is never authority, but a rejected Promise still needs
148
+ // an observer so rejecting it fail-closed does not leak an unhandled
149
+ // rejection into the host process.
150
+ void Promise.resolve(value).catch(() => {});
151
+ throw invalidMcpRecoveryTransaction(capability, "complete");
152
+ }
153
+ return value;
154
+ }
155
+
114
156
  /**
115
157
  * Resolve the streaming-delta coalesce window (ms). Adjacent partial-message
116
158
  * text/thinking deltas are batched into a single `stream_event` line over this
@@ -943,6 +985,7 @@ async function runTurn(
943
985
  provider: event.provider,
944
986
  model: event.model,
945
987
  usage: event.usage,
988
+ ...(event.source ? { source: event.source } : {}),
946
989
  });
947
990
  if (costBudget) {
948
991
  costBudget.add({
@@ -1013,6 +1056,168 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1013
1056
  const provider = options.provider || "ollama";
1014
1057
  const baseUrl = options.baseUrl || "http://localhost:11434";
1015
1058
  const apiKey = options.apiKey || null;
1059
+ const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
1060
+ const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
1061
+ if (!deps.writeOut && !deps.writeErr) installPipeSafety();
1062
+
1063
+ const sessionId =
1064
+ options.sessionId || `headless-stream-${Date.now()}-${process.pid}`;
1065
+ const persist = Boolean(options.sessionId) && options.ephemeral !== true;
1066
+ const traceId = resolveTraceId(options, process.env, deps);
1067
+ const fieldGate = {
1068
+ seq: true,
1069
+ trace_id: true,
1070
+ tool_use_id: true,
1071
+ permission_decision: true,
1072
+ };
1073
+ const streamCoalescer =
1074
+ deps.streamCoalescer ||
1075
+ createStreamCoalescer({
1076
+ writeOut,
1077
+ coalesceMs: resolveStreamCoalesceMs(options, process.env),
1078
+ traceId,
1079
+ fieldGate,
1080
+ });
1081
+ const emit = streamCoalescer.emit;
1082
+
1083
+ const hasInjectedSessionStore =
1084
+ typeof deps.sessionExists === "function" ||
1085
+ typeof deps.rebuildMessages === "function" ||
1086
+ typeof deps.appendEvent === "function" ||
1087
+ typeof deps.appendAuthorityEvent === "function" ||
1088
+ typeof deps.readVerifiedEvents === "function" ||
1089
+ typeof deps.readVerifiedProjection === "function";
1090
+ const unavailableAuthorityCapability = (operation) => () => {
1091
+ const error = new Error(
1092
+ `Injected session store must provide ${operation} for MCP authority`,
1093
+ );
1094
+ error.code = "SESSION_AUTHORITY_CAPABILITY_UNAVAILABLE";
1095
+ throw error;
1096
+ };
1097
+
1098
+ // A persisted stream resume is an authority boundary, not best-effort chat
1099
+ // history. Resolve it before config/settings, Setup hooks, bootstrap, MCP,
1100
+ // model or tool access. The canonical reader folds active messages and MCP
1101
+ // recovery from one verified, anchored transcript sample under the writer
1102
+ // lock; a damaged or asynchronous seam refuses the entire host session.
1103
+ let canonicalResume = null;
1104
+ let canonicalResumeMessages = null;
1105
+ let canonicalMcpCallRecovery = null;
1106
+ if (persist) {
1107
+ const readResumeState =
1108
+ deps.readSessionHostResumeState || readSessionHostResumeState;
1109
+ const readVerifiedEvents =
1110
+ deps.readVerifiedEvents ||
1111
+ (hasInjectedSessionStore
1112
+ ? unavailableAuthorityCapability("readVerifiedEvents")
1113
+ : jsonlReadVerifiedEvents);
1114
+ const readVerifiedProjection =
1115
+ typeof deps.readVerifiedProjection === "function"
1116
+ ? deps.readVerifiedProjection
1117
+ : !hasInjectedSessionStore
1118
+ ? jsonlReadVerifiedProjection
1119
+ : null;
1120
+ const resumeDependencies = {
1121
+ sessionExists: deps.sessionExists || jsonlSessionExists,
1122
+ readVerifiedEvents: (...args) =>
1123
+ requireSynchronousRecoveryResult(
1124
+ readVerifiedEvents(...args),
1125
+ "readVerifiedEvents",
1126
+ ),
1127
+ ...(readVerifiedProjection
1128
+ ? {
1129
+ readVerifiedProjection: (...args) =>
1130
+ requireSynchronousRecoveryResult(
1131
+ readVerifiedProjection(...args),
1132
+ "readVerifiedProjection",
1133
+ ),
1134
+ }
1135
+ : {}),
1136
+ };
1137
+ try {
1138
+ const existingSession = requireSynchronousRecoveryResult(
1139
+ resumeDependencies.sessionExists(sessionId),
1140
+ "sessionExists",
1141
+ );
1142
+ if (typeof existingSession !== "boolean") {
1143
+ throw invalidMcpRecoveryTransaction(
1144
+ "sessionExists",
1145
+ "return a boolean",
1146
+ );
1147
+ }
1148
+ canonicalResume = existingSession
1149
+ ? requireSynchronousRecoveryResult(
1150
+ readResumeState(sessionId, {
1151
+ ...resumeDependencies,
1152
+ sessionExists: () => true,
1153
+ }),
1154
+ "readSessionHostResumeState",
1155
+ )
1156
+ : null;
1157
+ if (canonicalResume !== null) {
1158
+ if (
1159
+ isProxy(canonicalResume) ||
1160
+ !isVerifiedSessionHostSnapshot(canonicalResume.snapshot) ||
1161
+ !Array.isArray(canonicalResume.messages) ||
1162
+ isProxy(canonicalResume.messages) ||
1163
+ !canonicalResume.recovery ||
1164
+ typeof canonicalResume.recovery !== "object" ||
1165
+ isProxy(canonicalResume.recovery) ||
1166
+ !Array.isArray(canonicalResume.recovery.unsettled) ||
1167
+ isProxy(canonicalResume.recovery.unsettled) ||
1168
+ !Array.isArray(canonicalResume.recovery.incidents) ||
1169
+ isProxy(canonicalResume.recovery.incidents)
1170
+ ) {
1171
+ throw invalidMcpRecoveryTransaction(
1172
+ "readSessionHostResumeState",
1173
+ "return one verified session-host projection",
1174
+ );
1175
+ }
1176
+ if (
1177
+ !canonicalResume.messages.every(
1178
+ (message) =>
1179
+ message &&
1180
+ !isProxy(message) &&
1181
+ ["system", "user", "assistant", "tool"].includes(message.role),
1182
+ )
1183
+ ) {
1184
+ throw invalidMcpRecoveryTransaction(
1185
+ "readSessionHostResumeState",
1186
+ "return plain replay messages with supported roles",
1187
+ );
1188
+ }
1189
+ canonicalResumeMessages = [...canonicalResume.messages];
1190
+ const notice = formatMcpLedgerRecoveryNotice(canonicalResume.recovery);
1191
+ if (notice) {
1192
+ canonicalMcpCallRecovery = {
1193
+ count: canonicalResume.recovery.unsettled.length,
1194
+ incidents: canonicalResume.recovery.incidents.length,
1195
+ items: canonicalResume.recovery.unsettled
1196
+ .slice(0, 10)
1197
+ .map((record) => ({
1198
+ ledgerId: record.ledgerId,
1199
+ server: record.serverName,
1200
+ tool: record.toolName,
1201
+ effect: record.effectContract?.effect || "unknown",
1202
+ })),
1203
+ notice,
1204
+ };
1205
+ }
1206
+ }
1207
+ } catch {
1208
+ const code = "CC_SESSION_HOST_SNAPSHOT_UNVERIFIED";
1209
+ emit({
1210
+ type: "result",
1211
+ subtype: "error_session_resume",
1212
+ is_error: true,
1213
+ code,
1214
+ error: "Canonical stream session could not be verified",
1215
+ session_id: sessionId,
1216
+ });
1217
+ writeErr(`${code}: canonical stream resume was refused\n`);
1218
+ return { exitCode: 1, turns: 0 };
1219
+ }
1220
+ }
1016
1221
  // Vision model (config.llm.visionModel) — image turns switch to it for that
1017
1222
  // turn only (resolveVisionLlm falls back to the default when unset), so a
1018
1223
  // pasted/typed image is read by a vision-capable model even though the
@@ -1067,12 +1272,19 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1067
1272
  let settingsHooks = options.settingsHooks || null;
1068
1273
  if (!settingsHooks) {
1069
1274
  try {
1070
- const { loadHooks, projectHookTrustNotice } =
1275
+ const { loadHooks, projectHookTrustNotice, attachAuthorityErrors } =
1071
1276
  await import("../lib/settings-hooks.cjs");
1072
1277
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
1278
+ const { mergePluginHooks } =
1279
+ await import("../lib/plugin-runtime/hooks.js");
1280
+ const effectiveHooks = mergePluginHooks(
1281
+ attachAuthorityErrors(loaded.hooks, loaded.authorityErrors),
1282
+ { cwd },
1283
+ );
1073
1284
  settingsHooks =
1074
- loaded.hooks && Object.keys(loaded.hooks).length > 0
1075
- ? loaded.hooks
1285
+ Object.keys(effectiveHooks).length > 0 ||
1286
+ effectiveHooks._authorityErrors.length > 0
1287
+ ? effectiveHooks
1076
1288
  : null;
1077
1289
  // First-run trust notice for an untrusted/cloned repo's shell-running
1078
1290
  // hooks (Claude-Code 2.1.195 parity). stderr keeps the NDJSON stdout clean.
@@ -1085,8 +1297,17 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1085
1297
  } catch {
1086
1298
  /* trust notice is best-effort */
1087
1299
  }
1088
- } catch {
1089
- settingsHooks = null; // fail-open
1300
+ } catch (error) {
1301
+ settingsHooks = {};
1302
+ Object.defineProperty(settingsHooks, "_authorityErrors", {
1303
+ value: Object.freeze([
1304
+ Object.freeze({
1305
+ sourceFile: null,
1306
+ code: error?.code || "CC_HOOK_AUTHORITY_LOAD_FAILED",
1307
+ }),
1308
+ ]),
1309
+ enumerable: false,
1310
+ });
1090
1311
  }
1091
1312
  }
1092
1313
 
@@ -1113,44 +1334,6 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1113
1334
  const doExpand = deps.expandFileRefs || expandFileRefsAsync;
1114
1335
  const runSessionSlashCommand =
1115
1336
  deps.executeSessionSlashCommand || executeSessionSlashCommand;
1116
- const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
1117
- const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
1118
- // Guard the real stdout/stderr against a downstream `| head` closing the pipe
1119
- // (unhandled async EPIPE → crash). Only when we own the streams (no injected
1120
- // seams = production, not tests). Idempotent; shared with the -p runner.
1121
- if (!deps.writeOut && !deps.writeErr) {
1122
- installPipeSafety();
1123
- }
1124
- // Run-scoped cross-event trace id (additive protocol-v1, docs/PROTOCOL.md
1125
- // §1.2.1): one id stamped on EVERY stdout line so a consumer can correlate
1126
- // the whole run across Webview → Bridge → CLI logs, transcripts and
1127
- // diagnostic bundles. The IDE bridge may thread its own id through
1128
- // `--trace-id` / options.traceId / CC_TRACE_ID; otherwise a per-process id
1129
- // is minted (unique even when two runs resume the same session_id).
1130
- const traceId = resolveTraceId(options, process.env, deps);
1131
- // Live field-gate for the capability handshake (docs/PROTOCOL.md §1.3): a
1132
- // client `hello` narrowing the wire features flips these to suppress the
1133
- // additive fields it can't parse. All true by default = current behavior
1134
- // byte-for-byte; the coalescer reads it per line.
1135
- const fieldGate = {
1136
- seq: true,
1137
- trace_id: true,
1138
- tool_use_id: true,
1139
- permission_decision: true,
1140
- };
1141
- // Batch consecutive partial-message text/thinking deltas into one stream_event
1142
- // line (Claude-Code 2.1.191 streaming-CPU optimization). `emit` flushes any
1143
- // pending deltas before writing a non-delta line, so ordering is preserved;
1144
- // CC_STREAM_COALESCE_MS=0 restores the per-token emit behavior.
1145
- const streamCoalescer =
1146
- deps.streamCoalescer ||
1147
- createStreamCoalescer({
1148
- writeOut,
1149
- coalesceMs: resolveStreamCoalesceMs(options, process.env),
1150
- traceId,
1151
- fieldGate,
1152
- });
1153
- const emit = streamCoalescer.emit;
1154
1337
 
1155
1338
  const getApprovalGate =
1156
1339
  deps.getApprovalGate ||
@@ -1181,9 +1364,6 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1181
1364
  // DB optional — static-prompt fallback.
1182
1365
  }
1183
1366
 
1184
- const sessionId =
1185
- options.sessionId || `headless-stream-${Date.now()}-${process.pid}`;
1186
-
1187
1367
  const setupHooks = await executeLifecycleHooks(
1188
1368
  "Setup",
1189
1369
  {
@@ -1216,6 +1396,23 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1216
1396
  // prior history is rebuilt into the conversation and every new turn is
1217
1397
  // appended, so a later run with the same id picks up where this one left
1218
1398
  // off. Anonymous runs (no id) stay persistence-free, exactly as before.
1399
+ const storeReadEvents = deps.readEvents || jsonlReadEvents;
1400
+ const storeFindLatestEvent =
1401
+ deps.findLatestEvent ||
1402
+ (deps.readEvents
1403
+ ? (sessionId, type, predicate = null) => {
1404
+ const events = storeReadEvents(sessionId) || [];
1405
+ for (let index = events.length - 1; index >= 0; index -= 1) {
1406
+ const event = events[index];
1407
+ if (type != null && event?.type !== type) continue;
1408
+ if (typeof predicate === "function" && !predicate(event)) continue;
1409
+ return event;
1410
+ }
1411
+ return null;
1412
+ }
1413
+ : hasInjectedSessionStore
1414
+ ? () => null
1415
+ : jsonlFindLatestEvent);
1219
1416
  const store = {
1220
1417
  sessionExists: deps.sessionExists || jsonlSessionExists,
1221
1418
  startSession: deps.startSession || jsonlStartSession,
@@ -1223,16 +1420,35 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1223
1420
  appendAssistantMessage:
1224
1421
  deps.appendAssistantMessage || jsonlAppendAssistantMessage,
1225
1422
  appendToolCallCompact:
1226
- deps.appendToolCallCompact || jsonlAppendToolCallCompact,
1423
+ deps.appendToolCallCompact ||
1424
+ (hasInjectedSessionStore ? () => true : jsonlAppendToolCallCompact),
1227
1425
  appendLlmRetryCompact:
1228
- deps.appendLlmRetryCompact || jsonlAppendLlmRetryCompact,
1229
- appendEvent: deps.appendEvent || jsonlAppendEvent,
1230
- readEvents: deps.readEvents || jsonlReadEvents,
1231
- rebuildMessages: deps.rebuildMessages || jsonlRebuildMessages,
1426
+ deps.appendLlmRetryCompact ||
1427
+ (hasInjectedSessionStore ? () => true : jsonlAppendLlmRetryCompact),
1428
+ appendEvent:
1429
+ deps.appendEvent ||
1430
+ (hasInjectedSessionStore ? () => true : jsonlAppendEvent),
1431
+ appendAuthorityEvent:
1432
+ deps.appendAuthorityEvent ||
1433
+ (hasInjectedSessionStore
1434
+ ? unavailableAuthorityCapability("appendAuthorityEvent")
1435
+ : jsonlAppendAuthorityEvent),
1436
+ readEvents: storeReadEvents,
1437
+ readVerifiedEvents:
1438
+ deps.readVerifiedEvents ||
1439
+ (hasInjectedSessionStore
1440
+ ? unavailableAuthorityCapability("readVerifiedEvents")
1441
+ : jsonlReadVerifiedEvents),
1442
+ readVerifiedProjection:
1443
+ deps.readVerifiedProjection ||
1444
+ (hasInjectedSessionStore ? null : jsonlReadVerifiedProjection),
1445
+ findLatestEvent: storeFindLatestEvent,
1232
1446
  };
1233
- // --ephemeral forces persistence OFF even with an explicit session id (the
1234
- // id is kept for event correlation only; nothing is written or replayed).
1235
- const persist = Boolean(options.sessionId) && options.ephemeral !== true;
1447
+ const mcpLedgerSink = persist
1448
+ ? createSessionMcpLedgerSink(sessionId, {
1449
+ appendEvent: store.appendAuthorityEvent,
1450
+ })
1451
+ : null;
1236
1452
 
1237
1453
  // ── P0-2: crash-safe side-effect ledger — the stream twin of the
1238
1454
  // single-prompt runner (headless-runner.js) and the WS bridge
@@ -1328,17 +1544,13 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1328
1544
  };
1329
1545
  if (persist) {
1330
1546
  try {
1331
- const priorEvents = store.readEvents(sessionId) || [];
1332
- for (let index = priorEvents.length - 1; index >= 0; index--) {
1333
- const event = priorEvents[index];
1334
- if (
1335
- event?.type === TURN_BINDING_EVENT &&
1336
- event.data &&
1337
- typeof event.data === "object"
1338
- ) {
1339
- turnBindingLog = TurnBindingLog.fromJSON(event.data);
1340
- break;
1341
- }
1547
+ const event = store.findLatestEvent(
1548
+ sessionId,
1549
+ TURN_BINDING_EVENT,
1550
+ (candidate) => candidate?.data && typeof candidate.data === "object",
1551
+ );
1552
+ if (event) {
1553
+ turnBindingLog = TurnBindingLog.fromJSON(event.data);
1342
1554
  }
1343
1555
  } catch (error) {
1344
1556
  recordTurnBindingFailure(error, "read");
@@ -1705,34 +1917,53 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1705
1917
  // leads; persisted system turns are dropped, mirroring runAgentHeadless).
1706
1918
  let resumedMessages = 0;
1707
1919
  let sideEffectRecovery = null;
1920
+ let mcpCallRecovery = null;
1921
+ let mcpLedgerRecovery = null;
1922
+ let mcpLedgerRecoveryError = null;
1708
1923
  if (persist) {
1709
- try {
1710
- if (store.sessionExists(sessionId)) {
1711
- // P0-2: reconcile the crash-safe ledger on resume (parity with
1712
- // runAgentHeadless + the WS bridge). The verify-before-replay system
1713
- // note goes BEFORE the replayed history — the same slot the
1714
- // single-prompt runner uses — which also keeps the trailing-role
1715
- // resume-degeneracy check below intact.
1716
- if (sideEffectLedger) {
1717
- sideEffectRecovery = buildSideEffectRecovery(sideEffectLedger);
1718
- }
1719
- if (sideEffectRecovery) {
1720
- messages.push({ role: "system", content: sideEffectRecovery.notice });
1721
- }
1722
- const history = (store.rebuildMessages(sessionId) || []).filter(
1723
- (m) => m && m.role !== "system",
1924
+ if (canonicalResume) {
1925
+ // The history and MCP authority below came from the same verified head.
1926
+ // No second pathname read is allowed between verification and replay.
1927
+ if (sideEffectLedger) {
1928
+ sideEffectRecovery = buildSideEffectRecovery(sideEffectLedger);
1929
+ }
1930
+ if (sideEffectRecovery) {
1931
+ messages.push({ role: "system", content: sideEffectRecovery.notice });
1932
+ }
1933
+ mcpLedgerRecovery = canonicalResume.recovery;
1934
+ mcpCallRecovery = canonicalMcpCallRecovery;
1935
+ if (mcpCallRecovery) {
1936
+ messages.push({ role: "system", content: mcpCallRecovery.notice });
1937
+ }
1938
+ messages.push(...canonicalResumeMessages);
1939
+ // Preserve the existing public counter semantics: control-plane stream
1940
+ // metadata counts conversational turns, never private system context.
1941
+ resumedMessages = canonicalResumeMessages.filter(
1942
+ (message) => message.role !== "system",
1943
+ ).length;
1944
+ } else {
1945
+ try {
1946
+ requireSynchronousRecoveryResult(
1947
+ store.startSession(sessionId, {
1948
+ title: "stream session",
1949
+ provider,
1950
+ model,
1951
+ }),
1952
+ "startSession",
1724
1953
  );
1725
- messages.push(...history);
1726
- resumedMessages = history.length;
1727
- } else {
1728
- store.startSession(sessionId, {
1729
- title: "stream session",
1730
- provider,
1731
- model,
1954
+ } catch {
1955
+ const code = "CC_SESSION_PERSISTENCE_START_FAILED";
1956
+ emit({
1957
+ type: "result",
1958
+ subtype: "error_session_persistence",
1959
+ is_error: true,
1960
+ code,
1961
+ error: "Canonical stream session could not be created",
1962
+ session_id: sessionId,
1732
1963
  });
1964
+ writeErr(`${code}: canonical stream session creation was refused\n`);
1965
+ return { exitCode: 1, turns: 0 };
1733
1966
  }
1734
- } catch {
1735
- // persistence is best-effort — never fail the stream over it
1736
1967
  }
1737
1968
  }
1738
1969
 
@@ -1794,6 +2025,17 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1794
2025
  session_id: sessionId,
1795
2026
  });
1796
2027
  }
2028
+ if (mcpCallRecovery) {
2029
+ emit({
2030
+ type: "raw",
2031
+ subtype: "mcp_call_recovery",
2032
+ text: `⚠️ ${mcpCallRecovery.count} interrupted MCP call(s) and ${mcpCallRecovery.incidents} ledger incident(s) need inspection before replay (resume ${sessionId}).`,
2033
+ count: mcpCallRecovery.count,
2034
+ incidents: mcpCallRecovery.incidents,
2035
+ items: mcpCallRecovery.items,
2036
+ session_id: sessionId,
2037
+ });
2038
+ }
1797
2039
 
1798
2040
  // Goal binding (cc goal, Phase 1) — resolved once and injected on every turn.
1799
2041
  // `--goal <id>` binds explicitly; `--goal` with no value auto-resolves.
@@ -1872,6 +2114,17 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1872
2114
  }
1873
2115
  }
1874
2116
 
2117
+ const mcpRecoveryRuntime = createMcpHostRecoveryRuntime({
2118
+ bundle: mcp,
2119
+ sessionId,
2120
+ sink: mcpLedgerSink,
2121
+ recovery: mcpLedgerRecovery,
2122
+ recoveryError: mcpLedgerRecoveryError,
2123
+ });
2124
+ const hostMcp = mcp
2125
+ ? { ...mcp, mcpClient: mcpRecoveryRuntime.client || mcp.mcpClient }
2126
+ : null;
2127
+
1875
2128
  // MCP servers may pause a tool flow with `elicitation/create`. Register the
1876
2129
  // handler only after MCP resolution so the client is initialized before use.
1877
2130
  // Reuse the structured Desktop/headless question channel, while preserving
@@ -1968,12 +2221,12 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
1968
2221
  // workspace-root list to connected MCP servers when the stream session started
1969
2222
  // with extra roots. No --add-dir → workspaceRootDirs = [cwd] → no-op. Mirrors
1970
2223
  // the single-prompt runner + the REPL /add-dir path. Best-effort.
1971
- if (mcp?.mcpClient && additionalDirectories.length > 0) {
2224
+ if (hostMcp?.mcpClient && additionalDirectories.length > 0) {
1972
2225
  try {
1973
2226
  const { notifyMcpRootsChanged, workspaceRootDirs } =
1974
2227
  await import("../repl/add-dir.js");
1975
2228
  notifyMcpRootsChanged(
1976
- [mcp.mcpClient],
2229
+ [hostMcp.mcpClient],
1977
2230
  workspaceRootDirs(options.cwd || process.cwd(), additionalDirectories),
1978
2231
  );
1979
2232
  } catch {
@@ -2000,7 +2253,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
2000
2253
  if (approvalGate && typeof approvalGate.setConfirmer === "function") {
2001
2254
  approvalGate.setConfirmer(
2002
2255
  makePermissionPromptConfirmer({
2003
- mcpClient: mcp.mcpClient,
2256
+ mcpClient: hostMcp.mcpClient,
2004
2257
  server: ppt.server,
2005
2258
  tool: ppt.tool,
2006
2259
  }),
@@ -2057,6 +2310,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
2057
2310
  cwd,
2058
2311
  additionalDirectories,
2059
2312
  sessionId,
2313
+ sessionHostSnapshot: canonicalResume?.snapshot || null,
2060
2314
  // Auto-checkpoint (Claude-Code parity): snapshot the work tree before each
2061
2315
  // mutating tool so a stream consumer (e.g. the IDE chat panel) can rewind.
2062
2316
  // Keyed by this run's sessionId — agent-core falls back to it — so the panel
@@ -2065,6 +2319,9 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
2065
2319
  // only, a no-op outside a git repo.
2066
2320
  autoCheckpoint: options.autoCheckpoint || false,
2067
2321
  checkpointSession: options.checkpointSession || sessionId,
2322
+ managedCheckpoint: options.managedCheckpoint === true,
2323
+ managedCheckpointStateDir: options.managedCheckpointStateDir || null,
2324
+ managedCheckpointExclusions: options.managedCheckpointExclusions || [],
2068
2325
  hookDb: db,
2069
2326
  approvalGate,
2070
2327
  permissionRules,
@@ -2086,9 +2343,13 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
2086
2343
  prepareCall: goalPrepareCallFn,
2087
2344
  // --mcp-config wiring (tool defs + dispatch map + live client).
2088
2345
  mcpClient: mcp?.mcpClient || null,
2346
+ mcpHostClient: mcpRecoveryRuntime.client || mcp?.mcpClient || null,
2089
2347
  extraToolDefinitions: mcp?.extraToolDefinitions || undefined,
2090
2348
  externalToolExecutors: mcp?.externalToolExecutors || undefined,
2091
2349
  externalToolDescriptors: mcp?.externalToolDescriptors || undefined,
2350
+ // A null sink disables durable writes, not recovery admission. Retain the
2351
+ // guarded ledger so outcome-unknown calls cannot be retried in-process.
2352
+ mcpCallLedger: mcpRecoveryRuntime.ledger,
2092
2353
  chatFn: deps.chatFn || options.chatFn || undefined,
2093
2354
  signal: options.signal || undefined,
2094
2355
  // --include-partial-messages: stream live assistant-text deltas as
@@ -2709,11 +2970,11 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
2709
2970
  try {
2710
2971
  const ideCtx = await (
2711
2972
  deps.buildIdePromptContext || buildIdePromptContext
2712
- )(mcp);
2973
+ )(hostMcp);
2713
2974
  if (ideCtx) userContent += `\n\n${ideCtx}`;
2714
2975
  // Explicit @selection / @diagnostics mentions (Claude-Code parity);
2715
2976
  // scan the original user event text, append the expansion ephemerally.
2716
- const mentioned = await expandIdeMentions(parsed.text, mcp);
2977
+ const mentioned = await expandIdeMentions(parsed.text, hostMcp);
2717
2978
  for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
2718
2979
  if (mentioned.block) userContent += `\n\n${mentioned.block}`;
2719
2980
  } catch {