chainlesschain 0.163.8 → 0.165.1

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 (240) hide show
  1. package/package.json +7 -4
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/.build-hash +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-CYxFDrcm.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-CPBtdiU2.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Dayq7Dp7.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-6U7bPb2s.js} +4 -4
  10. package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-D2Iqg_3D.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-CdoOB7WV.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-DrnAVB8w.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-CesMi5cy.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-DaX9ptax.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-OrwOPxDS.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-CvPZFRxM.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-DiHbcysC.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-CbgCkaBJ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-Du5hgrh4.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-DsPOBW-p.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-BwHIFkNC.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-BvrDQSgd.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-gwAE6arx.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DW-0l4uF.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-j-NsLesB.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-CibVEBOI.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-W4z9vSfe.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-DAcrkKxG.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-6GXah-89.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-TKDCq8Ku.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BXBLlcNm.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-BoJJBkG3.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-okjsl46v.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-Rvs7i6nn.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-CHSUxXXS.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-V3BlfxsB.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-C_NlD4aR.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-Nn4LNxhA.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-DEmjFcg-.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-DlopXipI.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-BG3ynX60.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-DeRzWOfT.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-DlPwcCbq.js → MobileProjects-Tyd3o2A0.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-BoPbOv1C.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-un-rTHp7.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Ds0oveEB.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-D09JI-yY.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-DTRhiKJn.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-BAnnNCim.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-Yr-1fSYi.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-S9EAolpj.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-CqcLKqJ8.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-Dw0F9EcU.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BDRwUevN.js} +5 -5
  56. package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-D3_c3nKB.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-CxdMV98x.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-CgjNQFLI.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-BHghIIht.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-De6pqaKM.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-Bg4ZkNYQ.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-CUnHbNf-.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-DA2f3Wts.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-C1FeHDqp.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-B5guaUMN.js} +1 -1
  67. package/src/assets/web-panel/assets/RemoteSession-PDADSds3.js +5 -0
  68. package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-eTlRhgvK.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-D7AqSGY0.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-JiuLm4Ja.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-CwruahW3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-CdhqaR0b.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-CU0ZIlcT.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-CtduPfAb.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CROXm6AY.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-DiZiABFD.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-B5pLcXUw.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-DBX6J1Oe.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-BLyRJd3-.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-BKa5qzmk.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-DnD3a4M6.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-DEitQeTb.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-CjHggTDq.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-CsGT7sfl.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-yr4rFDrW.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-CLvu1Sjp.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-B0m7yUP8.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-C0VvP4lc.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-kllBAG1M.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-C54UQNLx.js} +3 -3
  91. package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B7y8qSvU.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-DRzTh8CJ.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-BSMwSnCx.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-BTg602H5.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-B6EGsdvp.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-DDKqJ8RD.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-323Hhxxt.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-BICn3Qh1.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-BMuGd2--.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-BRqt4fO-.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-BVTAl5N2.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-BsR7Y2NG.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-Bx044qDj.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-C1GFfuqN.js} +1 -1
  106. package/src/assets/web-panel/assets/index-C3QX5tOl.js +1 -0
  107. package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-C66NpWy5.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-CDTvsX8t.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-CGNklbP6.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-CHfLYwcW.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-CNxg61YP.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-CQlHFN_g.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-CUEU48o1.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-CWGax2QW.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-C_JzIXUq.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-Cf23wVMs.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-CmAInUkX.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-CmAubjDi.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-Co7oM1qr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-CwPUZbMI.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-D1naNj4U.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-D5CsBShd.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DBT3YeQ9.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-DLdrHhML.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-Dc77VR3H.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Dfv2lKu3.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index-DiW0sDkz.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-DpTHIRfZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-DqFXGzzC.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-XFe-1twF.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-p2HYn89m.js} +3 -3
  132. package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-pqfux8vZ.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-pPL66J85.js → index-rjzk9z1Q.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-th2ihDc0.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-u2YVld9W.js} +1 -1
  136. package/src/assets/web-panel/assets/index-xYybvEic.js +1 -0
  137. package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-C3Djh9fa.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-BzqFmbSe.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-DJo_FFaW.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-_tlTiBvk.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-CB2ZyxUg.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DZwIFD4u.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-DxZY0dgk.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-CzzGt7GL.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-BaIK52yz.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-3-FHu9_M.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-BkRT68fK.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-DHYwKS-s.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-DVVUhV8p.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-CkrFKAzQ.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-BuBLFz0c.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-kpm6LtXU.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +3 -3
  155. package/src/commands/cowork.js +418 -41
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/data/changelog.json +28 -2
  161. package/src/gateways/ws/action-protocol.js +316 -17
  162. package/src/gateways/ws/message-dispatcher.js +30 -0
  163. package/src/gateways/ws/remote-session-protocol.js +565 -35
  164. package/src/gateways/ws/ws-agent-handler.js +12 -0
  165. package/src/gateways/ws/ws-approval-gate.js +5 -0
  166. package/src/gateways/ws/ws-server.js +510 -50
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +2 -0
  170. package/src/harness/remote-session-crypto.js +929 -21
  171. package/src/harness/remote-session-registry.js +945 -24
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/auto-mode-config.js +98 -3
  175. package/src/lib/background-agent-keeper-client.js +248 -0
  176. package/src/lib/background-agent-keeper-protocol.js +291 -0
  177. package/src/lib/background-agent-supervisor.js +1357 -85
  178. package/src/lib/background-interaction-resolver.js +12 -0
  179. package/src/lib/background-session-transport.js +23 -6
  180. package/src/lib/background-turn-bootstrap-protocol.js +190 -0
  181. package/src/lib/cowork-workflow.js +1188 -76
  182. package/src/lib/delivery-production-adapter.js +38 -2
  183. package/src/lib/dynamic-workflow-facade.js +1736 -0
  184. package/src/lib/execution-location-contract.js +551 -0
  185. package/src/lib/execution-location-runtime.js +130 -0
  186. package/src/lib/ide-context.js +94 -6
  187. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  188. package/src/lib/packer/pkg-config-generator.js +2 -0
  189. package/src/lib/permission-authority.js +77 -0
  190. package/src/lib/permission-side-effect-center.js +495 -0
  191. package/src/lib/plugin-runtime/install.js +514 -13
  192. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  193. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  194. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  195. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  196. package/src/lib/plugin-security.js +60 -3
  197. package/src/lib/process-execution-broker/index.js +1095 -57
  198. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  199. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  200. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  201. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  202. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  203. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  204. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  205. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  206. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  207. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  208. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  209. package/src/lib/public-ide-capability-manifest.js +3 -0
  210. package/src/lib/remote-approval-bridge.js +777 -34
  211. package/src/lib/remote-control.js +2 -0
  212. package/src/lib/remote-membership-authority.js +632 -0
  213. package/src/lib/remote-membership-coordinator.js +2973 -0
  214. package/src/lib/remote-membership-host-store.js +1799 -0
  215. package/src/lib/runtime-provenance-ledger.js +171 -46
  216. package/src/lib/scoped-permission-store.js +369 -0
  217. package/src/lib/session-anti-rollback-anchor.js +262 -5
  218. package/src/lib/shell-approval.js +169 -6
  219. package/src/lib/sub-agent-context.js +4 -0
  220. package/src/lib/with-file-lock.js +73 -38
  221. package/src/lib/workflow-definition-contract.js +149 -0
  222. package/src/repl/agent-repl.js +111 -36
  223. package/src/repl/chat-repl.js +2 -0
  224. package/src/repl/clipboard-image.js +735 -16
  225. package/src/repl/ide-status.js +1 -1
  226. package/src/repl/prompt-interactions.js +59 -6
  227. package/src/repl/remote-approval.js +29 -7
  228. package/src/runtime/agent-core.js +1182 -155
  229. package/src/runtime/headless-runner.js +52 -30
  230. package/src/runtime/headless-stream.js +51 -28
  231. package/src/workers/background-agent-keeper.js +689 -0
  232. package/src/workers/background-agent-worker.js +365 -13
  233. package/src/workers/background-turn-bootstrap.js +170 -0
  234. package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
  235. package/src/assets/web-panel/assets/OrderTableRenderer-Bb1O3Ofr.js +0 -1
  236. package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
  237. package/src/assets/web-panel/assets/RemoteSession-Biyn2-Ro.js +0 -5
  238. package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
  239. package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
  240. package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
@@ -35,6 +35,17 @@ export const SESSION_ANTI_ROLLBACK_DETECTED_CODE =
35
35
  export const SESSION_ANTI_ROLLBACK_UNAVAILABLE_CODE =
36
36
  "CC_SESSION_ANTI_ROLLBACK_UNAVAILABLE";
37
37
 
38
+ // Test-only seams for deterministic durability failures. Production callers
39
+ // never assign these hooks; keeping them immediately before the two fsync
40
+ // boundaries lets tests exercise the real append and rollback path without
41
+ // replacing node:fs for the namespace or lock stores.
42
+ export const _sessionAntiRollbackFaultHooks = Object.seal({
43
+ afterRecordOpen: null,
44
+ beforeRecordFsync: null,
45
+ beforeRecordDirectoryFsync: null,
46
+ beforeRecordRollback: null,
47
+ });
48
+
38
49
  const NAMESPACE_VERSION = 1;
39
50
  const ANCHOR_SCHEMA = "chainlesschain.session-anti-rollback-anchor/v1";
40
51
  const GENERATION_SCHEMA = "chainlesschain.session-generation-authority/v1";
@@ -59,12 +70,19 @@ function anchorError(code, message, cause = null, details = {}) {
59
70
 
60
71
  function unavailable(cause, filePath = null) {
61
72
  if (cause?.code === SESSION_ANTI_ROLLBACK_DETECTED_CODE) return cause;
62
- return anchorError(
73
+ const error = anchorError(
63
74
  SESSION_ANTI_ROLLBACK_UNAVAILABLE_CODE,
64
75
  "Session anti-rollback witness is unavailable; canonical session access is denied",
65
76
  cause,
66
77
  filePath ? { filePath } : {},
67
78
  );
79
+ for (const key of ["commitState", "rollbackState", "persistenceTarget"]) {
80
+ if (cause?.[key] != null) error[key] = cause[key];
81
+ }
82
+ if (cause?.rollbackCause) {
83
+ error.rollbackErrorCode = cause.rollbackCause?.code || null;
84
+ }
85
+ return error;
68
86
  }
69
87
 
70
88
  function rollback(sessionId, message, current = null, candidate = null) {
@@ -628,11 +646,173 @@ function appendRecord(location, record) {
628
646
  return appendRecordAtPath(location.recordPath, record, null);
629
647
  }
630
648
 
649
+ function settleExistingRecord(location, record) {
650
+ if (isAffectedWindowsZeroDeviceStatRuntime()) {
651
+ return withTrustedFileParentSync(
652
+ fs,
653
+ location.recordPath,
654
+ ({ canonicalPath, parentDevice }) =>
655
+ settleExistingRecordAtPath(canonicalPath, record, parentDevice),
656
+ );
657
+ }
658
+ return settleExistingRecordAtPath(location.recordPath, record, null);
659
+ }
660
+
661
+ function runFaultHook(name, payload) {
662
+ if (process.env.CC_SESSION_ANTI_ROLLBACK_FAULT_INJECTION !== "1") return;
663
+ const hook = _sessionAntiRollbackFaultHooks[name];
664
+ if (typeof hook === "function") hook(payload);
665
+ }
666
+
667
+ function fsyncDirectory(directory) {
668
+ const descriptor = fs.openSync(directory, "r");
669
+ try {
670
+ fs.fsyncSync(descriptor);
671
+ } finally {
672
+ fs.closeSync(descriptor);
673
+ }
674
+ }
675
+
676
+ function settleExistingRecordAtPath(recordPath, record, parentDevice) {
677
+ let descriptor = null;
678
+ try {
679
+ let flags = fs.constants.O_RDWR;
680
+ if (typeof fs.constants.O_NOFOLLOW === "number") {
681
+ flags |= fs.constants.O_NOFOLLOW;
682
+ }
683
+ descriptor = fs.openSync(recordPath, flags);
684
+ const opened = fs.fstatSync(descriptor, { bigint: true });
685
+ const published = fs.lstatSync(recordPath, { bigint: true });
686
+ const identityMatches =
687
+ parentDevice === null
688
+ ? String(opened.dev) === String(published.dev) &&
689
+ String(opened.ino) === String(published.ino)
690
+ : samePathHandleStableFileIdentity(published, opened, parentDevice);
691
+ if (
692
+ !opened.isFile() ||
693
+ published.isSymbolicLink() ||
694
+ !published.isFile() ||
695
+ !identityMatches
696
+ ) {
697
+ throw new Error("session anti-rollback record identity changed");
698
+ }
699
+ runFaultHook("beforeRecordFsync", {
700
+ recordPath,
701
+ record,
702
+ createsRecord: false,
703
+ unchanged: true,
704
+ });
705
+ fs.fsyncSync(descriptor);
706
+ const after = fs.lstatSync(recordPath, { bigint: true });
707
+ const afterIdentityMatches =
708
+ parentDevice === null
709
+ ? String(opened.dev) === String(after.dev) &&
710
+ String(opened.ino) === String(after.ino)
711
+ : samePathHandleStableFileIdentity(after, opened, parentDevice);
712
+ if (after.isSymbolicLink() || !after.isFile() || !afterIdentityMatches) {
713
+ throw new Error("session anti-rollback record identity changed");
714
+ }
715
+ // A complete revision-1 line can survive a process death before either
716
+ // the file fsync or the first directory-entry barrier. Replaying the exact
717
+ // candidate must settle both boundaries before reporting success.
718
+ if (record.revision === "1" && process.platform !== "win32") {
719
+ runFaultHook("beforeRecordDirectoryFsync", {
720
+ recordPath,
721
+ record,
722
+ createsRecord: false,
723
+ recoveredCompleteRecord: true,
724
+ });
725
+ fsyncDirectory(path.dirname(recordPath));
726
+ }
727
+ } catch (cause) {
728
+ if (cause && typeof cause === "object" && !cause.commitState) {
729
+ cause.commitState = "unknown";
730
+ cause.rollbackState = "not-required";
731
+ cause.persistenceTarget = recordPath;
732
+ }
733
+ throw cause;
734
+ } finally {
735
+ if (descriptor !== null) fs.closeSync(descriptor);
736
+ }
737
+ }
738
+
739
+ function rollbackRecordAppend({
740
+ recordPath,
741
+ opened,
742
+ initialSize,
743
+ createsRecord,
744
+ parentDevice,
745
+ }) {
746
+ runFaultHook("beforeRecordRollback", {
747
+ recordPath,
748
+ initialSize,
749
+ createsRecord,
750
+ });
751
+ let descriptor = null;
752
+ try {
753
+ let flags = fs.constants.O_RDWR;
754
+ if (typeof fs.constants.O_NOFOLLOW === "number") {
755
+ flags |= fs.constants.O_NOFOLLOW;
756
+ }
757
+ descriptor = fs.openSync(recordPath, flags);
758
+ const rollbackOpened = fs.fstatSync(descriptor, { bigint: true });
759
+ const published = fs.lstatSync(recordPath, { bigint: true });
760
+ const identityMatches =
761
+ !published.isSymbolicLink() &&
762
+ published.isFile() &&
763
+ String(opened.dev) === String(rollbackOpened.dev) &&
764
+ String(opened.ino) === String(rollbackOpened.ino) &&
765
+ (parentDevice === null
766
+ ? String(rollbackOpened.dev) === String(published.dev) &&
767
+ String(rollbackOpened.ino) === String(published.ino)
768
+ : samePathHandleStableFileIdentity(
769
+ published,
770
+ rollbackOpened,
771
+ parentDevice,
772
+ ));
773
+ if (!identityMatches) {
774
+ throw new Error("session anti-rollback rollback record identity changed");
775
+ }
776
+ fs.ftruncateSync(descriptor, initialSize);
777
+ fs.fsyncSync(descriptor);
778
+ } finally {
779
+ if (descriptor !== null) fs.closeSync(descriptor);
780
+ }
781
+ if (createsRecord) {
782
+ fs.unlinkSync(recordPath);
783
+ if (process.platform !== "win32") {
784
+ fsyncDirectory(path.dirname(recordPath));
785
+ }
786
+ }
787
+ }
788
+
789
+ function rollbackEmptyCreatedRecord(recordPath) {
790
+ const published = fs.lstatSync(recordPath, { bigint: true });
791
+ if (
792
+ published.isSymbolicLink() ||
793
+ !published.isFile() ||
794
+ published.size !== 0n
795
+ ) {
796
+ throw new Error(
797
+ "session anti-rollback unverified first record cannot be removed",
798
+ );
799
+ }
800
+ fs.unlinkSync(recordPath);
801
+ if (process.platform !== "win32") {
802
+ fsyncDirectory(path.dirname(recordPath));
803
+ }
804
+ }
805
+
631
806
  function appendRecordAtPath(recordPath, record, parentDevice) {
632
807
  let descriptor = null;
808
+ let recordOpened = false;
809
+ let createsRecord = false;
810
+ let requiresDirectoryPublication = false;
811
+ let initialSize = 0;
812
+ let opened = null;
633
813
  try {
634
814
  let flags = fs.constants.O_WRONLY | fs.constants.O_APPEND;
635
- const createsRecord = !fs.existsSync(recordPath);
815
+ createsRecord = !fs.existsSync(recordPath);
636
816
  if (createsRecord) {
637
817
  flags |= fs.constants.O_CREAT | fs.constants.O_EXCL;
638
818
  }
@@ -640,7 +820,18 @@ function appendRecordAtPath(recordPath, record, parentDevice) {
640
820
  flags |= fs.constants.O_NOFOLLOW;
641
821
  }
642
822
  descriptor = fs.openSync(recordPath, flags, 0o600);
643
- const opened = fs.fstatSync(descriptor, { bigint: true });
823
+ recordOpened = true;
824
+ runFaultHook("afterRecordOpen", { recordPath, record, createsRecord });
825
+ opened = fs.fstatSync(descriptor, { bigint: true });
826
+ if (!opened.isFile()) {
827
+ throw new Error("session anti-rollback append target is not a file");
828
+ }
829
+ initialSize = Number(opened.size);
830
+ // A previous process can die immediately after O_CREAT|O_EXCL and leave a
831
+ // visible zero-byte entry before its parent-directory fsync. Treat that
832
+ // exact crash residue like a first publication: the retry must flush the
833
+ // directory entry after it writes and fsyncs revision 1.
834
+ requiresDirectoryPublication = createsRecord || opened.size === 0n;
644
835
  const payload = Buffer.from(`${JSON.stringify(record)}\n`, "utf8");
645
836
  let offset = 0;
646
837
  while (offset < payload.length) {
@@ -657,6 +848,11 @@ function appendRecordAtPath(recordPath, record, parentDevice) {
657
848
  }
658
849
  offset += written;
659
850
  }
851
+ runFaultHook("beforeRecordFsync", {
852
+ recordPath,
853
+ record,
854
+ createsRecord,
855
+ });
660
856
  fs.fsyncSync(descriptor);
661
857
  const published = fs.lstatSync(recordPath, { bigint: true });
662
858
  const identityMatches =
@@ -667,14 +863,64 @@ function appendRecordAtPath(recordPath, record, parentDevice) {
667
863
  if (published.isSymbolicLink() || !published.isFile() || !identityMatches) {
668
864
  throw new Error("session anti-rollback record identity changed");
669
865
  }
670
- if (createsRecord && process.platform !== "win32") {
866
+ if (requiresDirectoryPublication && process.platform !== "win32") {
671
867
  const directoryDescriptor = fs.openSync(path.dirname(recordPath), "r");
672
868
  try {
869
+ runFaultHook("beforeRecordDirectoryFsync", {
870
+ recordPath,
871
+ record,
872
+ createsRecord,
873
+ recoveredEmptyRecord: !createsRecord,
874
+ });
673
875
  fs.fsyncSync(directoryDescriptor);
674
876
  } finally {
675
877
  fs.closeSync(directoryDescriptor);
676
878
  }
677
879
  }
880
+ } catch (cause) {
881
+ // A completed JSON line is immediately readable even when its fsync (or a
882
+ // first-record directory fsync) reports failure. Best-effort rollback to
883
+ // the pre-append byte boundary prevents that unacknowledged record from
884
+ // becoming the next readback authority in the still-running process. If
885
+ // this was the first record, remove the empty entry and durably publish
886
+ // that removal on POSIX so a retry recreates and flushes the entry again.
887
+ try {
888
+ if (descriptor !== null) {
889
+ fs.closeSync(descriptor);
890
+ descriptor = null;
891
+ }
892
+ if (opened !== null) {
893
+ rollbackRecordAppend({
894
+ recordPath,
895
+ opened,
896
+ initialSize,
897
+ createsRecord,
898
+ parentDevice,
899
+ });
900
+ } else if (recordOpened && createsRecord) {
901
+ rollbackEmptyCreatedRecord(recordPath);
902
+ }
903
+ if (cause && typeof cause === "object") {
904
+ cause.commitState = "not-committed";
905
+ cause.rollbackState = "restored";
906
+ cause.persistenceTarget = recordPath;
907
+ }
908
+ } catch (rollbackCause) {
909
+ if (cause && typeof cause === "object") {
910
+ cause.rollbackCause = rollbackCause;
911
+ cause.commitState = "unknown";
912
+ cause.rollbackState = "failed";
913
+ cause.persistenceTarget = recordPath;
914
+ }
915
+ }
916
+ if (cause && typeof cause === "object" && !cause.commitState) {
917
+ // open/fstat failures happen before any payload write. A successfully
918
+ // opened first entry is removed above before reporting this state.
919
+ cause.commitState = "not-committed";
920
+ cause.rollbackState = "not-required";
921
+ cause.persistenceTarget = recordPath;
922
+ }
923
+ throw cause;
678
924
  } finally {
679
925
  if (descriptor !== null) fs.closeSync(descriptor);
680
926
  }
@@ -708,7 +954,18 @@ export function publishSessionAntiRollbackAnchor(
708
954
  current.headHash === candidate.headHash &&
709
955
  current.eventCount === candidate.eventCount &&
710
956
  current.deletedAtMs === candidate.deletedAtMs;
711
- if (unchanged) return current;
957
+ // Revision 1 is the only record that can carry an unsettled first
958
+ // directory entry. Settle it before either acknowledging an exact
959
+ // replay or advancing directly to a proven successor.
960
+ if (current?.revision === "1") {
961
+ settleExistingRecord(location, current);
962
+ }
963
+ if (unchanged) {
964
+ if (current.revision !== "1") {
965
+ settleExistingRecord(location, current);
966
+ }
967
+ return current;
968
+ }
712
969
  if (current === null) ensureNamespaceEntry(location);
713
970
  const core = recordCore(
714
971
  location,
@@ -32,6 +32,129 @@ import {
32
32
  resolveInstallPolicy,
33
33
  } from "./install-command-policy.js";
34
34
 
35
+ const SHELL_EXECUTION_DESCRIPTOR_VERSION =
36
+ "chainlesschain.shell-execution-descriptor/v1";
37
+
38
+ function deepFreezeData(value, seen = new WeakSet()) {
39
+ if (!value || typeof value !== "object" || Object.isFrozen(value))
40
+ return value;
41
+ if (seen.has(value)) return value;
42
+ seen.add(value);
43
+ for (const child of Object.values(value)) deepFreezeData(child, seen);
44
+ return Object.freeze(value);
45
+ }
46
+
47
+ function cloneData(value, label) {
48
+ try {
49
+ return structuredClone(value);
50
+ } catch (cause) {
51
+ throw new Error(`${label} must be structured-cloneable`, { cause });
52
+ }
53
+ }
54
+
55
+ /** Capture only the declared run_shell data contract and freeze it. */
56
+ export function snapshotShellExecutionArgs(args = {}, fallbackCommand = null) {
57
+ const source = args && typeof args === "object" ? args : {};
58
+ const snapshot = {
59
+ command:
60
+ source.command !== undefined
61
+ ? cloneData(source.command, "command")
62
+ : cloneData(fallbackCommand ?? null, "command"),
63
+ };
64
+ for (const key of ["cwd", "shell", "run_in_background", "timeout"]) {
65
+ if (source[key] !== undefined) snapshot[key] = cloneData(source[key], key);
66
+ }
67
+ return deepFreezeData(snapshot);
68
+ }
69
+
70
+ /**
71
+ * Build the bounded, secret-free data tuple shown to ApprovalGate and later
72
+ * consumed at dispatch. Runtime objects/callbacks never enter this descriptor.
73
+ */
74
+ export function createShellExecutionDescriptor({
75
+ args,
76
+ workspace = null,
77
+ shellInvocation = null,
78
+ pluginInvocation = null,
79
+ pluginSandboxPolicy = null,
80
+ pluginSandboxExecutionContract = null,
81
+ sandbox = null,
82
+ environmentRef = null,
83
+ } = {}) {
84
+ const shellArgs = snapshotShellExecutionArgs(args);
85
+ const descriptor = {
86
+ ...shellArgs,
87
+ execution: {
88
+ version: SHELL_EXECUTION_DESCRIPTOR_VERSION,
89
+ mode: shellArgs.run_in_background === true ? "background" : "foreground",
90
+ workspace: workspace || null,
91
+ shell: shellInvocation
92
+ ? {
93
+ kind: shellInvocation.kind || null,
94
+ useDefaultShell: shellInvocation.useDefaultShell === true,
95
+ file: shellInvocation.file || null,
96
+ argv: Array.isArray(shellInvocation.argv)
97
+ ? [...shellInvocation.argv]
98
+ : [],
99
+ }
100
+ : null,
101
+ plugin: pluginInvocation
102
+ ? {
103
+ command: pluginInvocation.command || null,
104
+ id: pluginInvocation.pluginId || null,
105
+ version: pluginInvocation.pluginVersion || null,
106
+ source: pluginInvocation.pluginSource || null,
107
+ bin: pluginInvocation.binName || null,
108
+ path: pluginInvocation.binPath || null,
109
+ runtime: pluginInvocation.runtime || null,
110
+ argv: Array.isArray(pluginInvocation.args)
111
+ ? [...pluginInvocation.args]
112
+ : [],
113
+ executableSha256:
114
+ pluginInvocation.executableIdentity?.sha256 || null,
115
+ sandboxPolicy: pluginSandboxPolicy
116
+ ? cloneData(pluginSandboxPolicy, "pluginSandboxPolicy")
117
+ : null,
118
+ sandboxExecution: pluginSandboxExecutionContract
119
+ ? {
120
+ version:
121
+ pluginSandboxExecutionContract.contractVersion || null,
122
+ kind: pluginSandboxExecutionContract.kind || null,
123
+ pluginRoot: pluginSandboxExecutionContract.pluginRoot || null,
124
+ workingDirectory:
125
+ pluginSandboxExecutionContract.workingDirectory || null,
126
+ runtimePath:
127
+ pluginSandboxExecutionContract.runtimePath || null,
128
+ entrySha256:
129
+ pluginSandboxExecutionContract.entryIdentity?.sha256 ||
130
+ null,
131
+ runtimeSha256:
132
+ pluginSandboxExecutionContract.runtimeIdentity?.sha256 ||
133
+ null,
134
+ }
135
+ : null,
136
+ }
137
+ : null,
138
+ sandbox: sandbox ? cloneData(sandbox, "sandbox") : null,
139
+ environment: environmentRef
140
+ ? cloneData(environmentRef, "environmentRef")
141
+ : null,
142
+ },
143
+ };
144
+ return deepFreezeData(descriptor);
145
+ }
146
+
147
+ export function shellApprovalAction(riskLevel) {
148
+ return riskLevel ? `${riskLevel}-risk` : null;
149
+ }
150
+
151
+ export function commitShellApprovalSideEffects(result) {
152
+ const audit = result?.installAudit || null;
153
+ if (!audit) return false;
154
+ recordInstallCommandAudit(audit.entry, audit.options || {});
155
+ return true;
156
+ }
157
+
35
158
  export const SHELL_TO_RISK = {
36
159
  allow: RISK.LOW,
37
160
  warn: RISK.MEDIUM,
@@ -41,10 +164,16 @@ export const SHELL_TO_RISK = {
41
164
 
42
165
  export async function evaluateShellCommandWithApproval({
43
166
  command,
167
+ args = null,
44
168
  sessionId = null,
45
169
  approvalGate = null,
46
170
  shellPolicyOptions = {},
47
171
  installPolicy = null,
172
+ workspace = null,
173
+ targetEnv = null,
174
+ policyEnv = process.env,
175
+ policyVersion = null,
176
+ deferSideEffects = false,
48
177
  } = {}) {
49
178
  const shellPolicy = sharedShellPolicy.evaluateShellCommandPolicy(
50
179
  command,
@@ -62,8 +191,9 @@ export async function evaluateShellCommandWithApproval({
62
191
  // CC_INSTALL_RISK_FLOOR) so the real run_shell path picks it up with no extra
63
192
  // wiring. Both unset → disabled → the block below is skipped, byte-unchanged.
64
193
  const effectiveInstallPolicy =
65
- installPolicy || resolveInstallPolicy({ env: process.env });
194
+ installPolicy || resolveInstallPolicy({ env: policyEnv });
66
195
  let install = null;
196
+ let installAudit = null;
67
197
  if (effectiveInstallPolicy && effectiveInstallPolicy.enabled) {
68
198
  const cls = classifyCodeAcquisition(command);
69
199
  if (cls.flagged) {
@@ -72,8 +202,8 @@ export async function evaluateShellCommandWithApproval({
72
202
  riskLevel = applyRiskFloor(riskLevel, effectiveInstallPolicy.riskFloor);
73
203
  }
74
204
  if (effectiveInstallPolicy.audit) {
75
- recordInstallCommandAudit(
76
- {
205
+ installAudit = {
206
+ entry: {
77
207
  command,
78
208
  shellDecision: shellPolicy.decision,
79
209
  riskLevel,
@@ -82,8 +212,12 @@ export async function evaluateShellCommandWithApproval({
82
212
  global: hasGlobalInstall(cls),
83
213
  sessionId,
84
214
  },
85
- effectiveInstallPolicy.auditOpts || {},
86
- );
215
+ options: effectiveInstallPolicy.auditOpts || {},
216
+ };
217
+ if (!deferSideEffects) {
218
+ recordInstallCommandAudit(installAudit.entry, installAudit.options);
219
+ installAudit = null;
220
+ }
87
221
  }
88
222
  }
89
223
  }
@@ -100,6 +234,7 @@ export async function evaluateShellCommandWithApproval({
100
234
  riskLevel,
101
235
  policy: null,
102
236
  install,
237
+ installAudit,
103
238
  };
104
239
  }
105
240
 
@@ -114,14 +249,29 @@ export async function evaluateShellCommandWithApproval({
114
249
  riskLevel,
115
250
  policy: null,
116
251
  install,
252
+ installAudit,
117
253
  };
118
254
  }
119
255
 
256
+ const operationArgs = args
257
+ ? Object.isFrozen(args)
258
+ ? args
259
+ : deepFreezeData(cloneData(args, "run_shell approval args"))
260
+ : snapshotShellExecutionArgs({ command });
261
+ const effectivePolicyVersion =
262
+ typeof policyVersion === "string" && policyVersion
263
+ ? policyVersion
264
+ : `shell-policy:${shellPolicy.decision}:${shellPolicy.ruleId || "none"}`;
265
+ const action = shellApprovalAction(riskLevel);
120
266
  const gateResult = await approvalGate.decide({
121
267
  sessionId,
122
268
  riskLevel,
123
269
  tool: "run_shell",
124
- args: { command },
270
+ args: operationArgs,
271
+ cwd: workspace,
272
+ targetEnv,
273
+ policyVersion: effectivePolicyVersion,
274
+ action,
125
275
  });
126
276
 
127
277
  return {
@@ -133,6 +283,19 @@ export async function evaluateShellCommandWithApproval({
133
283
  riskLevel,
134
284
  policy: gateResult.policy,
135
285
  install,
286
+ installAudit,
287
+ authorization: gateResult.authorization || null,
288
+ authorizationContext: gateResult.authorization
289
+ ? {
290
+ tool: "run_shell",
291
+ action,
292
+ args: operationArgs,
293
+ workspace,
294
+ session: sessionId,
295
+ targetEnv,
296
+ policyVersion: effectivePolicyVersion,
297
+ }
298
+ : null,
136
299
  // Explainability passthrough (autoMode.decisions wrapper attaches these):
137
300
  // which gate rule fired and why — surfaced in the permission chain.
138
301
  gateReason: gateResult.reason ?? null,
@@ -323,6 +323,7 @@ export class SubAgentContext {
323
323
  // parent's policy, Plan lock, workspace sandbox, or unattended boundary.
324
324
  this._parentAuthority = Object.freeze({
325
325
  permissionRules: options.permissionRules || null,
326
+ permissionRulesProvider: options.permissionRulesProvider || null,
326
327
  hostManagedToolPolicy: options.hostManagedToolPolicy || null,
327
328
  planManager: options.planManager || null,
328
329
  sandbox: options.sandbox || null,
@@ -618,6 +619,9 @@ export class SubAgentContext {
618
619
  if (authority.permissionRules) {
619
620
  options.permissionRules = authority.permissionRules;
620
621
  }
622
+ if (authority.permissionRulesProvider) {
623
+ options.permissionRulesProvider = authority.permissionRulesProvider;
624
+ }
621
625
  if (authority.hostManagedToolPolicy) {
622
626
  options.hostManagedToolPolicy = authority.hostManagedToolPolicy;
623
627
  }