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
@@ -0,0 +1,1065 @@
1
+ import { isProxy } from "node:util/types";
2
+ import {
3
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS,
4
+ McpEffect,
5
+ computeMcpExactReplayDigest,
6
+ createMcpCallLedger,
7
+ normalizeMcpLedgerProtocolText,
8
+ normalizeMcpEffectContract,
9
+ snapshotMcpJsonRpcInput,
10
+ summarizeMcpPayload,
11
+ } from "./mcp-call-ledger.js";
12
+
13
+ export const McpRecoveryBlockMode = Object.freeze({
14
+ ALL: "all",
15
+ UNSAFE: "unsafe",
16
+ });
17
+
18
+ export const MCP_RECOVERY_INVALID_CODE = "CC_MCP_LEDGER_RECOVERY_INVALID";
19
+ export const MCP_OUTCOME_UNKNOWN_CODE = "CC_MCP_LEDGER_OUTCOME_UNKNOWN";
20
+ export const MCP_EXACT_REPLAY_DENIED_CODE = "CC_MCP_LEDGER_EXACT_REPLAY_DENIED";
21
+ export const MCP_RECOVERY_DENY_REGRESSION_CODE =
22
+ "CC_MCP_LEDGER_REPLAY_DENY_REGRESSION";
23
+
24
+ const SHA256_DIGEST = /^sha256:[0-9a-f]{64}$/;
25
+ const REPLAY_DENY_FIELDS = new Set([
26
+ "ledgerId",
27
+ "serverName",
28
+ "toolName",
29
+ "inputBytes",
30
+ "replayDigest",
31
+ ]);
32
+
33
+ const RECOVERY_CONTROLLERS = new WeakSet();
34
+ const GUARDED_LEDGER_CONTROLLERS = new WeakMap();
35
+ const GUARDED_MCP_CLIENTS = new WeakMap();
36
+
37
+ function ownDataValue(record, key) {
38
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
39
+ if (!descriptor || !("value" in descriptor)) {
40
+ return { valid: false, value: undefined };
41
+ }
42
+ return { valid: true, value: descriptor.value };
43
+ }
44
+
45
+ function isPlainDataObject(value) {
46
+ if (
47
+ !value ||
48
+ typeof value !== "object" ||
49
+ Array.isArray(value) ||
50
+ isProxy(value)
51
+ ) {
52
+ return false;
53
+ }
54
+ const prototype = Object.getPrototypeOf(value);
55
+ return prototype === Object.prototype || prototype === null;
56
+ }
57
+
58
+ function canonicalReplayDenyEntry(value) {
59
+ if (!isPlainDataObject(value)) return null;
60
+ const descriptors = Object.getOwnPropertyDescriptors(value);
61
+ const fields = Object.keys(descriptors);
62
+ if (
63
+ fields.length !== REPLAY_DENY_FIELDS.size ||
64
+ fields.some((field) => !REPLAY_DENY_FIELDS.has(field)) ||
65
+ [...REPLAY_DENY_FIELDS].some(
66
+ (field) => !descriptors[field] || !("value" in descriptors[field]),
67
+ )
68
+ ) {
69
+ return null;
70
+ }
71
+ const ledgerId = descriptors.ledgerId.value;
72
+ const serverName = descriptors.serverName.value;
73
+ const toolName = descriptors.toolName.value;
74
+ const inputBytes = descriptors.inputBytes.value;
75
+ const replayDigest = descriptors.replayDigest.value;
76
+ if (
77
+ typeof ledgerId !== "string" ||
78
+ ledgerId !==
79
+ normalizeMcpLedgerProtocolText(
80
+ ledgerId,
81
+ null,
82
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS.ledgerId,
83
+ ) ||
84
+ typeof serverName !== "string" ||
85
+ serverName !==
86
+ normalizeMcpLedgerProtocolText(
87
+ serverName,
88
+ null,
89
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS.identifier,
90
+ ) ||
91
+ typeof toolName !== "string" ||
92
+ toolName !==
93
+ normalizeMcpLedgerProtocolText(
94
+ toolName,
95
+ null,
96
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS.identifier,
97
+ ) ||
98
+ !Number.isInteger(inputBytes) ||
99
+ inputBytes < 0 ||
100
+ typeof replayDigest !== "string" ||
101
+ !SHA256_DIGEST.test(replayDigest)
102
+ ) {
103
+ return null;
104
+ }
105
+ return Object.freeze({
106
+ ledgerId,
107
+ serverName,
108
+ toolName,
109
+ inputBytes,
110
+ replayDigest,
111
+ });
112
+ }
113
+
114
+ function replayDenyKey(value) {
115
+ return JSON.stringify([
116
+ value?.serverName || null,
117
+ value?.toolName || null,
118
+ Number.isInteger(value?.inputBytes) ? value.inputBytes : null,
119
+ value?.replayDigest || null,
120
+ ]);
121
+ }
122
+
123
+ function replayDenyAuthorityKey(value) {
124
+ return JSON.stringify([value?.ledgerId || null, replayDenyKey(value)]);
125
+ }
126
+
127
+ function invalidMcpCallInput(reason) {
128
+ const error = new TypeError(
129
+ `MCP call input is not strict immutable JSON data (${reason})`,
130
+ );
131
+ error.code = "CC_MCP_WIRE_INPUT_INVALID";
132
+ return error;
133
+ }
134
+
135
+ function snapshotMcpAdmissionCall(call = {}) {
136
+ if (!isPlainDataObject(call)) throw invalidMcpCallInput("call-envelope");
137
+ if (Object.getOwnPropertySymbols(call).length > 0) {
138
+ throw invalidMcpCallInput("symbol-key");
139
+ }
140
+ const descriptors = Object.getOwnPropertyDescriptors(call);
141
+ const snapshot = {};
142
+ for (const key of Object.keys(descriptors)) {
143
+ const descriptor = descriptors[key];
144
+ if (!("value" in descriptor)) throw invalidMcpCallInput("accessor");
145
+ if (!descriptor.enumerable) throw invalidMcpCallInput("hidden-property");
146
+ if (key === "input") continue;
147
+ Object.defineProperty(snapshot, key, {
148
+ configurable: false,
149
+ enumerable: true,
150
+ writable: false,
151
+ value: descriptor.value,
152
+ });
153
+ }
154
+ const inputDescriptor = descriptors.input;
155
+ Object.defineProperty(snapshot, "input", {
156
+ configurable: false,
157
+ enumerable: true,
158
+ writable: false,
159
+ value: snapshotMcpJsonRpcInput(
160
+ inputDescriptor ? inputDescriptor.value : {},
161
+ ),
162
+ });
163
+ return Object.freeze(snapshot);
164
+ }
165
+
166
+ function replayIdentityForCall(call = {}) {
167
+ const serverName = normalizeMcpLedgerProtocolText(
168
+ call.serverName || call.server,
169
+ null,
170
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS.identifier,
171
+ );
172
+ const toolNameValue = normalizeMcpLedgerProtocolText(
173
+ call.toolName || call.tool,
174
+ null,
175
+ MCP_CALL_LEDGER_PROTOCOL_LIMITS.identifier,
176
+ );
177
+ if (!serverName || !toolNameValue) return null;
178
+ const toolName = toolNameValue;
179
+ const input = snapshotMcpJsonRpcInput(
180
+ Object.prototype.hasOwnProperty.call(call, "input") ? call.input : {},
181
+ );
182
+ const summary = summarizeMcpPayload(input);
183
+ return Object.freeze({
184
+ serverName,
185
+ toolName,
186
+ inputBytes: summary.bytes,
187
+ replayDigest: computeMcpExactReplayDigest({
188
+ serverName,
189
+ toolName,
190
+ inputDigest: summary.sha256,
191
+ inputBytes: summary.bytes,
192
+ }),
193
+ });
194
+ }
195
+
196
+ function findReplayDeny(replayDenied, call) {
197
+ if (!Array.isArray(replayDenied) || replayDenied.length === 0) return null;
198
+ const identity = replayIdentityForCall(call);
199
+ if (!identity) return null;
200
+ const key = replayDenyKey(identity);
201
+ return replayDenied.find((entry) => replayDenyKey(entry) === key) || null;
202
+ }
203
+
204
+ function invalidRecoveryProjection() {
205
+ return {
206
+ valid: false,
207
+ incidents: 0,
208
+ unsettled: 0,
209
+ explicitMode: null,
210
+ replayDenied: Object.freeze([]),
211
+ };
212
+ }
213
+
214
+ function inspectRecoveryProjection(recovery) {
215
+ if (recovery == null) {
216
+ return {
217
+ valid: true,
218
+ incidents: 0,
219
+ unsettled: 0,
220
+ explicitMode: null,
221
+ replayDenied: Object.freeze([]),
222
+ };
223
+ }
224
+
225
+ try {
226
+ if (
227
+ typeof recovery !== "object" ||
228
+ isProxy(recovery) ||
229
+ Array.isArray(recovery)
230
+ ) {
231
+ return invalidRecoveryProjection();
232
+ }
233
+ const prototype = Object.getPrototypeOf(recovery);
234
+ if (prototype !== Object.prototype && prototype !== null) {
235
+ return invalidRecoveryProjection();
236
+ }
237
+
238
+ const thenDescriptor = Object.getOwnPropertyDescriptor(recovery, "then");
239
+ if (
240
+ thenDescriptor &&
241
+ (!("value" in thenDescriptor) ||
242
+ typeof thenDescriptor.value === "function")
243
+ ) {
244
+ return invalidRecoveryProjection();
245
+ }
246
+
247
+ const incidentsProperty = ownDataValue(recovery, "incidents");
248
+ const unsettledProperty = ownDataValue(recovery, "unsettled");
249
+ const incidentsValue = incidentsProperty.value;
250
+ const unsettledValue = unsettledProperty.value;
251
+ if (
252
+ !incidentsProperty.valid ||
253
+ !unsettledProperty.valid ||
254
+ isProxy(incidentsValue) ||
255
+ isProxy(unsettledValue) ||
256
+ !Array.isArray(incidentsValue) ||
257
+ !Array.isArray(unsettledValue)
258
+ ) {
259
+ return invalidRecoveryProjection();
260
+ }
261
+
262
+ const blockModeDescriptor = Object.getOwnPropertyDescriptor(
263
+ recovery,
264
+ "blockMode",
265
+ );
266
+ if (blockModeDescriptor && !("value" in blockModeDescriptor)) {
267
+ return invalidRecoveryProjection();
268
+ }
269
+ const explicitMode = blockModeDescriptor?.value;
270
+ if (
271
+ explicitMode != null &&
272
+ explicitMode !== McpRecoveryBlockMode.ALL &&
273
+ explicitMode !== McpRecoveryBlockMode.UNSAFE
274
+ ) {
275
+ return invalidRecoveryProjection();
276
+ }
277
+
278
+ const replayDeniedDescriptor = Object.getOwnPropertyDescriptor(
279
+ recovery,
280
+ "replayDenied",
281
+ );
282
+ if (!replayDeniedDescriptor || !("value" in replayDeniedDescriptor)) {
283
+ return invalidRecoveryProjection();
284
+ }
285
+ const replayDeniedValue = replayDeniedDescriptor.value;
286
+ if (isProxy(replayDeniedValue) || !Array.isArray(replayDeniedValue)) {
287
+ return invalidRecoveryProjection();
288
+ }
289
+ const replayDenied = replayDeniedValue.map(canonicalReplayDenyEntry);
290
+ if (replayDenied.some((entry) => entry === null)) {
291
+ return invalidRecoveryProjection();
292
+ }
293
+ const replayKeys = new Set(replayDenied.map(replayDenyKey));
294
+ if (replayKeys.size !== replayDenied.length) {
295
+ return invalidRecoveryProjection();
296
+ }
297
+
298
+ return {
299
+ valid: true,
300
+ incidents: incidentsValue.length,
301
+ unsettled: unsettledValue.length,
302
+ explicitMode: explicitMode ?? null,
303
+ replayDenied: Object.freeze(replayDenied),
304
+ };
305
+ } catch {
306
+ // Accessors/proxies are not trusted recovery evidence. Keep admission
307
+ // synchronous and fail closed instead of allowing a malformed projection.
308
+ return invalidRecoveryProjection();
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Reduce a content-free recovery projection to one admission decision. A
314
+ * present projection must contain synchronous incidents/unsettled arrays;
315
+ * malformed or asynchronous values are not evidence of a clean recovery.
316
+ * Incidents and verified-read failures block every MCP call. A surviving
317
+ * started record blocks non-read effects until a caller explicitly
318
+ * adjudicates the prior outcome.
319
+ */
320
+ export function classifyMcpRecoveryAdmission(
321
+ recovery,
322
+ { recoveryError = null, blockMode: requestedMode = null } = {},
323
+ ) {
324
+ const projection = inspectRecoveryProjection(recovery);
325
+ const { incidents, unsettled, explicitMode } = projection;
326
+ const replayDenied = projection.replayDenied.length;
327
+ const requestedModeValid =
328
+ requestedMode == null ||
329
+ requestedMode === McpRecoveryBlockMode.ALL ||
330
+ requestedMode === McpRecoveryBlockMode.UNSAFE;
331
+ const reasonCode =
332
+ projection.valid && requestedModeValid ? null : MCP_RECOVERY_INVALID_CODE;
333
+ let blockMode = null;
334
+ if (
335
+ !projection.valid ||
336
+ !requestedModeValid ||
337
+ recoveryError != null ||
338
+ incidents > 0
339
+ ) {
340
+ blockMode = McpRecoveryBlockMode.ALL;
341
+ } else if (requestedMode || explicitMode) {
342
+ blockMode = requestedMode || explicitMode;
343
+ } else if (unsettled > 0) {
344
+ blockMode = McpRecoveryBlockMode.UNSAFE;
345
+ }
346
+ return Object.freeze({
347
+ blockMode,
348
+ incidents,
349
+ unsettled,
350
+ replayDenied,
351
+ reasonCode,
352
+ });
353
+ }
354
+
355
+ function admissionRank(blockMode) {
356
+ if (blockMode === McpRecoveryBlockMode.ALL) return 2;
357
+ if (blockMode === McpRecoveryBlockMode.UNSAFE) return 1;
358
+ return 0;
359
+ }
360
+
361
+ /**
362
+ * Mutable-by-method, immutable-by-reference recovery admission authority.
363
+ * Only a new verified projection may replace (and therefore lower) the current
364
+ * admission. Runtime latches are monotonic until that explicit replacement.
365
+ */
366
+ export function createMcpRecoveryAdmissionController(
367
+ recovery = null,
368
+ options = {},
369
+ ) {
370
+ let currentProjection = inspectRecoveryProjection(recovery);
371
+ let currentAdmission = classifyMcpRecoveryAdmission(recovery, options);
372
+
373
+ const latch = (blockMode, reasonCode = null) => {
374
+ const requestedRank = admissionRank(blockMode);
375
+ const currentRank = admissionRank(currentAdmission.blockMode);
376
+ if (requestedRank < currentRank) return currentAdmission;
377
+ if (requestedRank === currentRank) {
378
+ if (currentAdmission.reasonCode || !reasonCode) return currentAdmission;
379
+ currentAdmission = Object.freeze({
380
+ ...currentAdmission,
381
+ reasonCode,
382
+ });
383
+ return currentAdmission;
384
+ }
385
+ currentAdmission = Object.freeze({
386
+ ...currentAdmission,
387
+ blockMode,
388
+ // A stricter admission must explain the stricter condition. Preserve the
389
+ // old reason only when the escalation itself has no diagnosable cause.
390
+ reasonCode: reasonCode || currentAdmission.reasonCode || null,
391
+ });
392
+ return currentAdmission;
393
+ };
394
+
395
+ const controller = {
396
+ get admission() {
397
+ return currentAdmission;
398
+ },
399
+ getAdmission() {
400
+ return currentAdmission;
401
+ },
402
+ replaceVerifiedRecovery(nextRecovery) {
403
+ const replacementProjection = inspectRecoveryProjection(nextRecovery);
404
+ const replacement = classifyMcpRecoveryAdmission(nextRecovery);
405
+ if (replacement.reasonCode === MCP_RECOVERY_INVALID_CODE) {
406
+ return latch(McpRecoveryBlockMode.ALL, MCP_RECOVERY_INVALID_CODE);
407
+ }
408
+ const replacementAuthority = new Set(
409
+ replacementProjection.replayDenied.map(replayDenyAuthorityKey),
410
+ );
411
+ const losesDeny = currentProjection.replayDenied.some(
412
+ (entry) => !replacementAuthority.has(replayDenyAuthorityKey(entry)),
413
+ );
414
+ if (losesDeny) {
415
+ return latch(
416
+ McpRecoveryBlockMode.ALL,
417
+ MCP_RECOVERY_DENY_REGRESSION_CODE,
418
+ );
419
+ }
420
+ currentProjection = replacementProjection;
421
+ currentAdmission = replacement;
422
+ return currentAdmission;
423
+ },
424
+ findReplayDeny(call) {
425
+ return findReplayDeny(currentProjection.replayDenied, call);
426
+ },
427
+ latchUnsafe(reasonCode = null) {
428
+ return latch(McpRecoveryBlockMode.UNSAFE, reasonCode);
429
+ },
430
+ latchAll(reasonCode = null) {
431
+ return latch(McpRecoveryBlockMode.ALL, reasonCode);
432
+ },
433
+ };
434
+ Object.freeze(controller);
435
+ RECOVERY_CONTROLLERS.add(controller);
436
+ return controller;
437
+ }
438
+
439
+ function isRecoveryController(value) {
440
+ return (
441
+ (typeof value === "object" || typeof value === "function") &&
442
+ value !== null &&
443
+ RECOVERY_CONTROLLERS.has(value)
444
+ );
445
+ }
446
+
447
+ export class McpLedgerRecoveryBlockedError extends Error {
448
+ constructor(effect, admission, options = {}) {
449
+ super(
450
+ options.message ||
451
+ `MCP ${effect} call blocked until durable recovery incidents are explicitly adjudicated`,
452
+ );
453
+ this.name = "McpLedgerRecoveryBlockedError";
454
+ this.code =
455
+ options.code || admission.reasonCode || "CC_MCP_LEDGER_RECOVERY_BLOCKED";
456
+ this.effect = effect;
457
+ this.blockMode = admission.blockMode;
458
+ }
459
+ }
460
+
461
+ export class McpExactReplayDeniedError extends Error {
462
+ constructor(effect, deny) {
463
+ super(
464
+ "MCP call exactly matches a prior confirmed-applied call and must not be replayed",
465
+ );
466
+ this.name = "McpExactReplayDeniedError";
467
+ this.code = MCP_EXACT_REPLAY_DENIED_CODE;
468
+ this.effect = effect;
469
+ this.ledgerId = deny?.ledgerId || null;
470
+ this.serverName = deny?.serverName || null;
471
+ this.toolName = deny?.toolName || null;
472
+ this.inputBytes = deny?.inputBytes ?? null;
473
+ this.replayDigest = deny?.replayDigest || null;
474
+ this.replayDenied = true;
475
+ this.retryable = false;
476
+ }
477
+ }
478
+
479
+ export class McpCallOutcomeUnknownError extends Error {
480
+ constructor(
481
+ ticket,
482
+ settlementError,
483
+ effect = McpEffect.UNKNOWN,
484
+ options = {},
485
+ ) {
486
+ super(
487
+ options.message ||
488
+ "MCP call outcome is unknown; do not retry automatically until durable recovery is adjudicated",
489
+ settlementError ? { cause: settlementError } : undefined,
490
+ );
491
+ this.name = "McpCallOutcomeUnknownError";
492
+ this.code = MCP_OUTCOME_UNKNOWN_CODE;
493
+ this.ledgerId =
494
+ safeProperty(ticket, "ledgerId") ||
495
+ safeProperty(settlementError, "ledgerId") ||
496
+ null;
497
+ this.effect = effect;
498
+ this.phase = options.phase || "settled";
499
+ this.outcomeUnknown = true;
500
+ this.retryable = false;
501
+ }
502
+ }
503
+
504
+ function safeProperty(value, property) {
505
+ try {
506
+ return value?.[property];
507
+ } catch {
508
+ return undefined;
509
+ }
510
+ }
511
+
512
+ function failureCode(error, fallback) {
513
+ const code = safeProperty(error, "code");
514
+ return typeof code === "string" && code ? code : fallback;
515
+ }
516
+
517
+ function outcomeUnknown(
518
+ controller,
519
+ ticket,
520
+ cause,
521
+ effect,
522
+ { phase = "settled", fallbackCode = "CC_MCP_LEDGER_SETTLE_FAILED" } = {},
523
+ ) {
524
+ controller?.latchUnsafe(failureCode(cause, fallbackCode));
525
+ return new McpCallOutcomeUnknownError(ticket, cause, effect, { phase });
526
+ }
527
+
528
+ async function settleWithRecoveryLatch(controller, operation) {
529
+ try {
530
+ return await operation();
531
+ } catch (error) {
532
+ controller?.latchUnsafe(failureCode(error, "CC_MCP_LEDGER_SETTLE_FAILED"));
533
+ throw error;
534
+ }
535
+ }
536
+
537
+ function wrapLedgerTicketForRecovery(ticket, controller) {
538
+ if (
539
+ !controller ||
540
+ (typeof ticket !== "object" && typeof ticket !== "function") ||
541
+ ticket === null
542
+ ) {
543
+ return ticket;
544
+ }
545
+
546
+ try {
547
+ if (isProxy(ticket)) {
548
+ const invalid = new TypeError("MCP ledger tickets cannot be Proxies");
549
+ invalid.code = "CC_MCP_LEDGER_TICKET_INVALID";
550
+ throw invalid;
551
+ }
552
+ const descriptors = Object.getOwnPropertyDescriptors(ticket);
553
+ for (const property of ["settle", "settleCall"]) {
554
+ const originalDescriptor = descriptors[property];
555
+ const method = Reflect.get(ticket, property, ticket);
556
+ if (typeof method === "function") {
557
+ descriptors[property] = {
558
+ configurable: false,
559
+ enumerable: originalDescriptor?.enumerable ?? true,
560
+ writable: false,
561
+ value: (...args) =>
562
+ settleWithRecoveryLatch(controller, () =>
563
+ Reflect.apply(method, ticket, args),
564
+ ),
565
+ };
566
+ } else if (property in ticket) {
567
+ const unavailable = new TypeError(
568
+ `MCP ledger ticket ${property} is not callable`,
569
+ );
570
+ unavailable.code = "CC_MCP_LEDGER_SETTLE_UNAVAILABLE";
571
+ throw unavailable;
572
+ }
573
+ }
574
+ // Ledger tickets are commonly frozen. Clone their descriptors so
575
+ // settlement can be wrapped without violating read-only invariants.
576
+ return Object.freeze(
577
+ Object.create(Object.getPrototypeOf(ticket), descriptors),
578
+ );
579
+ } catch (error) {
580
+ controller.latchUnsafe(failureCode(error, "CC_MCP_LEDGER_TICKET_INVALID"));
581
+ throw error;
582
+ }
583
+ }
584
+
585
+ function constrainRecoveryController(controller, options = {}) {
586
+ const constraint = classifyMcpRecoveryAdmission(null, options);
587
+ if (constraint.blockMode === McpRecoveryBlockMode.ALL) {
588
+ controller.latchAll(
589
+ constraint.reasonCode ||
590
+ (options.recoveryError != null
591
+ ? failureCode(
592
+ options.recoveryError,
593
+ "CC_MCP_LEDGER_EVENT_READ_FAILED",
594
+ )
595
+ : null),
596
+ );
597
+ } else if (constraint.blockMode === McpRecoveryBlockMode.UNSAFE) {
598
+ controller.latchUnsafe(constraint.reasonCode);
599
+ }
600
+ return controller;
601
+ }
602
+
603
+ /** Wrap an MCP ledger with a fail-closed recovery admission gate. */
604
+ export function guardMcpLedgerForRecovery(ledger, recovery, options = {}) {
605
+ if (!ledger) return ledger;
606
+ const ledgerBegin = ledger.begin;
607
+ if (typeof ledgerBegin !== "function") return ledger;
608
+ const controller = isRecoveryController(recovery) ? recovery : null;
609
+ if (controller) constrainRecoveryController(controller, options);
610
+ if (controller && GUARDED_LEDGER_CONTROLLERS.get(ledger) === controller) {
611
+ return ledger;
612
+ }
613
+ const staticProjection = controller
614
+ ? null
615
+ : inspectRecoveryProjection(recovery);
616
+ const staticAdmission = controller
617
+ ? null
618
+ : classifyMcpRecoveryAdmission(recovery, options);
619
+ if (
620
+ !controller &&
621
+ !staticAdmission.blockMode &&
622
+ staticProjection.replayDenied.length === 0
623
+ ) {
624
+ return ledger;
625
+ }
626
+ const getAdmission = () =>
627
+ controller ? controller.getAdmission() : staticAdmission;
628
+ const getReplayDeny = (call) =>
629
+ controller
630
+ ? controller.findReplayDeny(call)
631
+ : findReplayDeny(staticProjection.replayDenied, call);
632
+
633
+ const begin = async (call = {}) => {
634
+ const callSnapshot = snapshotMcpAdmissionCall(call);
635
+ const admission = getAdmission();
636
+ const normalizedEffect = normalizeMcpEffectContract(
637
+ snapshotMcpJsonRpcInput(
638
+ callSnapshot.effectContract || callSnapshot.effect || {},
639
+ ),
640
+ );
641
+ const ledgerCall = Object.freeze({
642
+ ...callSnapshot,
643
+ effectContract: normalizedEffect,
644
+ });
645
+ const effect =
646
+ normalizedEffect.effect === McpEffect.READ &&
647
+ normalizedEffect.trusted !== true
648
+ ? McpEffect.UNKNOWN
649
+ : normalizedEffect.effect;
650
+ const deny = getReplayDeny(ledgerCall);
651
+ if (deny) {
652
+ throw new McpExactReplayDeniedError(effect, deny);
653
+ }
654
+ const blocked =
655
+ admission.blockMode === McpRecoveryBlockMode.ALL ||
656
+ (admission.blockMode === McpRecoveryBlockMode.UNSAFE &&
657
+ effect !== McpEffect.READ);
658
+ if (blocked) {
659
+ throw new McpLedgerRecoveryBlockedError(effect, admission, options);
660
+ }
661
+ const ticket = await Reflect.apply(ledgerBegin, ledger, [ledgerCall]);
662
+ return wrapLedgerTicketForRecovery(ticket, controller);
663
+ };
664
+
665
+ const guarded = {
666
+ begin,
667
+ beginCall: begin,
668
+ };
669
+ Object.defineProperty(guarded, "recoveryAdmission", {
670
+ enumerable: true,
671
+ get: getAdmission,
672
+ });
673
+ for (const method of ["settle", "settleCall"]) {
674
+ const ledgerMethod = ledger[method];
675
+ if (typeof ledgerMethod === "function") {
676
+ guarded[method] = (...args) =>
677
+ controller
678
+ ? settleWithRecoveryLatch(controller, () =>
679
+ Reflect.apply(ledgerMethod, ledger, args),
680
+ )
681
+ : Reflect.apply(ledgerMethod, ledger, args);
682
+ }
683
+ }
684
+ for (const method of ["get", "list"]) {
685
+ const ledgerMethod = ledger[method];
686
+ if (typeof ledgerMethod === "function") {
687
+ guarded[method] = ledgerMethod.bind(ledger);
688
+ }
689
+ }
690
+ if (ledger.prewriteFailurePolicy) {
691
+ guarded.prewriteFailurePolicy = ledger.prewriteFailurePolicy;
692
+ }
693
+ Object.freeze(guarded);
694
+ if (controller) GUARDED_LEDGER_CONTROLLERS.set(guarded, controller);
695
+ return guarded;
696
+ }
697
+
698
+ /**
699
+ * Monotonically tighten a branded dynamic ledger after an external call's
700
+ * outcome becomes unknowable. The WeakMap is the capability boundary: callers
701
+ * can latch a guarded ledger but cannot read, replace, or downgrade its
702
+ * controller.
703
+ */
704
+ export function markMcpLedgerOutcomeUnknown(
705
+ ledger,
706
+ reasonCode = MCP_OUTCOME_UNKNOWN_CODE,
707
+ ) {
708
+ const controller =
709
+ ledger && (typeof ledger === "object" || typeof ledger === "function")
710
+ ? GUARDED_LEDGER_CONTROLLERS.get(ledger)
711
+ : null;
712
+ if (!controller) return false;
713
+ controller.latchUnsafe(
714
+ typeof reasonCode === "string" && reasonCode
715
+ ? reasonCode
716
+ : MCP_OUTCOME_UNKNOWN_CODE,
717
+ );
718
+ return true;
719
+ }
720
+
721
+ /** Build the normal call ledger, then apply the shared recovery admission. */
722
+ export function createRecoveryGuardedMcpCallLedger(options = {}) {
723
+ const {
724
+ sink = null,
725
+ recovery = null,
726
+ recoveryError = null,
727
+ blockMode = null,
728
+ controller = null,
729
+ code,
730
+ message,
731
+ ...ledgerOptions
732
+ } = options;
733
+ return guardMcpLedgerForRecovery(
734
+ createMcpCallLedger({ ...ledgerOptions, sink }),
735
+ controller || recovery,
736
+ { recoveryError, blockMode, code, message },
737
+ );
738
+ }
739
+
740
+ async function resolveHostEffectContract(
741
+ resolveEffect,
742
+ client,
743
+ serverName,
744
+ toolName,
745
+ input,
746
+ ) {
747
+ let resolved = null;
748
+ if (resolveEffect) {
749
+ try {
750
+ resolved = await Reflect.apply(resolveEffect, client, [
751
+ serverName,
752
+ toolName,
753
+ input,
754
+ ]);
755
+ } catch {
756
+ // A failed host classification is not evidence that a tool is read-only.
757
+ resolved = null;
758
+ }
759
+ }
760
+ const contract =
761
+ resolved && typeof resolved === "object" && resolved.effectContract
762
+ ? resolved.effectContract
763
+ : resolved || {};
764
+ const normalizedContract = normalizeMcpEffectContract(contract);
765
+ const effectContract =
766
+ normalizedContract.effect === McpEffect.READ &&
767
+ normalizedContract.trusted !== true
768
+ ? normalizeMcpEffectContract({
769
+ ...normalizedContract,
770
+ effect: McpEffect.UNKNOWN,
771
+ })
772
+ : normalizedContract;
773
+ return {
774
+ effectContract,
775
+ resourceScopes:
776
+ resolved && typeof resolved === "object"
777
+ ? resolved.resourceScopes
778
+ : undefined,
779
+ networkScopes:
780
+ resolved && typeof resolved === "object"
781
+ ? resolved.networkScopes
782
+ : undefined,
783
+ };
784
+ }
785
+
786
+ async function settleHostCall(ledger, ticket, outcome) {
787
+ if (typeof ticket?.settle === "function") {
788
+ return Reflect.apply(ticket.settle, ticket, [outcome]);
789
+ }
790
+ if (typeof ticket?.settleCall === "function") {
791
+ return Reflect.apply(ticket.settleCall, ticket, [outcome]);
792
+ }
793
+ if (typeof ledger.settleCall === "function") {
794
+ return Reflect.apply(ledger.settleCall, ledger, [ticket, outcome]);
795
+ }
796
+ if (typeof ledger.settle === "function") {
797
+ return Reflect.apply(ledger.settle, ledger, [ticket, outcome]);
798
+ }
799
+ const error = new Error("MCP ledger ticket has no settlement method");
800
+ error.code = "CC_MCP_LEDGER_SETTLE_UNAVAILABLE";
801
+ throw error;
802
+ }
803
+
804
+ /**
805
+ * Wrap host-owned auxiliary MCP calls with the same dynamic recovery admission
806
+ * and durable begin/settle protocol used by agent-core. Agent-core dispatch
807
+ * must continue to receive the raw client plus the shared guarded ledger so a
808
+ * model-originated call is recorded exactly once.
809
+ */
810
+ export function createRecoveryGuardedMcpClient({
811
+ client,
812
+ ledger,
813
+ controller,
814
+ resolveEffect = null,
815
+ sessionId = null,
816
+ } = {}) {
817
+ if (!client || typeof client.callTool !== "function") {
818
+ throw new TypeError("MCP client wrapper requires client.callTool()");
819
+ }
820
+ if (!ledger || typeof ledger.begin !== "function") {
821
+ throw new TypeError("MCP client wrapper requires a call ledger");
822
+ }
823
+ if (!isRecoveryController(controller)) {
824
+ throw new TypeError("MCP client wrapper requires a recovery controller");
825
+ }
826
+ if (resolveEffect != null && typeof resolveEffect !== "function") {
827
+ throw new TypeError("MCP client effect resolver must be a function");
828
+ }
829
+
830
+ const existingGuard = GUARDED_MCP_CLIENTS.get(client);
831
+ if (existingGuard) {
832
+ if (
833
+ existingGuard.ledger === ledger &&
834
+ existingGuard.controller === controller &&
835
+ existingGuard.resolveEffect === resolveEffect &&
836
+ existingGuard.sessionId === sessionId
837
+ ) {
838
+ return client;
839
+ }
840
+ const error = new TypeError(
841
+ "MCP client is already guarded by a different recovery authority",
842
+ );
843
+ error.code = "CC_MCP_CLIENT_ALREADY_GUARDED";
844
+ throw error;
845
+ }
846
+
847
+ const admittedLedger = guardMcpLedgerForRecovery(ledger, controller);
848
+ const rawCallTool = client.callTool;
849
+ const callTool = async (serverName, toolName, input = {}, ...rest) => {
850
+ // Snapshot before the first await. Admission, durable identity and the raw
851
+ // transport all receive this exact deeply-frozen JSON value.
852
+ const inputSnapshot = snapshotMcpJsonRpcInput(input);
853
+ const effect = await resolveHostEffectContract(
854
+ resolveEffect,
855
+ client,
856
+ serverName,
857
+ toolName,
858
+ inputSnapshot,
859
+ );
860
+ const ticket = await admittedLedger.begin({
861
+ sessionId,
862
+ serverName,
863
+ toolName,
864
+ input: inputSnapshot,
865
+ ...effect,
866
+ });
867
+
868
+ let result;
869
+ try {
870
+ result = await Reflect.apply(rawCallTool, client, [
871
+ serverName,
872
+ toolName,
873
+ inputSnapshot,
874
+ ...rest,
875
+ ]);
876
+ } catch (callError) {
877
+ if (effect.effectContract.effect !== McpEffect.READ) {
878
+ throw outcomeUnknown(
879
+ controller,
880
+ ticket,
881
+ callError,
882
+ effect.effectContract.effect,
883
+ {
884
+ phase: "call",
885
+ fallbackCode: "CC_MCP_TRANSPORT_OUTCOME_UNKNOWN",
886
+ },
887
+ );
888
+ }
889
+ try {
890
+ await settleHostCall(admittedLedger, ticket, {
891
+ status: "failed",
892
+ error: callError,
893
+ });
894
+ } catch (settlementError) {
895
+ throw outcomeUnknown(
896
+ controller,
897
+ ticket,
898
+ settlementError,
899
+ effect.effectContract.effect,
900
+ );
901
+ }
902
+ throw callError;
903
+ }
904
+
905
+ let protocolError;
906
+ try {
907
+ if (
908
+ result !== null &&
909
+ (typeof result === "object" || typeof result === "function") &&
910
+ isProxy(result)
911
+ ) {
912
+ const invalid = new TypeError("MCP result cannot be a Proxy");
913
+ invalid.code = "CC_MCP_PROTOCOL_RESULT_INVALID";
914
+ throw invalid;
915
+ }
916
+ protocolError = result?.isError === true;
917
+ } catch (inspectionError) {
918
+ throw outcomeUnknown(
919
+ controller,
920
+ ticket,
921
+ inspectionError,
922
+ effect.effectContract.effect,
923
+ {
924
+ phase: "result",
925
+ fallbackCode: "CC_MCP_PROTOCOL_RESULT_INVALID",
926
+ },
927
+ );
928
+ }
929
+ try {
930
+ const error = protocolError
931
+ ? Object.assign(new Error("MCP server returned isError=true"), {
932
+ code: "CC_MCP_PROTOCOL_TOOL_ERROR",
933
+ })
934
+ : null;
935
+ await settleHostCall(
936
+ admittedLedger,
937
+ ticket,
938
+ protocolError
939
+ ? { status: "failed", output: result, error }
940
+ : { status: "completed", output: result },
941
+ );
942
+ } catch (settlementError) {
943
+ throw outcomeUnknown(
944
+ controller,
945
+ ticket,
946
+ settlementError,
947
+ effect.effectContract.effect,
948
+ );
949
+ }
950
+ return result;
951
+ };
952
+
953
+ const methodCache = new Map();
954
+ let wrappedClient;
955
+ // Never proxy the raw client directly: a frozen, non-configurable callTool
956
+ // property would require the get trap to return the raw function byte-for-
957
+ // byte, defeating the guard (and otherwise throws a Proxy invariant error).
958
+ // An extensible facade lets reads/writes delegate to the raw instance while
959
+ // methods still execute with the raw `this` binding.
960
+ const facade = Object.create(Object.getPrototypeOf(client));
961
+ wrappedClient = new Proxy(facade, {
962
+ get(_facade, property) {
963
+ if (property === "callTool") return callTool;
964
+ const value = Reflect.get(client, property, client);
965
+ if (value === client) return wrappedClient;
966
+ if (typeof value !== "function") return value;
967
+ const cached = methodCache.get(property);
968
+ if (cached?.source === value) return cached.wrapper;
969
+ const wrapper = (...args) => {
970
+ const result = Reflect.apply(value, client, args);
971
+ if (result === client) return wrappedClient;
972
+ if (
973
+ result !== null &&
974
+ (typeof result === "object" || typeof result === "function")
975
+ ) {
976
+ let then;
977
+ try {
978
+ then = Reflect.get(result, "then", result);
979
+ } catch (error) {
980
+ return Promise.reject(error);
981
+ }
982
+ if (typeof then === "function") {
983
+ return Promise.resolve(result).then((resolved) =>
984
+ resolved === client ? wrappedClient : resolved,
985
+ );
986
+ }
987
+ }
988
+ return result;
989
+ };
990
+ methodCache.set(property, { source: value, wrapper });
991
+ return wrapper;
992
+ },
993
+ set(_facade, property, value) {
994
+ if (property === "callTool") return false;
995
+ return Reflect.set(
996
+ client,
997
+ property,
998
+ value === wrappedClient ? client : value,
999
+ client,
1000
+ );
1001
+ },
1002
+ has(_facade, property) {
1003
+ return Reflect.has(client, property);
1004
+ },
1005
+ ownKeys() {
1006
+ return Reflect.ownKeys(client);
1007
+ },
1008
+ getOwnPropertyDescriptor(_facade, property) {
1009
+ const descriptor = Reflect.getOwnPropertyDescriptor(client, property);
1010
+ if (!descriptor) return undefined;
1011
+ if (property === "callTool") {
1012
+ return {
1013
+ configurable: true,
1014
+ enumerable: descriptor.enumerable,
1015
+ writable: false,
1016
+ value: callTool,
1017
+ };
1018
+ }
1019
+ if ("value" in descriptor) {
1020
+ return {
1021
+ configurable: true,
1022
+ enumerable: descriptor.enumerable,
1023
+ writable: descriptor.writable,
1024
+ value: Reflect.get(wrappedClient, property, wrappedClient),
1025
+ };
1026
+ }
1027
+ return {
1028
+ configurable: true,
1029
+ enumerable: descriptor.enumerable,
1030
+ get: descriptor.get
1031
+ ? () => Reflect.get(wrappedClient, property, wrappedClient)
1032
+ : undefined,
1033
+ set: descriptor.set
1034
+ ? (value) =>
1035
+ Reflect.set(wrappedClient, property, value, wrappedClient)
1036
+ : undefined,
1037
+ };
1038
+ },
1039
+ defineProperty(_facade, property, descriptor) {
1040
+ // A non-configurable property on the raw object cannot be mirrored onto
1041
+ // the facade without reintroducing the get-trap invariant above.
1042
+ if (property === "callTool" || descriptor.configurable === false) {
1043
+ return false;
1044
+ }
1045
+ return Reflect.defineProperty(client, property, descriptor);
1046
+ },
1047
+ deleteProperty(_facade, property) {
1048
+ if (property === "callTool") return false;
1049
+ return Reflect.deleteProperty(client, property);
1050
+ },
1051
+ getPrototypeOf() {
1052
+ return Reflect.getPrototypeOf(client);
1053
+ },
1054
+ preventExtensions() {
1055
+ return false;
1056
+ },
1057
+ });
1058
+ GUARDED_MCP_CLIENTS.set(wrappedClient, {
1059
+ ledger,
1060
+ controller,
1061
+ resolveEffect,
1062
+ sessionId,
1063
+ });
1064
+ return wrappedClient;
1065
+ }