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
@@ -22,6 +22,7 @@
22
22
  * - bypassPermissions → AUTOPILOT (everything allowed)
23
23
  */
24
24
 
25
+ import { randomUUID } from "node:crypto";
25
26
  import { bootstrap } from "./bootstrap.js";
26
27
  import {
27
28
  buildSystemPrompt,
@@ -46,7 +47,10 @@ import {
46
47
  appendLlmRetryCompact as jsonlAppendLlmRetryCompact,
47
48
  appendCompactEvent as jsonlAppendCompactEvent,
48
49
  appendEvent as jsonlAppendEvent,
50
+ appendAuthorityEvent as jsonlAppendAuthorityEvent,
49
51
  readEvents as jsonlReadEvents,
52
+ readVerifiedEvents as jsonlReadVerifiedEvents,
53
+ findLatestEvent as jsonlFindLatestEvent,
50
54
  rebuildMessages as jsonlRebuildMessages,
51
55
  sessionExists as jsonlSessionExists,
52
56
  getLastSessionId as jsonlGetLastSessionId,
@@ -60,6 +64,13 @@ import {
60
64
  } from "../lib/side-effect-ledger.js";
61
65
  import { DiffReviewFollowUpTracker } from "../lib/diff-review-follow-up.js";
62
66
  import { SIDE_EFFECT_LEDGER_EVENT } from "../lib/side-effect-ledger-store.js";
67
+ import {
68
+ createSessionMcpLedgerSink,
69
+ formatMcpLedgerRecoveryNotice,
70
+ loadMcpLedgerRecovery,
71
+ } from "../lib/mcp-call-ledger-store.js";
72
+ import { createMcpHostRecoveryRuntime } from "../lib/mcp-host-recovery-runtime.js";
73
+ import { readSessionHostResumeState } from "../lib/session-host-snapshot.js";
63
74
  import { TurnBindingLog, createTurnBindingFeed } from "../lib/turn-binding.js";
64
75
  import { TURN_BINDING_EVENT } from "../lib/turn-binding-store.js";
65
76
  import { operationIdempotencyKey } from "../lib/idempotency.js";
@@ -99,6 +110,7 @@ import {
99
110
  } from "../lib/repl-denials.js";
100
111
  import executionBroker from "../lib/process-execution-broker/index.js";
101
112
  import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
113
+ import { formatManagedCheckpointEvent } from "../lib/managed-checkpoint-render.js";
102
114
 
103
115
  const goalBrokerRunner = executionBroker.spawnSync.bind(executionBroker);
104
116
 
@@ -295,7 +307,7 @@ export function resolveHeadlessSession(options = {}, store = {}, fallbackId) {
295
307
  * apart from the injected store's side effect; both `sessionExists`/`forkSession`
296
308
  * are injection seams so this is unit-testable without disk.
297
309
  *
298
- * @param {{forkSession?:boolean, sessionId?:string|null}} opts
310
+ * @param {{forkSession?:boolean, sessionId?:string|null, forkRequestId?:string}} opts
299
311
  * @param {{sessionExists?:Function, forkSession?:Function}} store
300
312
  * @returns {{ sessionId:string|null, forkedFrom:string|null, missing:boolean }}
301
313
  */
@@ -306,8 +318,14 @@ export function applyForkSession(opts = {}, store = {}) {
306
318
  if (typeof store.sessionExists === "function" && !store.sessionExists(id)) {
307
319
  return { sessionId: id, forkedFrom: null, missing: true };
308
320
  }
321
+ const requestId =
322
+ typeof opts.forkRequestId === "string" && opts.forkRequestId.length > 0
323
+ ? opts.forkRequestId
324
+ : `cli-${randomUUID()}`;
309
325
  const newId =
310
- typeof store.forkSession === "function" ? store.forkSession(id) : null;
326
+ typeof store.forkSession === "function"
327
+ ? store.forkSession(id, { requestId })
328
+ : null;
311
329
  if (!newId) return { sessionId: id, forkedFrom: null, missing: false };
312
330
  return { sessionId: newId, forkedFrom: id, missing: false };
313
331
  }
@@ -341,7 +359,7 @@ export function applyForkSession(opts = {}, store = {}) {
341
359
  * @param {boolean} [options.expandFileRefs=true] Expand `@path` file references
342
360
  * in the prompt into context blocks.
343
361
  * @param {object} [deps] Injection seam for tests.
344
- * @returns {Promise<{ exitCode:number, result:string, isError:boolean }>}
362
+ * @returns {Promise<{ exitCode:number, result:string, isError:boolean, sessionSnapshot?:object }>}
345
363
  */
346
364
  export async function runAgentHeadless(options = {}, deps = {}) {
347
365
  const trustedWorkspaceRoot = options.cwd || process.cwd();
@@ -365,6 +383,80 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
365
383
  );
366
384
  }
367
385
 
386
+ const isStream = outputFormat === "stream-json";
387
+ const isJson = outputFormat === "json";
388
+ const isText = outputFormat === "text";
389
+ const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
390
+ const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
391
+ if (!deps.writeOut && !deps.writeErr) installPipeSafety();
392
+
393
+ const hasInjectedSessionStore =
394
+ typeof deps.sessionExists === "function" ||
395
+ typeof deps.rebuildMessages === "function" ||
396
+ typeof deps.appendEvent === "function" ||
397
+ typeof deps.appendAuthorityEvent === "function" ||
398
+ typeof deps.readVerifiedEvents === "function";
399
+ const { sessionId, resumeId, persist } = resolveHeadlessSession(
400
+ options,
401
+ { getLastSessionId: deps.getLastSessionId || jsonlGetLastSessionId },
402
+ `headless-${Date.now()}-${process.pid}`,
403
+ );
404
+
405
+ const emitHeadlessError = (resultMsg) => {
406
+ if (isStream) {
407
+ writeOut(
408
+ JSON.stringify({
409
+ type: "result",
410
+ subtype: "error",
411
+ is_error: true,
412
+ error: resultMsg,
413
+ }) + "\n",
414
+ );
415
+ } else if (isJson) {
416
+ writeOut(
417
+ JSON.stringify(
418
+ buildResultEnvelope({
419
+ subtype: "error",
420
+ isError: true,
421
+ result: resultMsg,
422
+ sessionId,
423
+ toolCalls: [],
424
+ usage: {},
425
+ numTurns: 0,
426
+ durationMs: 0,
427
+ }),
428
+ ) + "\n",
429
+ );
430
+ }
431
+ };
432
+
433
+ // Resume authority is the first host boundary after argument validation.
434
+ // In particular this precedes /config writes, slash-macro bang expansion,
435
+ // settings/plugin loading, bootstrap, model access, hooks, MCP and tools.
436
+ const canReadCanonicalResume =
437
+ !hasInjectedSessionStore || typeof deps.readVerifiedEvents === "function";
438
+ const canonicalResume =
439
+ resumeId && canReadCanonicalResume
440
+ ? readSessionHostResumeState(resumeId, {
441
+ sessionExists: deps.sessionExists || jsonlSessionExists,
442
+ readVerifiedEvents:
443
+ deps.readVerifiedEvents || jsonlReadVerifiedEvents,
444
+ })
445
+ : null;
446
+ if (canonicalResume && !canonicalResume.snapshot.verified) {
447
+ const message =
448
+ "CC_SESSION_HOST_SNAPSHOT_UNVERIFIED: canonical JSONL session is not " +
449
+ "fully verified; resume was refused";
450
+ emitHeadlessError(message);
451
+ writeErr(`${message}\n`);
452
+ return {
453
+ exitCode: 1,
454
+ result: message,
455
+ isError: true,
456
+ sessionSnapshot: canonicalResume.snapshot,
457
+ };
458
+ }
459
+
368
460
  // `let` (not const): a custom-command macro's `model:` frontmatter may
369
461
  // override it below (when the user passed no explicit --model), mirroring
370
462
  // `cc command run`.
@@ -418,16 +510,20 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
418
510
  let settingsHooks = options.settingsHooks || null;
419
511
  if (!settingsHooks) {
420
512
  try {
421
- const { loadHooks, projectHookTrustNotice } =
513
+ const { loadHooks, projectHookTrustNotice, attachAuthorityErrors } =
422
514
  await import("../lib/settings-hooks.cjs");
423
515
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
424
516
  // Fold in installed plugins' hooks/hooks.json (Phase 3.3c) — plugins ADD
425
517
  // to the user's settings hooks, never replace them.
426
518
  const { mergePluginHooks } =
427
519
  await import("../lib/plugin-runtime/hooks.js");
428
- const effectiveHooks = mergePluginHooks(loaded.hooks, { cwd });
520
+ const effectiveHooks = mergePluginHooks(
521
+ attachAuthorityErrors(loaded.hooks, loaded.authorityErrors),
522
+ { cwd },
523
+ );
429
524
  settingsHooks =
430
- effectiveHooks && Object.keys(effectiveHooks).length > 0
525
+ Object.keys(effectiveHooks).length > 0 ||
526
+ effectiveHooks._authorityErrors.length > 0
431
527
  ? effectiveHooks
432
528
  : null;
433
529
  // First-run trust notice for an untrusted/cloned repo's shell-running
@@ -441,8 +537,17 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
441
537
  } catch {
442
538
  /* trust notice is best-effort */
443
539
  }
444
- } catch {
445
- settingsHooks = null; // fail-open
540
+ } catch (error) {
541
+ settingsHooks = {};
542
+ Object.defineProperty(settingsHooks, "_authorityErrors", {
543
+ value: Object.freeze([
544
+ Object.freeze({
545
+ sourceFile: null,
546
+ code: error?.code || "CC_HOOK_AUTHORITY_LOAD_FAILED",
547
+ }),
548
+ ]),
549
+ enumerable: false,
550
+ });
446
551
  }
447
552
  }
448
553
 
@@ -493,18 +598,36 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
493
598
  const m = await import("../lib/session-core-singletons.js");
494
599
  return m.getApprovalGate();
495
600
  });
496
- // stdout carries the machine-consumable payload; stderr carries the human
497
- // trace so `cc agent -p ... > out.txt` keeps `out.txt` clean.
498
- const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
499
- const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
500
- // Only when we own the real stdout/stderr (no injected seams = production,
501
- // not tests): guard against a downstream `| head` closing the pipe, which
502
- // would otherwise crash with an unhandled EPIPE. Idempotent across calls.
503
- if (!deps.writeOut && !deps.writeErr) {
504
- installPipeSafety();
505
- }
506
601
  // Session persistence seam (file-based JSONL; DB-free, like the rest of
507
602
  // headless). Defaults to the real store; tests inject fakes.
603
+ const storeReadEvents = deps.readEvents || jsonlReadEvents;
604
+ const unavailableAuthorityCapability = (operation) => () => {
605
+ const error = new Error(
606
+ `Injected session store must provide ${operation} for MCP authority`,
607
+ );
608
+ error.code = "SESSION_AUTHORITY_CAPABILITY_UNAVAILABLE";
609
+ throw error;
610
+ };
611
+ const storeFindLatestEvent =
612
+ deps.findLatestEvent ||
613
+ (deps.readEvents
614
+ ? (sessionId, type, predicate = null) => {
615
+ const events = storeReadEvents(sessionId) || [];
616
+ const wanted = Array.isArray(type) ? new Set(type) : null;
617
+ for (let index = events.length - 1; index >= 0; index -= 1) {
618
+ const event = events[index];
619
+ const typeMatches = wanted
620
+ ? wanted.has(event?.type)
621
+ : type == null || event?.type === type;
622
+ if (!typeMatches) continue;
623
+ if (typeof predicate === "function" && !predicate(event)) continue;
624
+ return event;
625
+ }
626
+ return null;
627
+ }
628
+ : hasInjectedSessionStore
629
+ ? () => null
630
+ : jsonlFindLatestEvent);
508
631
  const store = {
509
632
  sessionExists: deps.sessionExists || jsonlSessionExists,
510
633
  rebuildMessages: deps.rebuildMessages || jsonlRebuildMessages,
@@ -514,19 +637,34 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
514
637
  deps.appendAssistantMessage || jsonlAppendAssistantMessage,
515
638
  appendTokenUsage: deps.appendTokenUsage || jsonlAppendTokenUsage,
516
639
  appendToolCallCompact:
517
- deps.appendToolCallCompact || jsonlAppendToolCallCompact,
640
+ deps.appendToolCallCompact ||
641
+ (hasInjectedSessionStore ? () => true : jsonlAppendToolCallCompact),
518
642
  appendLlmRetryCompact:
519
- deps.appendLlmRetryCompact || jsonlAppendLlmRetryCompact,
520
- appendCompactEvent: deps.appendCompactEvent || jsonlAppendCompactEvent,
521
- appendEvent: deps.appendEvent || jsonlAppendEvent,
522
- readEvents: deps.readEvents || jsonlReadEvents,
643
+ deps.appendLlmRetryCompact ||
644
+ (hasInjectedSessionStore ? () => true : jsonlAppendLlmRetryCompact),
645
+ appendCompactEvent:
646
+ deps.appendCompactEvent ||
647
+ (hasInjectedSessionStore ? () => true : jsonlAppendCompactEvent),
648
+ appendEvent:
649
+ deps.appendEvent ||
650
+ (hasInjectedSessionStore ? () => true : jsonlAppendEvent),
651
+ appendAuthorityEvent:
652
+ deps.appendAuthorityEvent ||
653
+ (hasInjectedSessionStore
654
+ ? unavailableAuthorityCapability("appendAuthorityEvent")
655
+ : jsonlAppendAuthorityEvent),
656
+ readEvents: storeReadEvents,
657
+ readVerifiedEvents:
658
+ deps.readVerifiedEvents ||
659
+ (hasInjectedSessionStore
660
+ ? unavailableAuthorityCapability("readVerifiedEvents")
661
+ : jsonlReadVerifiedEvents),
662
+ findLatestEvent: storeFindLatestEvent,
523
663
  getLastSessionId: deps.getLastSessionId || jsonlGetLastSessionId,
524
- verifySession: deps.verifySession || jsonlVerifySession,
664
+ verifySession:
665
+ deps.verifySession ||
666
+ (hasInjectedSessionStore ? () => null : jsonlVerifySession),
525
667
  };
526
- const isStream = outputFormat === "stream-json";
527
- const isJson = outputFormat === "json";
528
- const isText = outputFormat === "text";
529
-
530
668
  // ── Headless `/config` directive (Claude-Code 2.1.181: /config in -p mode) ──
531
669
  // A leading `/config …` prompt is a one-shot config get/set/show, not a task
532
670
  // for the LLM — handled before bootstrap/session/model so it never spends a
@@ -571,6 +709,10 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
571
709
  return { exitCode: isError ? 1 : 0, result: text, isError };
572
710
  }
573
711
 
712
+ if (options.continueSession === true && !resumeId && isText) {
713
+ writeErr("No previous session to continue; starting a new one.\n");
714
+ }
715
+
574
716
  // ── Custom slash-command macros (Claude-Code parity: a .claude/commands/*
575
717
  // command runs in `-p` mode too, not just the interactive REPL). A leading
576
718
  // `/name …` that resolves to a user/project command is expanded into its
@@ -661,50 +803,6 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
661
803
  // Continue without DB — static-prompt fallback.
662
804
  }
663
805
 
664
- // ── Resolve session continuity (--resume / --continue) ─────────────────
665
- const { sessionId, resumeId, persist } = resolveHeadlessSession(
666
- options,
667
- store,
668
- `headless-${Date.now()}-${process.pid}`,
669
- );
670
- if (options.continueSession === true && !resumeId && isText) {
671
- writeErr("No previous session to continue; starting a new one.\n");
672
- }
673
-
674
- // Machine-readable modes (`--output-format json` / `stream-json`) must ALWAYS
675
- // end with a terminal result envelope — a consumer parsing stdout otherwise
676
- // gets nothing and can't tell success from failure. Several setup-phase error
677
- // paths below early-return BEFORE the main loop's try/catch envelope (and
678
- // before `system/init`), so route them through this so stdout is never empty.
679
- // No-op in text mode (those paths already writeErr a human message).
680
- const emitHeadlessError = (resultMsg) => {
681
- if (isStream) {
682
- writeOut(
683
- JSON.stringify({
684
- type: "result",
685
- subtype: "error",
686
- is_error: true,
687
- error: resultMsg,
688
- }) + "\n",
689
- );
690
- } else if (isJson) {
691
- writeOut(
692
- JSON.stringify(
693
- buildResultEnvelope({
694
- subtype: "error",
695
- isError: true,
696
- result: resultMsg,
697
- sessionId,
698
- toolCalls: [],
699
- usage: {},
700
- numTurns: 0,
701
- durationMs: 0,
702
- }),
703
- ) + "\n",
704
- );
705
- }
706
- };
707
-
708
806
  const setupHooks = await executeLifecycleHooks(
709
807
  "Setup",
710
808
  {
@@ -747,15 +845,19 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
747
845
  }
748
846
  userContent = expansion.prompt;
749
847
 
750
- // Load prior conversation when resuming an existing session. The fresh
751
- // system prompt always leads; we drop any persisted system turns so it is
752
- // never duplicated.
848
+ // Load prior conversation when resuming an existing session. The fresh host
849
+ // system prompt always leads; all system turns from the same verified
850
+ // canonical sample follow it (including compact checkpoint summaries).
753
851
  let history = [];
754
- if (resumeId && store.sessionExists(resumeId)) {
755
- // Tamper gate: a broken transcript hash chain means the file was edited
852
+ if (canonicalResume) {
853
+ history = canonicalResume.messages.filter(Boolean);
854
+ } else if (resumeId && store.sessionExists(resumeId)) {
855
+ // Compatibility gate for injected stores without a verified event reader.
856
+ // Real JSONL resumes were handled above and never reach this branch. A
857
+ // broken transcript hash chain means the file was edited
756
858
  // outside the store. Headless runs fail closed — a tampered transcript is
757
859
  // never silently rebuilt into trusted model context. Escape hatch:
758
- // CC_ALLOW_TAMPERED_RESUME=1 resumes with a stderr warning.
860
+ // CC_ALLOW_TAMPERED_RESUME=1 is retained only for this injected-store path.
759
861
  let trust = null;
760
862
  try {
761
863
  trust = store.verifySession(resumeId);
@@ -825,6 +927,9 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
825
927
  let sideEffectSeq = 0;
826
928
  let currentSideEffectOpId = null;
827
929
  let resumeSideEffectContext = null;
930
+ let resumeMcpCallContext = null;
931
+ let resumeMcpRecovery = null;
932
+ let resumeMcpRecoveryError = null;
828
933
  let resumeAsyncHookContext = null;
829
934
  const persistSideEffectLedger = () => {
830
935
  if (!persist) return;
@@ -862,18 +967,13 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
862
967
  let turnBindingLoadError = null;
863
968
  if (persist) {
864
969
  try {
865
- const events = store.readEvents(sessionId) || [];
866
- for (let i = events.length - 1; i >= 0; i--) {
867
- const e = events[i];
868
- if (
869
- e &&
870
- e.type === TURN_BINDING_EVENT &&
871
- e.data &&
872
- Array.isArray(e.data.turns)
873
- ) {
874
- turnBindingLog = TurnBindingLog.fromJSON(e.data);
875
- break;
876
- }
970
+ const event = store.findLatestEvent(
971
+ sessionId,
972
+ TURN_BINDING_EVENT,
973
+ (candidate) => Array.isArray(candidate?.data?.turns),
974
+ );
975
+ if (event) {
976
+ turnBindingLog = TurnBindingLog.fromJSON(event.data);
877
977
  }
878
978
  } catch (cause) {
879
979
  const error = new Error(
@@ -918,20 +1018,15 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
918
1018
  };
919
1019
  if (persist) {
920
1020
  try {
921
- const events = store.readEvents(sessionId) || [];
922
- for (let i = events.length - 1; i >= 0; i--) {
923
- const e = events[i];
924
- if (
925
- e &&
926
- e.type === SIDE_EFFECT_LEDGER_EVENT &&
927
- e.data &&
928
- Array.isArray(e.data.ops)
929
- ) {
930
- sideEffectLedger = SideEffectLedger.fromJSON(e.data, {
931
- clock: deps.now || null,
932
- });
933
- break;
934
- }
1021
+ const event = store.findLatestEvent(
1022
+ sessionId,
1023
+ SIDE_EFFECT_LEDGER_EVENT,
1024
+ (candidate) => Array.isArray(candidate?.data?.ops),
1025
+ );
1026
+ if (event) {
1027
+ sideEffectLedger = SideEffectLedger.fromJSON(event.data, {
1028
+ clock: deps.now || null,
1029
+ });
935
1030
  }
936
1031
  } catch (cause) {
937
1032
  const error = new Error(
@@ -978,6 +1073,41 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
978
1073
  } catch {
979
1074
  resumeSideEffectContext = null;
980
1075
  }
1076
+ // MCP calls have their own content-free started/settled ledger. A
1077
+ // started-only record means the external server may have completed the
1078
+ // operation before the process died, so replay must stop for inspection.
1079
+ try {
1080
+ const mcpRecovery =
1081
+ canonicalResume?.recovery ||
1082
+ loadMcpLedgerRecovery(resumeId, {
1083
+ readVerifiedEvents: store.readVerifiedEvents,
1084
+ });
1085
+ resumeMcpRecovery = mcpRecovery;
1086
+ resumeMcpCallContext = formatMcpLedgerRecoveryNotice(mcpRecovery);
1087
+ if (resumeMcpCallContext) {
1088
+ const risky = mcpRecovery.unsettled.filter(
1089
+ (record) => record.effectContract?.effect !== "read",
1090
+ ).length;
1091
+ writeErr(
1092
+ `⚠ ${mcpRecovery.unsettled.length} interrupted MCP call(s) and ${mcpRecovery.incidents.length} ledger incident(s) require inspection before replay (resume ${resumeId}).\n`,
1093
+ );
1094
+ if (risky > 0 || mcpRecovery.incidents.length > 0) {
1095
+ _bgPhase.reportUncertainSideEffects(
1096
+ risky + mcpRecovery.incidents.length,
1097
+ );
1098
+ }
1099
+ }
1100
+ } catch (error) {
1101
+ resumeMcpRecoveryError = error;
1102
+ resumeMcpCallContext =
1103
+ "MCP recovery notice — the durable MCP call ledger could not be read. " +
1104
+ "Do not execute or retry MCP tools until the session transcript has " +
1105
+ `been inspected (${error?.code || "CC_MCP_LEDGER_EVENT_READ_FAILED"}).`;
1106
+ writeErr(
1107
+ `⚠ MCP ledger recovery failed closed for resume ${resumeId}; MCP calls require inspection.\n`,
1108
+ );
1109
+ _bgPhase.reportUncertainSideEffects(1);
1110
+ }
981
1111
  // On resume, recover any async-hook REWAKE (a background check that opted
982
1112
  // in and FAILED) that the previous run parked but died before draining —
983
1113
  // surface it to the model instead of silently swallowing the failure. The
@@ -1232,6 +1362,9 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1232
1362
  ...(resumeSideEffectContext
1233
1363
  ? [{ role: "system", content: resumeSideEffectContext }]
1234
1364
  : []),
1365
+ ...(resumeMcpCallContext
1366
+ ? [{ role: "system", content: resumeMcpCallContext }]
1367
+ : []),
1235
1368
  ...(resumeAsyncHookContext
1236
1369
  ? [{ role: "system", content: resumeAsyncHookContext }]
1237
1370
  : []),
@@ -1328,18 +1461,33 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1328
1461
  }
1329
1462
  }
1330
1463
 
1464
+ const mcpRecoveryRuntime = createMcpHostRecoveryRuntime({
1465
+ bundle: mcp,
1466
+ sessionId,
1467
+ sink: persist
1468
+ ? createSessionMcpLedgerSink(sessionId, {
1469
+ appendEvent: store.appendAuthorityEvent,
1470
+ })
1471
+ : null,
1472
+ recovery: resumeMcpRecovery,
1473
+ recoveryError: resumeMcpRecoveryError,
1474
+ });
1475
+ const hostMcp = mcp
1476
+ ? { ...mcp, mcpClient: mcpRecoveryRuntime.client || mcp.mcpClient }
1477
+ : null;
1478
+
1331
1479
  // Seed MCP roots for --add-dir (Claude-Code roots/list_changed parity): a
1332
1480
  // headless session started with extra workspace roots must advertise the FULL
1333
1481
  // root list to connected MCP servers, exactly like the REPL /add-dir path —
1334
1482
  // otherwise a server's roots/list only ever sees the cwd. Only meaningful when
1335
1483
  // extra roots exist (setRoots fires only when the list actually changes); no
1336
1484
  // --add-dir → workspaceRootDirs = [cwd] and this is a no-op. Best-effort.
1337
- if (mcp?.mcpClient && additionalDirectories.length > 0) {
1485
+ if (hostMcp?.mcpClient && additionalDirectories.length > 0) {
1338
1486
  try {
1339
1487
  const { notifyMcpRootsChanged, workspaceRootDirs } =
1340
1488
  await import("../repl/add-dir.js");
1341
1489
  notifyMcpRootsChanged(
1342
- [mcp.mcpClient],
1490
+ [hostMcp.mcpClient],
1343
1491
  workspaceRootDirs(options.cwd || process.cwd(), additionalDirectories),
1344
1492
  );
1345
1493
  } catch {
@@ -1357,7 +1505,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1357
1505
  await import("../lib/ide-context.js");
1358
1506
  const last = messages[messages.length - 1];
1359
1507
  const ideCtx = await (deps.buildIdePromptContext || buildIdePromptContext)(
1360
- mcp,
1508
+ hostMcp,
1361
1509
  );
1362
1510
  if (ideCtx) {
1363
1511
  last.content = appendTextToContent(last.content, ideCtx);
@@ -1366,7 +1514,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1366
1514
  // (Claude-Code parity). Scan the ORIGINAL prompt so injected file-ref
1367
1515
  // blocks can't spoof a mention; append the expansion to the in-flight
1368
1516
  // message only (ephemeral, like the ambient block above).
1369
- const mentioned = await expandIdeMentions(prompt, mcp);
1517
+ const mentioned = await expandIdeMentions(prompt, hostMcp);
1370
1518
  for (const w of mentioned.warnings) writeErr(` @ide: ${w}\n`);
1371
1519
  if (mentioned.block) {
1372
1520
  last.content = appendTextToContent(last.content, mentioned.block);
@@ -1401,7 +1549,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1401
1549
  approvalGate.setConfirmer(
1402
1550
  _bgPhase.wrapConfirmer(
1403
1551
  makePermissionPromptConfirmer({
1404
- mcpClient: mcp.mcpClient,
1552
+ mcpClient: hostMcp.mcpClient,
1405
1553
  server: ppt.server,
1406
1554
  tool: ppt.tool,
1407
1555
  writeErr,
@@ -1572,6 +1720,9 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1572
1720
  additionalDirectories,
1573
1721
  sandbox: options.sandbox || null,
1574
1722
  sessionId,
1723
+ // Content-free continuity metadata from the same verified sample used for
1724
+ // replay history and MCP recovery authority.
1725
+ sessionHostSnapshot: canonicalResume?.snapshot || null,
1575
1726
  // Auto-pin (default ON since 2026-07-07): pin the original task through
1576
1727
  // compaction. Precedence: --auto-pin flag > CC_AUTO_PIN ("1"/"0") >
1577
1728
  // config context.autoPin > default on. Falsy → agent-core passes no pin
@@ -1579,6 +1730,9 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1579
1730
  autoPin: _autoPinResolved,
1580
1731
  autoCheckpoint: options.autoCheckpoint || false,
1581
1732
  checkpointSession: options.checkpointSession || sessionId,
1733
+ managedCheckpoint: options.managedCheckpoint === true,
1734
+ managedCheckpointStateDir: options.managedCheckpointStateDir || null,
1735
+ managedCheckpointExclusions: options.managedCheckpointExclusions || [],
1582
1736
  hookDb: db,
1583
1737
  approvalGate,
1584
1738
  permissionRules,
@@ -1634,9 +1788,16 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1634
1788
  : {}),
1635
1789
  // --mcp-config wiring: tool defs for the LLM + dispatch map + live client.
1636
1790
  mcpClient: mcp?.mcpClient || null,
1791
+ mcpHostClient: mcpRecoveryRuntime.client || mcp?.mcpClient || null,
1637
1792
  extraToolDefinitions: mcp?.extraToolDefinitions || undefined,
1638
1793
  externalToolExecutors: mcp?.externalToolExecutors || undefined,
1639
1794
  externalToolDescriptors: mcp?.externalToolDescriptors || undefined,
1795
+ // Persist every MCP started/settled record into this exact canonical
1796
+ // session. Unknown/write/destructive prewrite failure then blocks before
1797
+ // the external call; a settlement failure leaves a recoverable started row.
1798
+ // Keep the guarded in-memory ledger when persistence is disabled so an
1799
+ // outcome-unknown call still latches UNSAFE for the rest of this process.
1800
+ mcpCallLedger: mcpRecoveryRuntime.ledger,
1640
1801
  // chatFn passthrough lets tests drive the loop deterministically.
1641
1802
  chatFn: deps.chatFn || options.chatFn || undefined,
1642
1803
  signal: options.signal || undefined,
@@ -1725,6 +1886,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1725
1886
  // so a non-interactive run surfaces what got blocked the way the REPL's
1726
1887
  // `/permissions denials` does (Claude-Code 2.1.193 denial reasons).
1727
1888
  const denials = [];
1889
+ const compactionDegradations = [];
1728
1890
  const usage = {
1729
1891
  input_tokens: 0,
1730
1892
  output_tokens: 0,
@@ -1910,15 +2072,10 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
1910
2072
  let restoredSnap = null;
1911
2073
  if (resumeId) {
1912
2074
  try {
1913
- const events = store.readEvents(resumeId) || [];
1914
- for (let i = events.length - 1; i >= 0; i--) {
1915
- const ev = events[i];
1916
- if (ev && ev.type === "goal_snapshot") {
1917
- const snap = ev.data;
1918
- if (snap && snap.state && snap.state.done !== true)
1919
- restoredSnap = snap;
1920
- break; // only the latest goal_snapshot matters
1921
- }
2075
+ const event = store.findLatestEvent(resumeId, "goal_snapshot");
2076
+ const snap = event?.data;
2077
+ if (snap && snap.state && snap.state.done !== true) {
2078
+ restoredSnap = snap;
1922
2079
  }
1923
2080
  } catch {
1924
2081
  restoredSnap = null; // unreadable transcript → start fresh
@@ -2006,6 +2163,14 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2006
2163
  for await (const event of runLoop(messages, loopOptions)) {
2007
2164
  if (turnBindingFeed) turnBindingFeed.handleEvent(event);
2008
2165
  switch (event.type) {
2166
+ case "managed-checkpoint":
2167
+ case "managed-checkpoint-settled":
2168
+ case "managed-checkpoint-error": {
2169
+ const line = formatManagedCheckpointEvent(event);
2170
+ if (isText && line) writeErr(`${line}\n`);
2171
+ if (isStream) emitStream(event);
2172
+ break;
2173
+ }
2009
2174
  case "checkpoint": {
2010
2175
  if (isText)
2011
2176
  writeErr(` ⎌ checkpoint ${event.id} (before ${event.tool})\n`);
@@ -2138,6 +2303,23 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2138
2303
  }
2139
2304
  break;
2140
2305
  }
2306
+ case "compaction-degraded": {
2307
+ const reason = String(event.reason || "semantic-summary-degraded")
2308
+ .replace(/\s+/g, " ")
2309
+ .slice(0, 500);
2310
+ const degradation = {
2311
+ reason,
2312
+ summary_mode: event.summaryMode || "none",
2313
+ };
2314
+ compactionDegradations.push(degradation);
2315
+ if (isText) {
2316
+ writeErr(
2317
+ ` Semantic compaction degraded to ${degradation.summary_mode}: ${reason}\n`,
2318
+ );
2319
+ }
2320
+ emitStream({ ...event, reason });
2321
+ break;
2322
+ }
2141
2323
  case "token-usage": {
2142
2324
  if (event.attribution) {
2143
2325
  // Child-loop (sub-agent / isolated-skill) spend: excluded from
@@ -2164,6 +2346,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2164
2346
  provider: event.provider,
2165
2347
  model: event.model,
2166
2348
  usage: event.usage,
2349
+ ...(event.source ? { source: event.source } : {}),
2167
2350
  });
2168
2351
  if (costBudget) {
2169
2352
  costBudget.add({
@@ -2419,6 +2602,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2419
2602
  numTurns: budget.consumed,
2420
2603
  durationMs: (deps.now ? deps.now() : Date.now()) - startedAt,
2421
2604
  denials,
2605
+ compactionDegradations,
2422
2606
  }),
2423
2607
  ) + "\n",
2424
2608
  );
@@ -2700,6 +2884,9 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2700
2884
  num_turns: budget.consumed,
2701
2885
  duration_ms: durationMs,
2702
2886
  usage,
2887
+ ...(compactionDegradations.length
2888
+ ? { compaction_degradations: compactionDegradations }
2889
+ : {}),
2703
2890
  });
2704
2891
  } else if (isJson) {
2705
2892
  writeOut(
@@ -2714,6 +2901,7 @@ async function runAgentHeadlessInWorkspace(options = {}, deps = {}) {
2714
2901
  numTurns: budget.consumed,
2715
2902
  durationMs,
2716
2903
  denials,
2904
+ compactionDegradations,
2717
2905
  }),
2718
2906
  ) + "\n",
2719
2907
  );
@@ -2773,6 +2961,7 @@ function buildResultEnvelope({
2773
2961
  numTurns,
2774
2962
  durationMs,
2775
2963
  denials,
2964
+ compactionDegradations,
2776
2965
  }) {
2777
2966
  const env = {
2778
2967
  type: "result",
@@ -2788,5 +2977,8 @@ function buildResultEnvelope({
2788
2977
  // Only present when something was blocked — keeps the no-denial envelope
2789
2978
  // byte-identical to before (Claude-Code 2.1.193 denial reasons, json mode).
2790
2979
  if (Array.isArray(denials) && denials.length) env.denials = denials;
2980
+ if (Array.isArray(compactionDegradations) && compactionDegradations.length) {
2981
+ env.compaction_degradations = compactionDegradations;
2982
+ }
2791
2983
  return env;
2792
2984
  }