chainlesschain 0.165.2 → 0.165.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/README.md +151 -29
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/assets/{AIOps-lS1R0Cza.js → AIOps-C__nnraW.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BmlgBPsj.js → ActionButton-CsKWHEZ-.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CNKczv1S.js → Analytics-BhIjfjWO.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BuZGJARQ.js → AppLayout-BjuXFzWZ.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-Dm73Sl-O.js → Artifacts-k6whDkZJ.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BGMW7A5e.js → Audit-C4FBMYRh.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BQ6M54JR.js → BackgroundAgents-C_vRrSXk.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-DBzGP0bR.js → Backup-CngFZeVp.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-D1mLCoOV.js → BaseInput-B_H9EBRm.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BUfcN7p8.js → Chat-DLEC5kt7.js} +4 -4
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-Du0Yg5Pi.js → Checkbox-m3ClR4xh.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-B2RXziHW.js → Codegen-CmLSFrgp.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DWhekOrR.js → Col-DFGQteHN.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-HQhrkon4.js → Community-EUUVORHE.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-izHNb4uz.js → Compact-2PSg0Yr7.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-BDwLy41-.js → Compliance-CcKur7gB.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DFJhLa7K.js → Cowork-DK_Fezfa.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DYY9RG7-.js → Cron-Dbw89xl7.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-rr7tJTtv.js → Crosschain-CH66h_Ec.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-D2sfHRLi.js → DID-D1igRb17.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-q_eGdhha.js → Dashboard-DVAsrobk.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-Cufrh2Bz.js → Dropdown-Dl7W8AQs.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-B-kdv10f.js → EmailListRenderer-D5tpaEQC.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D21XjgfG.js → FamilyGuardDashboard-O_VQf8gq.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-CAwRTLZH.js → Federation-BTVcgS9n.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-vx3daNDF.js → FormItemContext-BRnkJAIz.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-CRWY2wU4.js → GenericCardRenderer-8OWSCkDj.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Q6SwauyD.js → Git-WXLYTQj2.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BJ1q4IQZ.js → Governance-BezaUhtc.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CSWjROgD.js → Inference-CuRay3Gu.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-fzuQsWuY.js → KnowledgeGraph-DfWLDW1m.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DVF8Mnns.js → Logs-C55y2pPY.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-BQP7LOA4.js → Marketplace-Dk08Uycg.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-BNlJCmNc.js → McpTools-C11fSB5V.js} +4 -4
  39. package/src/assets/web-panel/assets/{Memory-DLLg5WQ4.js → Memory-mr0eZc97.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CR2skNAF.js → MobileBridge-C0iCSRbb.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-BxVavObl.js → MobileProjects-CY-xMG8Z.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-B17pgqMI.js → Mtc-Bplqc_Wc.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-4UmV5cIL.js → MtcAudit-BlzwsoSM.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-DoMEXEcU.js → Multisig-BBLmTty6.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-h9DMXFX4.js → NLProgramming-DtT1uf1W.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-Cihn-xX8.js → Notes-DcqQAxTK.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-BE6ZGa3R.js → NotificationSettings-cb0kWoZe.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-CnwojoSI.js → OrderTableRenderer-kw9HZQNN.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-B2vpwmjb.js → Organization-DlTlbkUN.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-C4z28R0-.js → Overflow-pp1qs-oY.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-BVlFkwhW.js → P2P-BESLnyYz.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-BXbEdL5B.js → PdhVaultBrowser-B-J1mGuf.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-C28xs4lp.js → Permissions-B36PeT1_.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-Dgl_rBjM.js → PersonalDataHub-CTK2ad-3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-3QUIhrKI.js → Pipeline-zJNGXsac.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-8Gh33OZ5.js → Privacy-b9fz0Qf0.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BNmg4tZi.js → ProjectInit-DjZbZgiB.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-vgMfeCf9.js → ProjectSettings-C-hHJXlD.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CXoOa8eX.js → Providers-Dz-CAYYU.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-BhfTF0oS.js → QrScannerModal-A0yoQ3-3.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-C746HEAj.js → QuickAsk-DrFgFJNC.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-BSej8Eo0.js → Recommend-KC8hF1g4.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-f3gmnlG3.js → RemoteSession-DGTPIk6u.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-CyvybpkN.js → Reputation-QmbwM7Yk.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DwV2PeYn.js → Row-BxjJylia.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-11GrzjZy.js → RssFeed-B7Wda1J6.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-BjKXkrAY.js → Search-_plQ_YSA.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-eWiFb9Yk.js → Security-CD2YJZfx.js} +2 -2
  70. package/src/assets/web-panel/assets/{Services-CdCsMAtt.js → Services-qQE7NmwE.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-4Q2UTKQ5.js → Skeleton-DgQqkFf7.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-v4rtYrRj.js → Skills-C4C0oFFt.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-CRhsFvd_.js → Sla-Px2N2B5c.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-DN6C3lQd.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-D16zonl7.js → SyncSettings-jm5aH_m7.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-Xxozz0i_.js → Tasks-DlkJcv67.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CXJpPtCT.js → Templates-DyrTHUBs.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-XRV0L1ZF.js → Tenant-mC434PtL.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CYuO1i_w.js → Terminal-o0_s3NgK.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-BXqitWsu.js → TimelineRenderer-DAGlAXOw.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BvPrDHIy.js → Tokens-BnulS_bs.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DhCrSTf5.js → Trigger-suQbVXYM.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DmsuZD6K.js → Trust-DbIJAPo5.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-D_yrts5C.js → UkeySign-CQNpbIHi.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-B01ihPrm.js → VideoEditing-D8aWCERk.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-DpUjKa-N.js → Wallet-CuLpYfZc.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CL07yON6.js → WebAuthn-CsfG8ZMc.js} +2 -2
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CLMflnRr.js → WorkflowEditor-BYsEAZbd.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-DtUqe8h_.js → chat-FT4Um3-I.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-DPKrgVfy.js → colors-CKbS_Wlt.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BTt2GtOm.js → compact-item-CFJtzuJM.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-D_VeUc1J.js → createContext-B9kSRW6K.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-1kndiylj.js → hasIn-DR-x0Xpi.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-dVc-CXY4.js → index-7jHr_A_k.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DFIZ_1Sf.js → index-B3ZX81mK.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-fk2Rjacw.js → index-B7osrXqy.js} +3 -3
  98. package/src/assets/web-panel/assets/{index-CHG-KcS4.js → index-BGbPnC5x.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Dbbymxpj.js → index-BI5hP_qy.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BaZAbw9A.js → index-BK3TiKVq.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CzjkKUmR.js → index-BVPU43b1.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BAXfRKfG.js → index-BW-t9n-q.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-8nz_fmlj.js → index-BfFCQHL3.js} +1 -1
  104. package/src/assets/web-panel/assets/index-Bizb4hkw.js +1 -0
  105. package/src/assets/web-panel/assets/{index-DdkplL9R.js → index-Bt4fS2eL.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DG2MZQ3f.js → index-BwR7yc2h.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DfKBRdSS.js → index-Bzz0C1BZ.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-GsoUQ2M7.js → index-C2JvmYRc.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-l1BETrDb.js → index-CGaXUsIs.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-4bna2_SR.js → index-CJmIQ9XR.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DfGl8CqG.js → index-C_enk9I_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D95OFht7.js → index-Cr2FLUsD.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DsJCDUJG.js → index-CvrCCqJt.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-sDoMHTNA.js → index-D4LfPvWA.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-By5n8up9.js → index-DMGmg497.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-ocf06EVQ.js → index-DShSkww-.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bhudc_Ez.js → index-DTxNy0ZU.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CX81qSM4.js → index-DW4BWjTk.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BlDNVgBt.js → index-DWdqx7zI.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CcO04eDn.js → index-Dap9c3eD.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Dwqmtk65.js → index-DcfxhKXR.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-2eyAXE3d.js → index-DdkIhfi-.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-brCInrzq.js → index-DeSgw-WV.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DJ8vXGOa.js → index-DiNUEpSQ.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BHpBMWCh.js → index-DjEP7WkH.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-m31Ka8hZ.js → index-DtkFqPVA.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CtF7EN49.js → index-KqDaCApw.js} +1 -1
  128. package/src/assets/web-panel/assets/index-OHSl-xCh.js +1 -0
  129. package/src/assets/web-panel/assets/{index-B9KvcS7R.js → index-OSzjTzGM.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CauoBQkH.js → index-QBSeNVO3.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-FzdwcSy2.js → index-WE08gMJP.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DxdTdBix.js → index-r2VI1Ikk.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BepLZwgB.js → index-tqSEHPRT.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CvyYJd7z.js → initDefaultProps-Dd7n7VgI.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-DYZkhUdz.js → motion-BwxouRw1.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-slnJRVT1.js → move-DObN0PG9.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DVc0CKmy.js → mtc-parser-B3nOUQc7.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BCXAtHCq.js → omit-o9WU2Nbl.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-DBsemz_K.js → pickAttrs-CL_vvfQ_.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BRtkJ-nv.js → placementArrow-CYrM2tyK.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-Cebq7EZn.js → responsiveObserve-k_06cQ96.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DT7qvId2.js → slide-CPKG0pxS.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-pQiITLkG.js → statusUtils-BDDEeLTw.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-c-19BVKQ.js → styleChecker-Cmb7RTh7.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DsS5-0bE.js → useFlexGapSupport-e2IedC4N.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-CxGiMe5n.js → useFs-CE_gxVnm.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-D9btVID5.js → usePersonalDataHub-BkMIIKMz.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-CUYFsFEN.js → vnode-DW886XV1.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-CXmn_35j.js → zoom-Dwo_adaf.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +3 -3
  152. package/src/commands/agent.js +105 -35
  153. package/src/commands/artifacts.js +363 -33
  154. package/src/commands/cowork.js +202 -36
  155. package/src/commands/session-budget.js +155 -0
  156. package/src/commands/session-location.js +948 -0
  157. package/src/commands/session.js +72 -46
  158. package/src/data/changelog.json +26 -0
  159. package/src/gateways/ws/artifact-protocol.js +77 -13
  160. package/src/gateways/ws/session-protocol.js +391 -24
  161. package/src/gateways/ws/ws-agent-handler.js +191 -14
  162. package/src/gateways/ws/ws-server.js +14 -3
  163. package/src/gateways/ws/ws-session-gateway.js +101 -5
  164. package/src/harness/jsonl-session-store.js +1210 -0
  165. package/src/lib/agent-team/team-runner.js +43 -13
  166. package/src/lib/artifact-access-ledger.js +461 -0
  167. package/src/lib/artifact-cleanup-ledger.js +861 -0
  168. package/src/lib/artifact-deletion-ledger.js +677 -0
  169. package/src/lib/artifact-store.js +256 -51
  170. package/src/lib/background-agent-keeper-protocol.js +75 -4
  171. package/src/lib/background-agent-launch-barrier.js +74 -0
  172. package/src/lib/background-agent-supervisor.js +149 -5
  173. package/src/lib/background-turn-bootstrap-protocol.js +4 -0
  174. package/src/lib/command-lifecycle-report.js +8 -4
  175. package/src/lib/cowork-adapter.js +9 -5
  176. package/src/lib/cowork-task-runner.js +20 -0
  177. package/src/lib/cowork-workflow.js +178 -20
  178. package/src/lib/direct-model-usage.js +62 -22
  179. package/src/lib/dynamic-workflow-runtime.js +3184 -111
  180. package/src/lib/execution-location-result-apply.js +339 -0
  181. package/src/lib/execution-location-result-artifact.js +271 -0
  182. package/src/lib/execution-location-result-review.js +253 -0
  183. package/src/lib/execution-location-result-store.js +331 -0
  184. package/src/lib/execution-location-result.js +617 -0
  185. package/src/lib/execution-location-target.js +236 -1
  186. package/src/lib/managed-tool-checkpoint.js +47 -4
  187. package/src/lib/process-execution-broker/workspace-transaction.js +3 -0
  188. package/src/lib/session-budget-production-root.js +376 -0
  189. package/src/lib/session-budget-runtime.js +109 -18
  190. package/src/lib/session-budget-usage.js +63 -0
  191. package/src/lib/session-host-snapshot.js +19 -2
  192. package/src/lib/session-resource-budget.js +766 -105
  193. package/src/lib/sub-agent-context.js +69 -22
  194. package/src/lib/web-ui-server.js +12 -1
  195. package/src/lib/with-file-lock.js +175 -26
  196. package/src/repl/agent-repl.js +237 -16
  197. package/src/runtime/agent-core.js +123 -0
  198. package/src/runtime/headless-runner.js +135 -46
  199. package/src/runtime/headless-stream.js +133 -25
  200. package/src/runtime/policies/agent-policy.js +10 -0
  201. package/src/workers/background-agent-keeper.js +112 -19
  202. package/src/workers/background-agent-worker.js +383 -134
  203. package/src/workers/background-turn-bootstrap.js +13 -8
  204. package/src/assets/web-panel/assets/ChatBubbleRenderer-CY5m8ZHg.js +0 -1
  205. package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +0 -1
  206. package/src/assets/web-panel/assets/Projects-BhtAVilc.js +0 -1
  207. package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +0 -1
  208. package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +0 -1
  209. package/src/assets/web-panel/assets/index-CPcM-eqo.js +0 -1
  210. package/src/assets/web-panel/assets/index-xeSyVoRe.js +0 -1
@@ -9,19 +9,57 @@ import {
9
9
  import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
10
10
  import {
11
11
  EXECUTION_LOCATION_TARGET_ATTESTATION_SCHEMA,
12
+ EXECUTION_LOCATION_TARGET_RESULT_COLLECTION_SCHEMA,
12
13
  EXECUTION_LOCATION_TARGET_RESUME_SCHEMA,
13
14
  attestExecutionLocationTarget,
15
+ collectExecutionLocationTargetResult,
16
+ createExecutionLocationTargetResultCollectionRequest,
14
17
  readExecutionLocationProfile,
15
18
  resumeExecutionLocationTarget,
16
19
  } from "../lib/execution-location-target.js";
20
+ import {
21
+ EXECUTION_LOCATION_RESULT_BUNDLE_SCHEMA,
22
+ EXECUTION_LOCATION_RESULT_VERIFICATION_SCHEMA,
23
+ MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
24
+ createExecutionLocationResultBundle,
25
+ readExecutionLocationResultBundle,
26
+ readExecutionLocationResultFile,
27
+ verifyExecutionLocationResultBundle,
28
+ } from "../lib/execution-location-result.js";
17
29
  import {
18
30
  MAX_SESSION_REPLICA_BYTES,
19
31
  SESSION_EXECUTION_LOCATION_HANDOFF_INSTALL_SCHEMA,
32
+ SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA,
33
+ SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA,
34
+ SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1,
20
35
  getVerifiedSessionExecutionLocationAuthority,
21
36
  installSessionReplica,
22
37
  installSessionReplicaWithLocationHandoff,
38
+ readVerifiedSessionExecutionLocationResultApply,
39
+ readVerifiedSessionExecutionLocationResultSettlement,
23
40
  readVerifiedTranscriptBytes,
41
+ reserveSessionExecutionLocationResultApply,
42
+ settleSessionExecutionLocationResultApply,
43
+ settleSessionExecutionLocationResultCollection,
24
44
  } from "../harness/jsonl-session-store.js";
45
+ import {
46
+ readStoredExecutionLocationResultBundle,
47
+ storeExecutionLocationResultBundle,
48
+ } from "../lib/execution-location-result-store.js";
49
+ import {
50
+ EXECUTION_LOCATION_RESULT_REVIEW_SCHEMA,
51
+ createExecutionLocationResultReview,
52
+ } from "../lib/execution-location-result-review.js";
53
+ import {
54
+ EXECUTION_LOCATION_RESULT_ARTIFACT_IMPORT_SCHEMA,
55
+ importExecutionLocationResultArtifact,
56
+ } from "../lib/execution-location-result-artifact.js";
57
+ import {
58
+ executeControlledExecutionLocationResultApply,
59
+ terminalExecutionLocationResultApplyTransaction,
60
+ verifyExecutionLocationResultApplySourceGit,
61
+ } from "../lib/execution-location-result-apply.js";
62
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
25
63
  import {
26
64
  sameFileStatIdentity,
27
65
  samePathHandleFileIdentity,
@@ -31,6 +69,8 @@ import {
31
69
  const MAX_HANDOFF_FACTS_BYTES = 1024 * 1024;
32
70
  export const SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA =
33
71
  "cc-session-execution-location-authority/v1";
72
+ export const EXECUTION_LOCATION_RESULT_PREVIEW_SCHEMA =
73
+ "cc-execution-location-result-preview/v1";
34
74
 
35
75
  function readHandoffFacts(filePath, deps = {}) {
36
76
  const runtimeFs = deps.fs || fs;
@@ -314,6 +354,621 @@ export function prepareSessionReplicaHandoff(sessionId, options, deps = {}) {
314
354
  );
315
355
  }
316
356
 
357
+ function parseResultFileSpec(value, label) {
358
+ const text = String(value || "");
359
+ const separator = text.indexOf("=");
360
+ if (separator <= 0 || separator === text.length - 1) {
361
+ throw new Error(`${label} must be <media-type>=<path>`);
362
+ }
363
+ return {
364
+ mediaType: text.slice(0, separator),
365
+ path: text.slice(separator + 1),
366
+ };
367
+ }
368
+
369
+ function collectResultFileSpec(value, previous) {
370
+ return [...previous, value];
371
+ }
372
+
373
+ function resultBoundary(authority) {
374
+ const root = authority?.binding?.policy?.dataBoundary?.root;
375
+ if (typeof root !== "string" || root.length === 0) {
376
+ throw new Error(
377
+ "verified execution location data boundary is required for result files",
378
+ );
379
+ }
380
+ return root;
381
+ }
382
+
383
+ export function createSessionExecutionLocationResultBundle(
384
+ sessionId,
385
+ options,
386
+ deps = {},
387
+ ) {
388
+ const sessionAuthority = projectSessionExecutionLocation(sessionId, deps);
389
+ const boundaryRoot = resultBoundary(sessionAuthority);
390
+ const readFile =
391
+ deps.readExecutionLocationResultFile || readExecutionLocationResultFile;
392
+ const read = (filePath, fileOptions = {}) =>
393
+ readFile(filePath, {
394
+ boundaryRoot,
395
+ ...fileOptions,
396
+ ...(deps.resultFileDependencies || {}),
397
+ });
398
+ const readItems = (values, label) =>
399
+ (values || []).map((value) => {
400
+ const spec = parseResultFileSpec(value, label);
401
+ return {
402
+ mediaType: spec.mediaType,
403
+ bytes: read(spec.path, { allowEmpty: true }),
404
+ };
405
+ });
406
+ return (
407
+ deps.createExecutionLocationResultBundle ||
408
+ createExecutionLocationResultBundle
409
+ )({
410
+ sessionAuthority,
411
+ resultId: options.resultId,
412
+ summaryBytes: read(options.summary),
413
+ diffBytes: read(options.diff, { allowEmpty: true }),
414
+ artifacts: readItems(options.artifact, "--artifact"),
415
+ evidence: readItems(options.evidence, "--evidence"),
416
+ });
417
+ }
418
+
419
+ export function verifySessionExecutionLocationResultBundle(
420
+ sessionId,
421
+ bundlePath,
422
+ expectedHandoffId,
423
+ deps = {},
424
+ ) {
425
+ const sourceAuthority = projectSessionExecutionLocation(sessionId, deps);
426
+ const boundaryRoot = resultBoundary(sourceAuthority);
427
+ const bundle = (
428
+ deps.readExecutionLocationResultBundle || readExecutionLocationResultBundle
429
+ )(bundlePath, {
430
+ boundaryRoot,
431
+ maxBytes: MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
432
+ ...(deps.resultFileDependencies || {}),
433
+ });
434
+ return (
435
+ deps.verifyExecutionLocationResultBundle ||
436
+ verifyExecutionLocationResultBundle
437
+ )({
438
+ bundle,
439
+ sourceAuthority,
440
+ expectedHandoffId,
441
+ });
442
+ }
443
+
444
+ export function collectSessionExecutionLocationResult(
445
+ sessionId,
446
+ target,
447
+ options,
448
+ deps = {},
449
+ ) {
450
+ const profile = (
451
+ deps.readExecutionLocationProfile || readExecutionLocationProfile
452
+ )(options.profile, deps);
453
+ const parseItems = (values, label) =>
454
+ (values || []).map((value) => parseResultFileSpec(value, label));
455
+ const artifacts = parseItems(options.artifact, "--artifact");
456
+ const evidence = parseItems(options.evidence, "--evidence");
457
+ const request = (
458
+ deps.createExecutionLocationTargetResultCollectionRequest ||
459
+ createExecutionLocationTargetResultCollectionRequest
460
+ )({
461
+ requestId: options.requestId,
462
+ sessionId,
463
+ target,
464
+ profile,
465
+ expectedTargetFactsDigest: options.expectedTargetFactsDigest,
466
+ expectedHandoffId: options.expectedHandoffId,
467
+ resultId: options.resultId,
468
+ summaryPath: options.summary,
469
+ diffPath: options.diff,
470
+ artifacts,
471
+ evidence,
472
+ });
473
+ const prior = (
474
+ deps.readVerifiedSessionExecutionLocationResultSettlement ||
475
+ readVerifiedSessionExecutionLocationResultSettlement
476
+ )(sessionId, request.requestId, { requestDigest: request.requestDigest });
477
+ if (prior !== null) {
478
+ if (prior.storage) {
479
+ const bundle = (
480
+ deps.readStoredExecutionLocationResultBundle ||
481
+ readStoredExecutionLocationResultBundle
482
+ )(prior.storage, deps.resultStoreOptions || {});
483
+ const verification = (
484
+ deps.verifyExecutionLocationResultBundle ||
485
+ verifyExecutionLocationResultBundle
486
+ )({
487
+ bundle,
488
+ sourceAuthority: {
489
+ sessionId: prior.sessionId,
490
+ headHash: prior.sourceHeadHash,
491
+ eventCount: prior.sourceEventCount,
492
+ },
493
+ expectedHandoffId: prior.handoffId,
494
+ });
495
+ if (
496
+ verification.verificationDigest !== prior.verificationDigest ||
497
+ bundle.bundleDigest !== prior.bundleDigest
498
+ ) {
499
+ throw new Error("stored result bundle does not match settlement");
500
+ }
501
+ return Object.freeze({
502
+ ...prior,
503
+ settlementAppended: false,
504
+ recovered: true,
505
+ bundleAvailable: true,
506
+ bundle,
507
+ verification,
508
+ });
509
+ }
510
+ return Object.freeze({
511
+ ...prior,
512
+ settlementAppended: false,
513
+ recovered: true,
514
+ bundleAvailable: false,
515
+ });
516
+ }
517
+ const handoff = projectExecutionLocationHandoff(
518
+ sessionId,
519
+ target,
520
+ options.facts,
521
+ deps,
522
+ );
523
+ const readSourceAuthority = () => {
524
+ const authority = (
525
+ deps.getVerifiedSessionExecutionLocationAuthority ||
526
+ getVerifiedSessionExecutionLocationAuthority
527
+ )(sessionId);
528
+ return {
529
+ sessionId: authority.sessionId,
530
+ headHash: authority.headHash,
531
+ eventCount: authority.eventCount,
532
+ };
533
+ };
534
+ const collection = (
535
+ deps.collectExecutionLocationTargetResult ||
536
+ collectExecutionLocationTargetResult
537
+ )(
538
+ {
539
+ requestId: request.requestId,
540
+ handoff,
541
+ profile,
542
+ expectedTargetFactsDigest: options.expectedTargetFactsDigest,
543
+ expectedHandoffId: options.expectedHandoffId,
544
+ resultId: options.resultId,
545
+ summaryPath: options.summary,
546
+ diffPath: options.diff,
547
+ artifacts,
548
+ evidence,
549
+ readSourceAuthority,
550
+ },
551
+ deps,
552
+ );
553
+ if (collection.requestDigest !== request.requestDigest) {
554
+ throw new Error(
555
+ "result collection request digest changed during collection",
556
+ );
557
+ }
558
+ const storage = (
559
+ deps.storeExecutionLocationResultBundle ||
560
+ storeExecutionLocationResultBundle
561
+ )(collection.bundle, deps.resultStoreOptions || {});
562
+ const settlement = (
563
+ deps.settleSessionExecutionLocationResultCollection ||
564
+ settleSessionExecutionLocationResultCollection
565
+ )(sessionId, request.requestId, collection, storage.receipt);
566
+ return Object.freeze({
567
+ ...collection,
568
+ storage: Object.freeze({ ...storage.receipt, stored: storage.stored }),
569
+ settlement,
570
+ });
571
+ }
572
+
573
+ function readSessionExecutionLocationResultReviewAuthority(
574
+ sessionId,
575
+ requestId,
576
+ deps,
577
+ ) {
578
+ const settlement = (
579
+ deps.readVerifiedSessionExecutionLocationResultSettlement ||
580
+ readVerifiedSessionExecutionLocationResultSettlement
581
+ )(sessionId, requestId);
582
+ if (settlement === null) {
583
+ throw new Error("result collection settlement was not found");
584
+ }
585
+ if (!settlement.storage) {
586
+ throw new Error(
587
+ "legacy result settlement has no durable bundle available for review",
588
+ );
589
+ }
590
+ const bundle = (
591
+ deps.readStoredExecutionLocationResultBundle ||
592
+ readStoredExecutionLocationResultBundle
593
+ )(settlement.storage, deps.resultStoreOptions || {});
594
+ const review = (
595
+ deps.createExecutionLocationResultReview ||
596
+ createExecutionLocationResultReview
597
+ )({ settlement, bundle });
598
+ return Object.freeze({ settlement, bundle, review });
599
+ }
600
+
601
+ export function reviewSessionExecutionLocationResult(
602
+ sessionId,
603
+ requestId,
604
+ deps = {},
605
+ ) {
606
+ return readSessionExecutionLocationResultReviewAuthority(
607
+ sessionId,
608
+ requestId,
609
+ deps,
610
+ ).review;
611
+ }
612
+
613
+ function selectResultPreviewRecord(bundle, selectorInput) {
614
+ const selector = String(selectorInput || "");
615
+ if (selector === "summary" || selector === "diff") {
616
+ return { kind: selector, record: bundle[selector] };
617
+ }
618
+ const match = /^(artifact|evidence):(sha256:[a-f0-9]{64})$/u.exec(selector);
619
+ if (!match) {
620
+ throw new Error(
621
+ "result preview item must be summary, diff, artifact:<sha256>, or evidence:<sha256>",
622
+ );
623
+ }
624
+ const [, kind, digest] = match;
625
+ const record = bundle[kind === "artifact" ? "artifacts" : "evidence"].find(
626
+ (entry) => entry.digest === digest,
627
+ );
628
+ if (!record) {
629
+ throw new Error(`reviewed ${kind} digest was not found`);
630
+ }
631
+ return { kind, record };
632
+ }
633
+
634
+ export function previewSessionExecutionLocationResult(
635
+ sessionId,
636
+ requestId,
637
+ reviewDigest,
638
+ item,
639
+ deps = {},
640
+ ) {
641
+ const loaded = readSessionExecutionLocationResultReviewAuthority(
642
+ sessionId,
643
+ requestId,
644
+ deps,
645
+ );
646
+ assertReviewDigest(loaded.review, reviewDigest);
647
+ const selected = selectResultPreviewRecord(loaded.bundle, item);
648
+ const bytes = Buffer.from(selected.record.contentBase64, "base64");
649
+ const reviewedRecord =
650
+ selected.kind === "artifact" || selected.kind === "evidence"
651
+ ? loaded.review[
652
+ selected.kind === "artifact" ? "artifacts" : "evidence"
653
+ ].find((entry) => entry.digest === selected.record.digest)
654
+ : loaded.review[selected.kind];
655
+ if (
656
+ bytes.byteLength !== selected.record.byteLength ||
657
+ reviewedRecord?.digest !== selected.record.digest ||
658
+ reviewedRecord?.byteLength !== selected.record.byteLength ||
659
+ reviewedRecord?.mediaType !== selected.record.mediaType
660
+ ) {
661
+ throw new Error(
662
+ "result preview content no longer matches review authority",
663
+ );
664
+ }
665
+ return Object.freeze({
666
+ schema: EXECUTION_LOCATION_RESULT_PREVIEW_SCHEMA,
667
+ sessionId,
668
+ requestId,
669
+ reviewDigest: loaded.review.reviewDigest,
670
+ item: String(item),
671
+ kind: selected.kind,
672
+ mediaType: selected.record.mediaType,
673
+ byteLength: selected.record.byteLength,
674
+ digest: selected.record.digest,
675
+ bytes,
676
+ });
677
+ }
678
+
679
+ export function importSessionExecutionLocationResultArtifact(
680
+ sessionId,
681
+ requestId,
682
+ reviewDigest,
683
+ item,
684
+ deps = {},
685
+ ) {
686
+ const preview = previewSessionExecutionLocationResult(
687
+ sessionId,
688
+ requestId,
689
+ reviewDigest,
690
+ item,
691
+ deps,
692
+ );
693
+ return (
694
+ deps.importExecutionLocationResultArtifact ||
695
+ importExecutionLocationResultArtifact
696
+ )(preview, { artifactStore: deps.artifactStore });
697
+ }
698
+
699
+ function terminalSafeText(bytes) {
700
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
701
+ return text.replace(
702
+ // The explicit control ranges are the terminal-injection boundary.
703
+ // eslint-disable-next-line no-control-regex
704
+ /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,
705
+ (character) =>
706
+ character.codePointAt(0) <= 0xff
707
+ ? `\\x${character.codePointAt(0).toString(16).padStart(2, "0")}`
708
+ : `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`,
709
+ );
710
+ }
711
+
712
+ export function writeSessionExecutionLocationResultPreview(preview, deps = {}) {
713
+ const output = deps.stdout || process.stdout;
714
+ const isTerminal = deps.isTTY ?? output.isTTY === true;
715
+ if (!isTerminal) {
716
+ output.write(preview.bytes);
717
+ return;
718
+ }
719
+ if (!["summary", "diff"].includes(preview.kind)) {
720
+ throw new Error(
721
+ "binary artifact/evidence preview requires redirected stdout",
722
+ );
723
+ }
724
+ output.write(terminalSafeText(preview.bytes));
725
+ }
726
+
727
+ function assertReviewDigest(review, expectedReviewDigest) {
728
+ if (review.reviewDigest !== String(expectedReviewDigest || "")) {
729
+ throw new Error(
730
+ "result apply review digest does not match stored authority",
731
+ );
732
+ }
733
+ }
734
+
735
+ function resultApplyProjection(receipt, options = {}) {
736
+ return Object.freeze({
737
+ ...receipt,
738
+ recovered: options.recovered === true,
739
+ allowed: receipt.applied === true,
740
+ stage: options.stage || (receipt.applied ? "complete" : receipt.status),
741
+ process: options.process || null,
742
+ });
743
+ }
744
+
745
+ function settleResultApplyFromTransaction(
746
+ sessionId,
747
+ applyId,
748
+ transactionState,
749
+ deps,
750
+ options = {},
751
+ ) {
752
+ const terminalTransaction = (
753
+ deps.terminalExecutionLocationResultApplyTransaction ||
754
+ terminalExecutionLocationResultApplyTransaction
755
+ )(transactionState);
756
+ const outcome =
757
+ transactionState.state === "committed" ? "applied" : "rolled_back";
758
+ const receipt = (
759
+ deps.settleSessionExecutionLocationResultApply ||
760
+ settleSessionExecutionLocationResultApply
761
+ )(sessionId, applyId, outcome, terminalTransaction);
762
+ return resultApplyProjection(receipt, {
763
+ recovered: options.recovered,
764
+ stage: options.stage || (outcome === "applied" ? "complete" : "recovery"),
765
+ process: options.process,
766
+ });
767
+ }
768
+
769
+ function readPriorResultApply(sessionId, applyId, deps) {
770
+ return (
771
+ deps.readVerifiedSessionExecutionLocationResultApply ||
772
+ readVerifiedSessionExecutionLocationResultApply
773
+ )(sessionId, applyId);
774
+ }
775
+
776
+ function inspectResultApplyTransaction(receipt, deps) {
777
+ const broker = deps.executionBroker || executionBroker;
778
+ if (typeof broker.inspectWorkspaceTransaction !== "function") {
779
+ throw new Error("result apply transaction inspection is unavailable");
780
+ }
781
+ return broker.inspectWorkspaceTransaction(receipt.transaction.id, {
782
+ ...(deps.transactionStateDir ? { stateDir: deps.transactionStateDir } : {}),
783
+ });
784
+ }
785
+
786
+ export function applySessionExecutionLocationResult(
787
+ sessionId,
788
+ options,
789
+ deps = {},
790
+ ) {
791
+ const loaded = readSessionExecutionLocationResultReviewAuthority(
792
+ sessionId,
793
+ options.requestId,
794
+ deps,
795
+ );
796
+ assertReviewDigest(loaded.review, options.reviewDigest);
797
+ const prior = readPriorResultApply(sessionId, options.applyId, deps);
798
+ if (prior !== null && prior.terminal !== null) {
799
+ if (
800
+ prior.requestId !== options.requestId ||
801
+ prior.reviewDigest !== loaded.review.reviewDigest
802
+ ) {
803
+ throw new Error("result apply id is already bound to different inputs");
804
+ }
805
+ return resultApplyProjection(prior, { recovered: true });
806
+ }
807
+ if (prior !== null) {
808
+ if (
809
+ prior.requestId !== options.requestId ||
810
+ prior.reviewDigest !== loaded.review.reviewDigest
811
+ ) {
812
+ throw new Error("result apply id is already bound to different inputs");
813
+ }
814
+ const transactionState = inspectResultApplyTransaction(prior, deps);
815
+ if (["committed", "rolled_back"].includes(transactionState.state)) {
816
+ return settleResultApplyFromTransaction(
817
+ sessionId,
818
+ options.applyId,
819
+ transactionState,
820
+ deps,
821
+ { recovered: true },
822
+ );
823
+ }
824
+ throw new Error(
825
+ `result apply recovery is required for transaction ${prior.transaction.id}`,
826
+ );
827
+ }
828
+
829
+ const authority = (
830
+ deps.getVerifiedSessionExecutionLocationAuthority ||
831
+ getVerifiedSessionExecutionLocationAuthority
832
+ )(sessionId);
833
+ if (
834
+ authority.headHash !== loaded.settlement.settlementEventHash ||
835
+ authority.eventCount !== loaded.settlement.settlementEventCount
836
+ ) {
837
+ throw new Error("source session advanced after result settlement");
838
+ }
839
+ const broker = deps.executionBroker || executionBroker;
840
+ const source = (
841
+ deps.verifyExecutionLocationResultApplySourceGit ||
842
+ verifyExecutionLocationResultApplySourceGit
843
+ )(authority, {
844
+ broker,
845
+ workspaceRoot: options.workspace,
846
+ platform: deps.platform,
847
+ });
848
+ const diffBytes = Buffer.from(loaded.bundle.diff.contentBase64, "base64");
849
+ const execution = (
850
+ deps.executeControlledExecutionLocationResultApply ||
851
+ executeControlledExecutionLocationResultApply
852
+ )({
853
+ broker,
854
+ sessionId,
855
+ applyId: options.applyId,
856
+ workspaceRoot: source.workspaceRoot,
857
+ diffBytes,
858
+ ...(deps.transactionStateDir ? { stateDir: deps.transactionStateDir } : {}),
859
+ onPrepared: (transaction) => {
860
+ const pinnedSource = (
861
+ deps.verifyExecutionLocationResultApplySourceGit ||
862
+ verifyExecutionLocationResultApplySourceGit
863
+ )(authority, {
864
+ broker,
865
+ workspaceRoot: source.workspaceRoot,
866
+ platform: deps.platform,
867
+ });
868
+ if (
869
+ pinnedSource.sourceGit.rootDigest !== source.sourceGit.rootDigest ||
870
+ pinnedSource.sourceGit.commit !== source.sourceGit.commit
871
+ ) {
872
+ throw new Error("source Git identity changed during apply preparation");
873
+ }
874
+ return (
875
+ deps.reserveSessionExecutionLocationResultApply ||
876
+ reserveSessionExecutionLocationResultApply
877
+ )(
878
+ sessionId,
879
+ options.applyId,
880
+ loaded.review,
881
+ pinnedSource.sourceGit,
882
+ transaction,
883
+ );
884
+ },
885
+ });
886
+ if (execution.stage === "reservation") {
887
+ const reserved = readPriorResultApply(sessionId, options.applyId, deps);
888
+ if (reserved === null) throw execution.error;
889
+ if (
890
+ reserved.reviewDigest !== loaded.review.reviewDigest ||
891
+ reserved.transaction.id !== execution.transaction.id
892
+ ) {
893
+ throw new Error("result apply reservation response is ambiguous");
894
+ }
895
+ }
896
+ const receipt = (
897
+ deps.settleSessionExecutionLocationResultApply ||
898
+ settleSessionExecutionLocationResultApply
899
+ )(sessionId, options.applyId, execution.outcome, execution.transaction);
900
+ return resultApplyProjection(receipt, {
901
+ stage: execution.stage,
902
+ process: execution.process,
903
+ });
904
+ }
905
+
906
+ export function recoverSessionExecutionLocationResultApply(
907
+ sessionId,
908
+ options,
909
+ deps = {},
910
+ ) {
911
+ const loaded = readSessionExecutionLocationResultReviewAuthority(
912
+ sessionId,
913
+ options.requestId,
914
+ deps,
915
+ );
916
+ assertReviewDigest(loaded.review, options.reviewDigest);
917
+ const prior = readPriorResultApply(sessionId, options.applyId, deps);
918
+ if (prior === null) {
919
+ throw new Error("result apply reservation was not found");
920
+ }
921
+ if (
922
+ prior.requestId !== options.requestId ||
923
+ prior.reviewDigest !== loaded.review.reviewDigest
924
+ ) {
925
+ throw new Error("result apply recovery authority does not match review");
926
+ }
927
+ if (prior.terminal !== null) {
928
+ return resultApplyProjection(prior, { recovered: true });
929
+ }
930
+ const broker = deps.executionBroker || executionBroker;
931
+ const authority = (
932
+ deps.getVerifiedSessionExecutionLocationAuthority ||
933
+ getVerifiedSessionExecutionLocationAuthority
934
+ )(sessionId);
935
+ const source = (
936
+ deps.verifyExecutionLocationResultApplySourceGit ||
937
+ verifyExecutionLocationResultApplySourceGit
938
+ )(authority, {
939
+ broker,
940
+ workspaceRoot: options.workspace,
941
+ platform: deps.platform,
942
+ });
943
+ let transactionState = inspectResultApplyTransaction(prior, deps);
944
+ if (!["committed", "rolled_back"].includes(transactionState.state)) {
945
+ if (typeof broker.recoverWorkspaceTransactions !== "function") {
946
+ throw new Error("result apply workspace recovery is unavailable");
947
+ }
948
+ broker.recoverWorkspaceTransactions({
949
+ id: prior.transaction.id,
950
+ workspaceRoot: source.workspaceRoot,
951
+ reason: "explicit session result apply recovery",
952
+ ...(deps.transactionStateDir
953
+ ? { stateDir: deps.transactionStateDir }
954
+ : {}),
955
+ });
956
+ transactionState = inspectResultApplyTransaction(prior, deps);
957
+ }
958
+ if (!["committed", "rolled_back"].includes(transactionState.state)) {
959
+ throw new Error(
960
+ `result apply transaction still requires manual recovery: ${transactionState.state}`,
961
+ );
962
+ }
963
+ return settleResultApplyFromTransaction(
964
+ sessionId,
965
+ options.applyId,
966
+ transactionState,
967
+ deps,
968
+ { recovered: true, stage: "recovery" },
969
+ );
970
+ }
971
+
317
972
  function renderBinding(binding) {
318
973
  const git = binding.source.git;
319
974
  return [
@@ -350,6 +1005,57 @@ function writeProjection(projection, options = {}) {
350
1005
  );
351
1006
  return;
352
1007
  }
1008
+ if (projection.schema === EXECUTION_LOCATION_RESULT_BUNDLE_SCHEMA) {
1009
+ process.stdout.write(
1010
+ `RESULT BUNDLE ${projection.resultId}\nBundle: ${projection.bundleDigest}\nBytes: ${projection.totalBytes}\nUse --json to transfer the canonical bundle bytes.\n`,
1011
+ );
1012
+ return;
1013
+ }
1014
+ if (projection.schema === EXECUTION_LOCATION_RESULT_VERIFICATION_SCHEMA) {
1015
+ process.stdout.write(
1016
+ `RESULT VERIFIED ${projection.resultId}\nBundle: ${projection.bundleDigest}\nVerification: ${projection.verificationDigest}\nApplied: no\n`,
1017
+ );
1018
+ return;
1019
+ }
1020
+ if (projection.schema === EXECUTION_LOCATION_RESULT_REVIEW_SCHEMA) {
1021
+ process.stdout.write(
1022
+ `RESULT REVIEWED ${projection.resultId}\nReview: ${projection.reviewDigest}\nBundle: ${projection.bundleDigest}\nSummary: ${projection.summary.byteLength} bytes (${projection.summary.digest})\nDiff: ${projection.diff.byteLength} bytes (${projection.diff.digest})\nApplied: no\n`,
1023
+ );
1024
+ return;
1025
+ }
1026
+ if (projection.schema === EXECUTION_LOCATION_RESULT_ARTIFACT_IMPORT_SCHEMA) {
1027
+ process.stdout.write(
1028
+ `RESULT ARTIFACT ${projection.imported ? "IMPORTED" : "AVAILABLE"} ${projection.artifact.id}\nImport: ${projection.importDigest}\nReview: ${projection.source.reviewDigest}\nItem: ${projection.source.item}\nArtifact bytes: ${projection.artifact.size} (${projection.source.sourceDigest})\nContent emitted: no\n`,
1029
+ );
1030
+ return;
1031
+ }
1032
+ if (
1033
+ projection.schema === SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA
1034
+ ) {
1035
+ process.stdout.write(
1036
+ `RESULT APPLY ${projection.applied ? "APPLIED" : "ROLLED BACK"} ${projection.applyId}\nReview: ${projection.reviewDigest}\nTransaction: ${projection.transaction.id}\nEvidence: ${projection.transaction.evidenceDigest || "pending"}\nRecovered: ${projection.recovered ? "yes" : "no"}\n`,
1037
+ );
1038
+ return;
1039
+ }
1040
+ if (
1041
+ projection.schema === EXECUTION_LOCATION_TARGET_RESULT_COLLECTION_SCHEMA
1042
+ ) {
1043
+ process.stdout.write(
1044
+ `RESULT COLLECTED ${projection.resultId}\nBundle: ${projection.bundleDigest}\nCollection: ${projection.collectionDigest}\nApplied: no\nGaps: ${projection.gaps.join(", ")}\n`,
1045
+ );
1046
+ return;
1047
+ }
1048
+ if (
1049
+ [
1050
+ SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA,
1051
+ SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1,
1052
+ ].includes(projection.schema)
1053
+ ) {
1054
+ process.stdout.write(
1055
+ `RESULT COLLECTION SETTLED ${projection.resultId}\nRequest: ${projection.requestId}\nSettlement: ${projection.receiptDigest}\nBundle bytes available: ${projection.bundleAvailable ? "yes" : "no"}\nApplied: no\n`,
1056
+ );
1057
+ return;
1058
+ }
353
1059
  if (projection.schema === "chainlesschain.session-replica-install/v1") {
354
1060
  process.stdout.write(
355
1061
  `${projection.installed ? "INSTALLED" : "ALREADY PRESENT"} ${projection.sessionId}\nReceipt: ${projection.receiptDigest}\n`,
@@ -399,6 +1105,16 @@ function runAction(action, options = {}) {
399
1105
  }
400
1106
  }
401
1107
 
1108
+ function runPreviewAction(action, deps = {}) {
1109
+ try {
1110
+ writeSessionExecutionLocationResultPreview(action(), deps);
1111
+ return 0;
1112
+ } catch (error) {
1113
+ process.stderr.write(`Execution location failed: ${error.message}\n`);
1114
+ return 1;
1115
+ }
1116
+ }
1117
+
402
1118
  export function registerSessionLocationSubcommands(session, deps = {}) {
403
1119
  const location = session
404
1120
  .command("location")
@@ -584,4 +1300,236 @@ export function registerSessionLocationSubcommands(session, deps = {}) {
584
1300
  options,
585
1301
  );
586
1302
  });
1303
+
1304
+ location
1305
+ .command("result-pack <id>")
1306
+ .description(
1307
+ "Build a bounded result bundle from a verified target handoff session",
1308
+ )
1309
+ .requiredOption("--result-id <id>", "Stable result bundle id")
1310
+ .requiredOption(
1311
+ "--summary <path>",
1312
+ "UTF-8 summary file inside the data boundary",
1313
+ )
1314
+ .requiredOption("--diff <path>", "Diff file inside the data boundary")
1315
+ .option(
1316
+ "--artifact <media-type=path>",
1317
+ "Artifact bytes to include (repeatable)",
1318
+ collectResultFileSpec,
1319
+ [],
1320
+ )
1321
+ .option(
1322
+ "--evidence <media-type=path>",
1323
+ "Evidence bytes to include (repeatable)",
1324
+ collectResultFileSpec,
1325
+ [],
1326
+ )
1327
+ .option("--json", "Write the canonical bundle including base64 content")
1328
+ .action((id, options) => {
1329
+ process.exitCode = runAction(
1330
+ () => createSessionExecutionLocationResultBundle(id, options, deps),
1331
+ options,
1332
+ );
1333
+ });
1334
+
1335
+ location
1336
+ .command("result-verify <id>")
1337
+ .description(
1338
+ "Rehash a returned bundle and bind it to the unchanged source session",
1339
+ )
1340
+ .requiredOption("--bundle <path>", "Returned canonical bundle JSON")
1341
+ .requiredOption(
1342
+ "--expected-handoff-id <sha256>",
1343
+ "Exact handoff id accepted before target execution",
1344
+ )
1345
+ .option("--json", "Machine-readable content-free verification receipt")
1346
+ .action((id, options) => {
1347
+ process.exitCode = runAction(
1348
+ () =>
1349
+ verifySessionExecutionLocationResultBundle(
1350
+ id,
1351
+ options.bundle,
1352
+ options.expectedHandoffId,
1353
+ deps,
1354
+ ),
1355
+ options,
1356
+ );
1357
+ });
1358
+
1359
+ location
1360
+ .command("result-collect <id> <target>")
1361
+ .description(
1362
+ "Fetch a target result through the fixed transport and verify it on source",
1363
+ )
1364
+ .requiredOption("--facts <path>", "Accepted handoff facts JSON")
1365
+ .requiredOption("--profile <path>", "Secret-free target profile JSON")
1366
+ .requiredOption(
1367
+ "--expected-target-facts-digest <sha256>",
1368
+ "Exact stable target facts digest accepted before execution",
1369
+ )
1370
+ .requiredOption(
1371
+ "--expected-handoff-id <sha256>",
1372
+ "Exact canonical target handoff id",
1373
+ )
1374
+ .requiredOption(
1375
+ "--request-id <id>",
1376
+ "Stable idempotency id for canonical collection settlement",
1377
+ )
1378
+ .requiredOption("--result-id <id>", "Stable result bundle id")
1379
+ .requiredOption("--summary <path>", "Target summary path")
1380
+ .requiredOption("--diff <path>", "Target diff path")
1381
+ .option(
1382
+ "--artifact <media-type=path>",
1383
+ "Target artifact bytes to include (repeatable)",
1384
+ collectResultFileSpec,
1385
+ [],
1386
+ )
1387
+ .option(
1388
+ "--evidence <media-type=path>",
1389
+ "Target evidence bytes to include (repeatable)",
1390
+ collectResultFileSpec,
1391
+ [],
1392
+ )
1393
+ .option(
1394
+ "--json",
1395
+ "Machine-readable collection with bundle bytes and verification receipt",
1396
+ )
1397
+ .action((id, target, options) => {
1398
+ process.exitCode = runAction(
1399
+ () => collectSessionExecutionLocationResult(id, target, options, deps),
1400
+ options,
1401
+ );
1402
+ });
1403
+
1404
+ location
1405
+ .command("result-review <id>")
1406
+ .description(
1407
+ "Review stored result metadata without exposing or applying content",
1408
+ )
1409
+ .requiredOption(
1410
+ "--request-id <id>",
1411
+ "Canonical result collection request id",
1412
+ )
1413
+ .option("--json", "Machine-readable content-free review authority")
1414
+ .action((id, options) => {
1415
+ process.exitCode = runAction(
1416
+ () => reviewSessionExecutionLocationResult(id, options.requestId, deps),
1417
+ options,
1418
+ );
1419
+ });
1420
+
1421
+ location
1422
+ .command("result-preview <id>")
1423
+ .description(
1424
+ "Explicitly stream one reviewed result item without changing the workspace",
1425
+ )
1426
+ .requiredOption(
1427
+ "--request-id <id>",
1428
+ "Canonical result collection request id",
1429
+ )
1430
+ .requiredOption(
1431
+ "--review-digest <sha256>",
1432
+ "Exact content-free review digest accepted by the operator",
1433
+ )
1434
+ .requiredOption(
1435
+ "--item <selector>",
1436
+ "summary, diff, artifact:<sha256>, or evidence:<sha256>",
1437
+ )
1438
+ .action((id, options) => {
1439
+ process.exitCode = runPreviewAction(
1440
+ () =>
1441
+ previewSessionExecutionLocationResult(
1442
+ id,
1443
+ options.requestId,
1444
+ options.reviewDigest,
1445
+ options.item,
1446
+ deps,
1447
+ ),
1448
+ deps.previewOutputDependencies || {},
1449
+ );
1450
+ });
1451
+
1452
+ location
1453
+ .command("result-import <id>")
1454
+ .description(
1455
+ "Import one explicitly reviewed result item into the managed ArtifactStore",
1456
+ )
1457
+ .requiredOption(
1458
+ "--request-id <id>",
1459
+ "Canonical result collection request id",
1460
+ )
1461
+ .requiredOption(
1462
+ "--review-digest <sha256>",
1463
+ "Exact content-free review digest accepted by the operator",
1464
+ )
1465
+ .requiredOption(
1466
+ "--item <selector>",
1467
+ "summary, diff, artifact:<sha256>, or evidence:<sha256>",
1468
+ )
1469
+ .option("--json", "Machine-readable content-free import receipt")
1470
+ .action((id, options) => {
1471
+ process.exitCode = runAction(
1472
+ () =>
1473
+ importSessionExecutionLocationResultArtifact(
1474
+ id,
1475
+ options.requestId,
1476
+ options.reviewDigest,
1477
+ options.item,
1478
+ deps,
1479
+ ),
1480
+ options,
1481
+ );
1482
+ });
1483
+
1484
+ location
1485
+ .command("result-apply <id>")
1486
+ .description(
1487
+ "Apply one explicitly reviewed stored diff inside a durable workspace transaction",
1488
+ )
1489
+ .requiredOption(
1490
+ "--request-id <id>",
1491
+ "Canonical result collection request id",
1492
+ )
1493
+ .requiredOption("--apply-id <id>", "Stable result apply idempotency id")
1494
+ .requiredOption(
1495
+ "--review-digest <sha256>",
1496
+ "Exact content-free review digest accepted by the operator",
1497
+ )
1498
+ .option(
1499
+ "--workspace <path>",
1500
+ "Exact source Git workspace (defaults to session authority)",
1501
+ )
1502
+ .option("--json", "Machine-readable content-free apply receipt")
1503
+ .action((id, options) => {
1504
+ process.exitCode = runAction(
1505
+ () => applySessionExecutionLocationResult(id, options, deps),
1506
+ options,
1507
+ );
1508
+ });
1509
+
1510
+ location
1511
+ .command("result-apply-recover <id>")
1512
+ .description(
1513
+ "Explicitly recover a reserved result apply without replaying its diff",
1514
+ )
1515
+ .requiredOption(
1516
+ "--request-id <id>",
1517
+ "Canonical result collection request id",
1518
+ )
1519
+ .requiredOption("--apply-id <id>", "Reserved result apply id")
1520
+ .requiredOption(
1521
+ "--review-digest <sha256>",
1522
+ "Exact content-free review digest bound to the reservation",
1523
+ )
1524
+ .option(
1525
+ "--workspace <path>",
1526
+ "Exact source Git workspace (defaults to session authority)",
1527
+ )
1528
+ .option("--json", "Machine-readable content-free recovery receipt")
1529
+ .action((id, options) => {
1530
+ process.exitCode = runAction(
1531
+ () => recoverSessionExecutionLocationResultApply(id, options, deps),
1532
+ options,
1533
+ );
1534
+ });
587
1535
  }