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,902 @@
1
+ /**
2
+ * Conservative recovery for a timeline restore whose session transaction is
3
+ * already durably completed.
4
+ *
5
+ * This controller never writes session state and never retries workspace or
6
+ * conversation mutation. It may only reconcile a verified session completion
7
+ * with an exact workspace target and then close the matching saga. The lock
8
+ * order is workspace lifetime authority, verified session read, then short
9
+ * saga CAS operations.
10
+ */
11
+
12
+ import path from "node:path";
13
+ import {
14
+ CheckpointRestoreSagaStore,
15
+ computeCheckpointRestoreWorkspaceLockOwnerDigest,
16
+ } from "./checkpoint-restore-saga.js";
17
+ import { computeCheckpointRestoreDigest } from "./checkpoint-restore-orchestrator.js";
18
+ import {
19
+ CHECKPOINT_RESTORE_SESSION_RECONCILIATION,
20
+ CHECKPOINT_RESTORE_SESSION_RECOVERY_SCHEMA,
21
+ CHECKPOINT_RESTORE_SESSION_RECOVERY_VERSION,
22
+ } from "./checkpoint-restore-session-recovery.js";
23
+ import {
24
+ inspectWorkspaceLockOwnerSync,
25
+ withWorkspaceRecoveryLockSync,
26
+ } from "./process-execution-broker/workspace-transaction.js";
27
+
28
+ const DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/;
29
+ const RAW_EVENT_HASH_PATTERN = /^[a-f0-9]{64}$/;
30
+ const OPERATION_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/;
31
+ const RECOVERY_PHASES = new Set(["recovery_required", "recovery_started"]);
32
+ const ALLOWED_BASE_PHASES = new Set(["workspace_applied", "session_committed"]);
33
+ const ACTIONS = new Set(["restore-code", "restore-both"]);
34
+ const CHECKPOINT_RESTORE_PURPOSE = "checkpoint-restore";
35
+
36
+ export const CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION =
37
+ "resume-already-completed";
38
+ export const CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_SCHEMA =
39
+ "chainlesschain.checkpoint-restore-workspace-target-verification";
40
+ export const CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_VERSION = 1;
41
+ export const CHECKPOINT_RESTORE_ALREADY_COMPLETED_RESULT_SCHEMA =
42
+ "chainlesschain.checkpoint-restore-already-completed-result";
43
+ export const CHECKPOINT_RESTORE_ALREADY_COMPLETED_RESULT_VERSION = 1;
44
+
45
+ export const CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES = Object.freeze({
46
+ INVALID_ARGUMENT: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_INVALID_ARGUMENT",
47
+ SAGA_CONFLICT: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_SAGA_CONFLICT",
48
+ ACTION_NOT_ALLOWED: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION_NOT_ALLOWED",
49
+ OWNER_CONFLICT: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_OWNER_CONFLICT",
50
+ SESSION_CONFLICT: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_SESSION_CONFLICT",
51
+ WORKSPACE_CONFLICT: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_WORKSPACE_CONFLICT",
52
+ ASYNC_UNSUPPORTED: "CHECKPOINT_RESTORE_ALREADY_COMPLETED_ASYNC_UNSUPPORTED",
53
+ });
54
+
55
+ export class CheckpointRestoreAlreadyCompletedError extends Error {
56
+ constructor(code, message, details = {}, cause = null) {
57
+ super(message, cause ? { cause } : undefined);
58
+ this.name = "CheckpointRestoreAlreadyCompletedError";
59
+ this.code = code;
60
+ Object.assign(this, details);
61
+ }
62
+ }
63
+
64
+ function recoveryError(code, message, details = {}, cause = null) {
65
+ return new CheckpointRestoreAlreadyCompletedError(
66
+ code,
67
+ message,
68
+ details,
69
+ cause,
70
+ );
71
+ }
72
+
73
+ function isPlainObject(value) {
74
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
75
+ return false;
76
+ }
77
+ const prototype = Object.getPrototypeOf(value);
78
+ return prototype === Object.prototype || prototype === null;
79
+ }
80
+
81
+ function canonicalJson(value) {
82
+ if (value === undefined || value === null) return "null";
83
+ if (typeof value === "string" || typeof value === "boolean") {
84
+ return JSON.stringify(value);
85
+ }
86
+ if (typeof value === "number" && Number.isFinite(value)) {
87
+ return JSON.stringify(value);
88
+ }
89
+ if (Array.isArray(value)) {
90
+ return `[${value.map((entry) => canonicalJson(entry)).join(",")}]`;
91
+ }
92
+ if (isPlainObject(value)) {
93
+ return `{${Object.keys(value)
94
+ .sort()
95
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
96
+ .join(",")}}`;
97
+ }
98
+ throw recoveryError(
99
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.INVALID_ARGUMENT,
100
+ "Checkpoint restore recovery evidence is not canonical JSON",
101
+ );
102
+ }
103
+
104
+ function boundedText(value, fallback, maximum = 2_048) {
105
+ let sanitized = "";
106
+ for (const character of String(value || fallback)) {
107
+ const code = character.charCodeAt(0);
108
+ sanitized += code < 32 || code === 127 ? " " : character;
109
+ }
110
+ const normalized = sanitized.trim();
111
+ return (normalized || fallback).slice(0, maximum);
112
+ }
113
+
114
+ function asError(value) {
115
+ return value && typeof value === "object"
116
+ ? value
117
+ : new Error(String(value || "checkpoint restore recovery failed"));
118
+ }
119
+
120
+ function isThenable(value) {
121
+ if (
122
+ value === null ||
123
+ (typeof value !== "object" && typeof value !== "function")
124
+ ) {
125
+ return false;
126
+ }
127
+ try {
128
+ return typeof value.then === "function";
129
+ } catch (cause) {
130
+ throw recoveryError(
131
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.ASYNC_UNSUPPORTED,
132
+ "Checkpoint restore recovery result exposed an unsafe thenable",
133
+ {},
134
+ cause,
135
+ );
136
+ }
137
+ }
138
+
139
+ function requireSynchronous(value, boundary) {
140
+ if (isThenable(value)) {
141
+ throw recoveryError(
142
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.ASYNC_UNSUPPORTED,
143
+ `${boundary} must be synchronous while workspace authority is held`,
144
+ );
145
+ }
146
+ return value;
147
+ }
148
+
149
+ function validateExpectedAuthority({
150
+ operationId,
151
+ expectedSeq,
152
+ expectedHash,
153
+ expectedOwnerDigest,
154
+ }) {
155
+ if (
156
+ typeof operationId !== "string" ||
157
+ !OPERATION_ID_PATTERN.test(operationId) ||
158
+ !Number.isSafeInteger(expectedSeq) ||
159
+ expectedSeq < 1 ||
160
+ !DIGEST_PATTERN.test(String(expectedHash || "")) ||
161
+ !DIGEST_PATTERN.test(String(expectedOwnerDigest || ""))
162
+ ) {
163
+ throw recoveryError(
164
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.INVALID_ARGUMENT,
165
+ "Already-completed recovery requires an operation id, exact saga head, and retained owner digest",
166
+ );
167
+ }
168
+ }
169
+
170
+ function exactSaga(saga, operationId, expectedSeq, expectedHash) {
171
+ if (
172
+ !saga ||
173
+ saga.operationId !== operationId ||
174
+ saga.seq !== expectedSeq ||
175
+ saga.headHash !== expectedHash
176
+ ) {
177
+ throw recoveryError(
178
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.SAGA_CONFLICT,
179
+ "Checkpoint restore saga changed after recovery preview",
180
+ {
181
+ operationId,
182
+ expectedSeq,
183
+ expectedHash,
184
+ actualSeq: saga?.seq ?? null,
185
+ actualHash: saga?.headHash ?? null,
186
+ },
187
+ );
188
+ }
189
+ return saga;
190
+ }
191
+
192
+ function basePhase(saga) {
193
+ for (let index = saga.events.length - 1; index >= 0; index -= 1) {
194
+ const phase = saga.events[index]?.phase;
195
+ if (!RECOVERY_PHASES.has(phase)) return phase || null;
196
+ }
197
+ return null;
198
+ }
199
+
200
+ function singleEvent(saga, phase) {
201
+ const matches = saga.events.filter((event) => event?.phase === phase);
202
+ return matches.length === 1 ? matches[0] : null;
203
+ }
204
+
205
+ function pathKey(value, platform) {
206
+ if (typeof value !== "string" || value.length === 0) return null;
207
+ const resolved = path.resolve(value);
208
+ return platform === "win32" ? resolved.toLowerCase() : resolved;
209
+ }
210
+
211
+ function samePath(left, right, platform) {
212
+ const leftKey = pathKey(left, platform);
213
+ return leftKey !== null && leftKey === pathKey(right, platform);
214
+ }
215
+
216
+ function stateDigest(kind, state, authority) {
217
+ return computeCheckpointRestoreDigest(`cc-checkpoint-restore-${state}-v1`, {
218
+ engine: kind,
219
+ scopeIdentity: authority.workspaceScopeIdentity,
220
+ stateIdentity:
221
+ state === "prestate"
222
+ ? authority.workspacePrestateIdentity
223
+ : authority.workspaceTargetPoststateIdentity,
224
+ });
225
+ }
226
+
227
+ function timelineSagaAuthority(saga, workspaceRoot, platform) {
228
+ const sourcePhase = basePhase(saga);
229
+ const created = singleEvent(saga, "created");
230
+ const prepared = singleEvent(saga, "prepared");
231
+ const intent = singleEvent(saga, "intent_committed");
232
+ const workspaceApplied = singleEvent(saga, "workspace_applied");
233
+ const sessionCommitted = singleEvent(saga, "session_committed");
234
+ const createdEvidence = created?.evidence;
235
+ const intentEvidence = intent?.evidence;
236
+ const sessionId = intentEvidence?.sessionId || createdEvidence?.sessionId;
237
+ const timelineEntryId =
238
+ intentEvidence?.timelineEntryId || createdEvidence?.timelineEntryId || null;
239
+
240
+ if (
241
+ saga.terminal ||
242
+ !ALLOWED_BASE_PHASES.has(sourcePhase) ||
243
+ !created ||
244
+ !prepared ||
245
+ !intent ||
246
+ !workspaceApplied ||
247
+ createdEvidence?.restoreSurface !== "timeline" ||
248
+ intentEvidence?.intentAuthority !== "session" ||
249
+ !["git", "copy"].includes(createdEvidence?.restoreKind) ||
250
+ typeof sessionId !== "string" ||
251
+ sessionId.length === 0 ||
252
+ (createdEvidence.sessionId && createdEvidence.sessionId !== sessionId) ||
253
+ (intentEvidence.sessionId && intentEvidence.sessionId !== sessionId) ||
254
+ (createdEvidence.timelineEntryId &&
255
+ createdEvidence.timelineEntryId !== timelineEntryId) ||
256
+ (intentEvidence.timelineEntryId &&
257
+ intentEvidence.timelineEntryId !== timelineEntryId) ||
258
+ !samePath(createdEvidence.workspaceRoot, workspaceRoot, platform) ||
259
+ typeof createdEvidence.checkpointId !== "string" ||
260
+ typeof createdEvidence.checkpointIdentity !== "string" ||
261
+ (createdEvidence.restoreKind === "git" &&
262
+ typeof createdEvidence.checkpointNamespace !== "string") ||
263
+ !DIGEST_PATTERN.test(String(createdEvidence.workspaceBinding || "")) ||
264
+ !DIGEST_PATTERN.test(String(createdEvidence.confirmationDigest || "")) ||
265
+ !DIGEST_PATTERN.test(String(prepared.evidence?.prestateDigest || "")) ||
266
+ !DIGEST_PATTERN.test(
267
+ String(workspaceApplied.evidence?.poststateDigest || ""),
268
+ ) ||
269
+ !DIGEST_PATTERN.test(String(intentEvidence.intentCommitDigest || "")) ||
270
+ (sourcePhase === "session_committed" &&
271
+ (!sessionCommitted ||
272
+ !DIGEST_PATTERN.test(
273
+ String(sessionCommitted.evidence?.sessionCommitDigest || ""),
274
+ ))) ||
275
+ (sourcePhase === "workspace_applied" && sessionCommitted)
276
+ ) {
277
+ throw recoveryError(
278
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.ACTION_NOT_ALLOWED,
279
+ "Only an exact timeline workspace_applied or session_committed saga can reconcile an already-completed session",
280
+ {
281
+ operationId: saga.operationId,
282
+ phase: saga.phase,
283
+ basePhase: sourcePhase,
284
+ },
285
+ );
286
+ }
287
+
288
+ return Object.freeze({
289
+ basePhase: sourcePhase,
290
+ restoreKind: createdEvidence.restoreKind,
291
+ sessionId,
292
+ timelineEntryId,
293
+ checkpointId: createdEvidence.checkpointId,
294
+ checkpointIdentity: createdEvidence.checkpointIdentity,
295
+ checkpointNamespace: createdEvidence.checkpointNamespace || null,
296
+ workspaceBinding: createdEvidence.workspaceBinding,
297
+ confirmationDigest: createdEvidence.confirmationDigest,
298
+ prestateDigest: prepared.evidence.prestateDigest,
299
+ poststateDigest: workspaceApplied.evidence.poststateDigest,
300
+ intentCommitDigest: intentEvidence.intentCommitDigest,
301
+ sessionCommitDigest:
302
+ sessionCommitted?.evidence?.sessionCommitDigest || null,
303
+ });
304
+ }
305
+
306
+ function sessionConflict(message, details = {}) {
307
+ throw recoveryError(
308
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.SESSION_CONFLICT,
309
+ message,
310
+ details,
311
+ );
312
+ }
313
+
314
+ function validateSessionProjection(
315
+ projection,
316
+ operationId,
317
+ authority,
318
+ workspaceRoot,
319
+ platform,
320
+ ) {
321
+ const intent = projection?.intent;
322
+ const completed = projection?.audit?.completed;
323
+ const intentAuthority = intent?.authority;
324
+ const completedAuthority = completed?.authority;
325
+ if (
326
+ !isPlainObject(projection) ||
327
+ projection.schema !== CHECKPOINT_RESTORE_SESSION_RECOVERY_SCHEMA ||
328
+ projection.version !== CHECKPOINT_RESTORE_SESSION_RECOVERY_VERSION ||
329
+ projection.operationId !== operationId ||
330
+ projection.sessionId !== authority.sessionId ||
331
+ projection.restoreSurface !== "timeline" ||
332
+ projection.classification !==
333
+ CHECKPOINT_RESTORE_SESSION_RECONCILIATION.ALREADY_COMPLETED ||
334
+ projection.failClosed !== false ||
335
+ projection.safeToMutate !== false ||
336
+ !Array.isArray(projection.issues) ||
337
+ projection.issues.length !== 0 ||
338
+ !isPlainObject(projection.transcript) ||
339
+ !RAW_EVENT_HASH_PATTERN.test(
340
+ String(projection.transcript.headHash || ""),
341
+ ) ||
342
+ !Number.isSafeInteger(projection.transcript.eventCount) ||
343
+ projection.transcript.eventCount < 1 ||
344
+ !isPlainObject(intent) ||
345
+ !RAW_EVENT_HASH_PATTERN.test(String(intent.eventHash || "")) ||
346
+ !DIGEST_PATTERN.test(String(intent.intentCommitDigest || "")) ||
347
+ !isPlainObject(intentAuthority) ||
348
+ !ACTIONS.has(intentAuthority.action) ||
349
+ !isPlainObject(completed) ||
350
+ completed.status !== "completed" ||
351
+ !RAW_EVENT_HASH_PATTERN.test(String(completed.eventHash || "")) ||
352
+ !DIGEST_PATTERN.test(String(completed.sessionCommitDigest || "")) ||
353
+ !isPlainObject(completedAuthority) ||
354
+ projection.audit.failed !== null ||
355
+ projection.transcript.operationTailHash !== completed.eventHash ||
356
+ canonicalJson(intentAuthority) !== canonicalJson(completedAuthority)
357
+ ) {
358
+ return sessionConflict(
359
+ "Verified session recovery did not return one exact already-completed settlement",
360
+ { operationId, classification: projection?.classification || null },
361
+ );
362
+ }
363
+
364
+ const computedIntentDigest = computeCheckpointRestoreDigest(
365
+ "cc-checkpoint-restore-intent-commit-v1",
366
+ intent.eventHash,
367
+ );
368
+ const computedSessionDigest = computeCheckpointRestoreDigest(
369
+ "cc-checkpoint-restore-session-commit-v1",
370
+ completed.eventHash,
371
+ );
372
+ if (
373
+ intent.intentCommitDigest !== computedIntentDigest ||
374
+ intent.intentCommitDigest !== authority.intentCommitDigest ||
375
+ completed.sessionCommitDigest !== computedSessionDigest ||
376
+ (authority.sessionCommitDigest &&
377
+ completed.sessionCommitDigest !== authority.sessionCommitDigest) ||
378
+ (authority.timelineEntryId &&
379
+ intentAuthority.turnId !== authority.timelineEntryId) ||
380
+ intentAuthority.checkpointId !== authority.checkpointId ||
381
+ intentAuthority.checkpointIdentity !== authority.checkpointIdentity ||
382
+ intentAuthority.workspaceWritePlanIdentity !== authority.workspaceBinding ||
383
+ intentAuthority.confirmationDigest !== authority.confirmationDigest ||
384
+ !samePath(intentAuthority.workspaceDir, workspaceRoot, platform) ||
385
+ stateDigest(authority.restoreKind, "prestate", intentAuthority) !==
386
+ authority.prestateDigest ||
387
+ stateDigest(authority.restoreKind, "poststate", intentAuthority) !==
388
+ authority.poststateDigest
389
+ ) {
390
+ return sessionConflict(
391
+ "Verified session settlement does not match the durable saga authority",
392
+ { operationId },
393
+ );
394
+ }
395
+
396
+ return Object.freeze({
397
+ schema: CHECKPOINT_RESTORE_SESSION_RECOVERY_SCHEMA,
398
+ version: CHECKPOINT_RESTORE_SESSION_RECOVERY_VERSION,
399
+ sessionId: authority.sessionId,
400
+ transcriptHeadHash: projection.transcript.headHash,
401
+ transcriptEventCount: projection.transcript.eventCount,
402
+ action: intentAuthority.action,
403
+ intentEventHash: intent.eventHash,
404
+ intentCommitDigest: intent.intentCommitDigest,
405
+ completedAuditEventHash: completed.eventHash,
406
+ sessionCommitDigest: completed.sessionCommitDigest,
407
+ });
408
+ }
409
+
410
+ function validateWorkspaceProjection(
411
+ projection,
412
+ operationId,
413
+ authority,
414
+ sessionAuthority,
415
+ ) {
416
+ if (
417
+ !isPlainObject(projection) ||
418
+ projection.schema !==
419
+ CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_SCHEMA ||
420
+ projection.version !==
421
+ CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_VERSION ||
422
+ projection.verified !== true ||
423
+ projection.exact !== true ||
424
+ projection.operationId !== operationId ||
425
+ projection.restoreKind !== authority.restoreKind ||
426
+ projection.checkpointNamespace !== authority.checkpointNamespace ||
427
+ projection.checkpointId !== authority.checkpointId ||
428
+ projection.checkpointIdentity !== authority.checkpointIdentity ||
429
+ projection.workspaceScopeIdentity !==
430
+ sessionAuthority.workspaceScopeIdentity ||
431
+ projection.workspaceTargetPoststateIdentity !==
432
+ sessionAuthority.workspaceTargetPoststateIdentity ||
433
+ projection.poststateDigest !== authority.poststateDigest
434
+ ) {
435
+ throw recoveryError(
436
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.WORKSPACE_CONFLICT,
437
+ "Workspace target verification did not prove the exact durable target",
438
+ { operationId },
439
+ );
440
+ }
441
+ return Object.freeze({
442
+ schema: CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_SCHEMA,
443
+ version: CHECKPOINT_RESTORE_WORKSPACE_TARGET_VERIFICATION_VERSION,
444
+ verified: true,
445
+ exact: true,
446
+ operationId,
447
+ restoreKind: authority.restoreKind,
448
+ checkpointNamespace: authority.checkpointNamespace,
449
+ checkpointId: authority.checkpointId,
450
+ checkpointIdentity: authority.checkpointIdentity,
451
+ workspaceScopeIdentity: projection.workspaceScopeIdentity,
452
+ workspaceTargetPoststateIdentity:
453
+ projection.workspaceTargetPoststateIdentity,
454
+ poststateDigest: projection.poststateDigest,
455
+ });
456
+ }
457
+
458
+ function resultProjection(operationId, workspace, session) {
459
+ return Object.freeze({
460
+ schema: CHECKPOINT_RESTORE_ALREADY_COMPLETED_RESULT_SCHEMA,
461
+ version: CHECKPOINT_RESTORE_ALREADY_COMPLETED_RESULT_VERSION,
462
+ operationId,
463
+ recoveryAction: CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION,
464
+ workspace,
465
+ session,
466
+ });
467
+ }
468
+
469
+ function terminalSummary(saga) {
470
+ return Object.freeze({
471
+ operationId: saga.operationId,
472
+ phase: saga.phase,
473
+ seq: saga.seq,
474
+ headHash: saga.headHash,
475
+ });
476
+ }
477
+
478
+ function archiveWarning(error) {
479
+ return Object.freeze({
480
+ code: boundedText(
481
+ error?.code,
482
+ "CHECKPOINT_RESTORE_SAGA_ARCHIVE_PENDING",
483
+ 128,
484
+ ),
485
+ message: boundedText(
486
+ error?.message,
487
+ "Checkpoint restore saga archive is pending",
488
+ 512,
489
+ ),
490
+ commitState:
491
+ typeof error?.commitState === "string"
492
+ ? boundedText(error.commitState, "unknown", 128)
493
+ : null,
494
+ });
495
+ }
496
+
497
+ function propagateRecoveryDiagnostics(error) {
498
+ if (!error || typeof error !== "object") return error;
499
+ const nested = error.cause;
500
+ if (!nested || typeof nested !== "object") return error;
501
+ for (const field of [
502
+ "checkpointRestoreRecoveryCause",
503
+ "checkpointRestoreOperationId",
504
+ "checkpointRestoreSagaPhase",
505
+ "checkpointRestoreSagaSeq",
506
+ "checkpointRestoreSagaHeadHash",
507
+ "checkpointRestoreRecoveryRequired",
508
+ ]) {
509
+ if (error[field] === undefined && nested[field] !== undefined) {
510
+ error[field] = nested[field];
511
+ }
512
+ }
513
+ return error;
514
+ }
515
+
516
+ export class CheckpointRestoreAlreadyCompletedController {
517
+ constructor(options = {}) {
518
+ if (!isPlainObject(options)) {
519
+ throw recoveryError(
520
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.INVALID_ARGUMENT,
521
+ "Already-completed recovery controller options must be an object",
522
+ );
523
+ }
524
+ if (
525
+ typeof options.workspaceRoot !== "string" ||
526
+ options.workspaceRoot.length === 0
527
+ ) {
528
+ throw recoveryError(
529
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.INVALID_ARGUMENT,
530
+ "Already-completed recovery requires a workspaceRoot",
531
+ );
532
+ }
533
+ const sessionReader =
534
+ options.readSessionRecovery ||
535
+ (typeof options.sessionRecoveryReader?.read === "function"
536
+ ? options.sessionRecoveryReader.read.bind(options.sessionRecoveryReader)
537
+ : null);
538
+ if (
539
+ typeof sessionReader !== "function" ||
540
+ typeof options.verifyWorkspaceTarget !== "function"
541
+ ) {
542
+ throw recoveryError(
543
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.INVALID_ARGUMENT,
544
+ "Already-completed recovery requires session and workspace verification readers",
545
+ );
546
+ }
547
+
548
+ this.workspaceRoot = options.workspaceRoot;
549
+ this.store =
550
+ options.store ||
551
+ new CheckpointRestoreSagaStore({ workspaceRoot: this.workspaceRoot });
552
+ this._readSessionRecovery = sessionReader;
553
+ this._verifyWorkspaceTarget = options.verifyWorkspaceTarget;
554
+ this._inspectWorkspaceLockOwnerSync =
555
+ options.inspectWorkspaceLockOwnerSync || inspectWorkspaceLockOwnerSync;
556
+ this._withWorkspaceRecoveryLockSync =
557
+ options.withWorkspaceRecoveryLockSync || withWorkspaceRecoveryLockSync;
558
+ this._workspaceLockOwnerDigest =
559
+ options.computeWorkspaceLockOwnerDigest ||
560
+ computeCheckpointRestoreWorkspaceLockOwnerDigest;
561
+ this._workspaceLockOptions = Object.freeze({
562
+ ...(options.workspaceLockOptions || {}),
563
+ });
564
+ this._platform = options.platform || process.platform;
565
+ }
566
+
567
+ _lockOptions(operationId) {
568
+ return {
569
+ ...this._workspaceLockOptions,
570
+ workspaceRoot: this.workspaceRoot,
571
+ operationId,
572
+ purpose: CHECKPOINT_RESTORE_PURPOSE,
573
+ };
574
+ }
575
+
576
+ _loadExact(operationId, expectedSeq, expectedHash) {
577
+ return exactSaga(
578
+ requireSynchronous(
579
+ this.store.load(operationId),
580
+ "checkpoint restore saga load",
581
+ ),
582
+ operationId,
583
+ expectedSeq,
584
+ expectedHash,
585
+ );
586
+ }
587
+
588
+ _advanceExact(saga, phase, evidence) {
589
+ try {
590
+ return requireSynchronous(
591
+ this.store.advance(saga.operationId, {
592
+ expectedSeq: saga.seq,
593
+ expectedHash: saga.headHash,
594
+ phase,
595
+ evidence,
596
+ }),
597
+ "checkpoint restore saga advance",
598
+ );
599
+ } catch (caught) {
600
+ const error = asError(caught);
601
+ try {
602
+ const observed = requireSynchronous(
603
+ this.store.load(saga.operationId),
604
+ "checkpoint restore saga reconciliation load",
605
+ );
606
+ const latest = observed.events?.at(-1);
607
+ if (
608
+ observed.seq === saga.seq + 1 &&
609
+ observed.phase === phase &&
610
+ latest?.prevHash === saga.headHash &&
611
+ canonicalJson(latest.evidence) === canonicalJson(evidence)
612
+ ) {
613
+ return observed;
614
+ }
615
+ } catch (loadError) {
616
+ error.checkpointRestoreRecoveryLoadError = loadError;
617
+ }
618
+ throw error;
619
+ }
620
+ }
621
+
622
+ _inspectBoundOwner(operationId, expectedOwnerDigest) {
623
+ const owner = this._inspectWorkspaceLockOwnerSync(
624
+ this._lockOptions(operationId),
625
+ );
626
+ if (!owner) {
627
+ throw recoveryError(
628
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.OWNER_CONFLICT,
629
+ "Checkpoint restore has no retained workspace owner to take over",
630
+ { operationId, expectedOwnerDigest, actualOwnerDigest: null },
631
+ );
632
+ }
633
+ const actualOwnerDigest = this._workspaceLockOwnerDigest(owner);
634
+ if (actualOwnerDigest !== expectedOwnerDigest) {
635
+ throw recoveryError(
636
+ CHECKPOINT_RESTORE_ALREADY_COMPLETED_ERROR_CODES.OWNER_CONFLICT,
637
+ "Checkpoint restore workspace owner changed after recovery preview",
638
+ { operationId, expectedOwnerDigest, actualOwnerDigest },
639
+ );
640
+ }
641
+ return owner;
642
+ }
643
+
644
+ _archiveTerminal(saga) {
645
+ try {
646
+ const archived = requireSynchronous(
647
+ this.store.archiveTerminal(saga.operationId, {
648
+ expectedSeq: saga.seq,
649
+ expectedHash: saga.headHash,
650
+ }),
651
+ "checkpoint restore saga archive",
652
+ );
653
+ return Object.freeze({
654
+ archived: true,
655
+ alreadyArchived: archived.alreadyArchived === true,
656
+ warning: null,
657
+ });
658
+ } catch (error) {
659
+ return Object.freeze({
660
+ archived: false,
661
+ alreadyArchived: false,
662
+ warning: archiveWarning(error),
663
+ });
664
+ }
665
+ }
666
+
667
+ _retainFailure(operationError, lease, completedEvidence = null) {
668
+ const error = asError(operationError);
669
+ let observed = null;
670
+ try {
671
+ observed = requireSynchronous(
672
+ this.store.load(lease.recoveryOfOperationId),
673
+ "checkpoint restore failure reconciliation load",
674
+ );
675
+ const latest = observed.events?.at(-1);
676
+ if (
677
+ completedEvidence &&
678
+ observed.terminal &&
679
+ observed.phase === "completed" &&
680
+ canonicalJson(latest?.evidence) === canonicalJson(completedEvidence)
681
+ ) {
682
+ return Object.freeze({ saga: observed, reconciledFromError: true });
683
+ }
684
+ if (!observed.terminal) {
685
+ timelineSagaAuthority(observed, this.workspaceRoot, this._platform);
686
+ if (observed.phase !== "recovery_required") {
687
+ observed = this._advanceExact(observed, "recovery_required", {
688
+ reason: boundedText(
689
+ error.message,
690
+ "Already-completed restore reconciliation requires another attempt",
691
+ ),
692
+ errorCode: boundedText(
693
+ error.code,
694
+ "CHECKPOINT_RESTORE_ALREADY_COMPLETED_FAILED",
695
+ 128,
696
+ ),
697
+ });
698
+ }
699
+ }
700
+ } catch (journalError) {
701
+ error.checkpointRestoreRecoveryJournalError = journalError;
702
+ }
703
+
704
+ try {
705
+ lease.retainForRecovery(
706
+ boundedText(
707
+ `${error.code || "CHECKPOINT_RESTORE_ALREADY_COMPLETED_FAILED"}: ${error.message || "already-completed outcome is unknown"}`,
708
+ "Already-completed restore outcome is unknown",
709
+ 512,
710
+ ),
711
+ );
712
+ } catch (retentionError) {
713
+ if (retentionError && typeof retentionError === "object") {
714
+ retentionError.checkpointRestoreRecoveryCause = error;
715
+ retentionError.checkpointRestoreOperationId =
716
+ lease.recoveryOfOperationId;
717
+ retentionError.checkpointRestoreSagaPhase = observed?.phase || null;
718
+ retentionError.checkpointRestoreSagaSeq = observed?.seq || null;
719
+ retentionError.checkpointRestoreSagaHeadHash =
720
+ observed?.headHash || null;
721
+ retentionError.checkpointRestoreRecoveryRequired = true;
722
+ }
723
+ throw retentionError;
724
+ }
725
+ throw error;
726
+ }
727
+
728
+ resume(operationId, { expectedSeq, expectedHash, expectedOwnerDigest } = {}) {
729
+ validateExpectedAuthority({
730
+ operationId,
731
+ expectedSeq,
732
+ expectedHash,
733
+ expectedOwnerDigest,
734
+ });
735
+ const previewSaga = this._loadExact(operationId, expectedSeq, expectedHash);
736
+ const previewAuthority = timelineSagaAuthority(
737
+ previewSaga,
738
+ this.workspaceRoot,
739
+ this._platform,
740
+ );
741
+ const observedOwner = this._inspectBoundOwner(
742
+ operationId,
743
+ expectedOwnerDigest,
744
+ );
745
+
746
+ let settled;
747
+ try {
748
+ settled = this._withWorkspaceRecoveryLockSync(
749
+ {
750
+ ...this._lockOptions(operationId),
751
+ expectedOwner: observedOwner,
752
+ },
753
+ (lease) => {
754
+ let completedEvidence = null;
755
+ try {
756
+ lease.assertOwned();
757
+ const sessionOptions = {
758
+ operationId,
759
+ sessionId: previewAuthority.sessionId,
760
+ restoreSurface: "timeline",
761
+ expectedIntentCommitDigest: previewAuthority.intentCommitDigest,
762
+ expectedCheckpointId: previewAuthority.checkpointId,
763
+ expectedCheckpointIdentity: previewAuthority.checkpointIdentity,
764
+ expectedConfirmationDigest: previewAuthority.confirmationDigest,
765
+ ...(previewAuthority.timelineEntryId
766
+ ? {
767
+ expectedTimelineEntryId: previewAuthority.timelineEntryId,
768
+ }
769
+ : {}),
770
+ ...(previewAuthority.sessionCommitDigest
771
+ ? {
772
+ expectedSessionCommitDigest:
773
+ previewAuthority.sessionCommitDigest,
774
+ }
775
+ : {}),
776
+ };
777
+ const rawSessionProjection = requireSynchronous(
778
+ this._readSessionRecovery(Object.freeze(sessionOptions)),
779
+ "checkpoint restore verified session recovery read",
780
+ );
781
+ const session = validateSessionProjection(
782
+ rawSessionProjection,
783
+ operationId,
784
+ previewAuthority,
785
+ this.workspaceRoot,
786
+ this._platform,
787
+ );
788
+ lease.assertOwned();
789
+
790
+ const sessionIntentAuthority =
791
+ rawSessionProjection.intent.authority;
792
+ const workspaceExpected = Object.freeze({
793
+ operationId,
794
+ restoreKind: previewAuthority.restoreKind,
795
+ checkpointId: previewAuthority.checkpointId,
796
+ checkpointIdentity: previewAuthority.checkpointIdentity,
797
+ checkpointNamespace: previewAuthority.checkpointNamespace,
798
+ workspaceScopeIdentity:
799
+ sessionIntentAuthority.workspaceScopeIdentity,
800
+ workspaceTargetPoststateIdentity:
801
+ sessionIntentAuthority.workspaceTargetPoststateIdentity,
802
+ poststateDigest: previewAuthority.poststateDigest,
803
+ });
804
+ const rawWorkspaceProjection = requireSynchronous(
805
+ this._verifyWorkspaceTarget(
806
+ Object.freeze({
807
+ operationId,
808
+ workspaceRoot: this.workspaceRoot,
809
+ workspaceLease: lease,
810
+ expected: workspaceExpected,
811
+ }),
812
+ ),
813
+ "checkpoint restore workspace target verification",
814
+ );
815
+ const workspace = validateWorkspaceProjection(
816
+ rawWorkspaceProjection,
817
+ operationId,
818
+ previewAuthority,
819
+ sessionIntentAuthority,
820
+ );
821
+ lease.assertOwned();
822
+
823
+ const projection = resultProjection(
824
+ operationId,
825
+ workspace,
826
+ session,
827
+ );
828
+ const resultDigest = computeCheckpointRestoreDigest(
829
+ "cc-checkpoint-restore-already-completed-result-v1",
830
+ projection,
831
+ );
832
+ completedEvidence = Object.freeze({
833
+ recoveryAction: CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION,
834
+ sessionCommitDigest: session.sessionCommitDigest,
835
+ resultDigest,
836
+ });
837
+
838
+ let saga = this._loadExact(operationId, expectedSeq, expectedHash);
839
+ timelineSagaAuthority(saga, this.workspaceRoot, this._platform);
840
+ if (saga.phase !== "recovery_required") {
841
+ saga = this._advanceExact(saga, "recovery_required", {
842
+ reason:
843
+ "Verified session completion requires exact saga reconciliation",
844
+ errorCode:
845
+ "CHECKPOINT_RESTORE_ALREADY_COMPLETED_RECONCILIATION",
846
+ });
847
+ }
848
+ lease.assertOwned();
849
+ saga = this._advanceExact(saga, "recovery_started", {
850
+ workspaceLockOwner: lease.owner,
851
+ lockOwnerDigest: this._workspaceLockOwnerDigest(lease.owner),
852
+ recoveryAction: CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION,
853
+ });
854
+ lease.assertOwned();
855
+ saga = this._advanceExact(saga, "completed", completedEvidence);
856
+ lease.assertOwned();
857
+ return Object.freeze({
858
+ saga,
859
+ sessionCommitDigest: session.sessionCommitDigest,
860
+ resultDigest,
861
+ reconciledFromError: false,
862
+ });
863
+ } catch (error) {
864
+ const reconciled = this._retainFailure(
865
+ error,
866
+ lease,
867
+ completedEvidence,
868
+ );
869
+ if (reconciled?.saga) {
870
+ return Object.freeze({
871
+ saga: reconciled.saga,
872
+ sessionCommitDigest: completedEvidence.sessionCommitDigest,
873
+ resultDigest: completedEvidence.resultDigest,
874
+ reconciledFromError: true,
875
+ });
876
+ }
877
+ return reconciled;
878
+ }
879
+ },
880
+ );
881
+ } catch (error) {
882
+ throw propagateRecoveryDiagnostics(error);
883
+ }
884
+
885
+ const archive = this._archiveTerminal(settled.saga);
886
+ return Object.freeze({
887
+ ok: true,
888
+ action: CHECKPOINT_RESTORE_ALREADY_COMPLETED_ACTION,
889
+ ...terminalSummary(settled.saga),
890
+ sessionCommitDigest: settled.sessionCommitDigest,
891
+ resultDigest: settled.resultDigest,
892
+ reconciledFromError: settled.reconciledFromError,
893
+ ...archive,
894
+ });
895
+ }
896
+ }
897
+
898
+ export function createCheckpointRestoreAlreadyCompletedController(
899
+ options = {},
900
+ ) {
901
+ return new CheckpointRestoreAlreadyCompletedController(options);
902
+ }