chainlesschain 0.166.81 → 0.166.83

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 (189) hide show
  1. package/package.json +1 -1
  2. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  3. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BZPs-bVl.js → AIOps-D5a4i3N7.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-BP1iLSwn.js → ActionButton-DxsRk5n1.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-WxwtPqcd.js → Analytics-D-7EvH4S.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-DvcgeNkP.js → AppLayout-DDEWVr-d.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CtYGOtnT.js → Artifacts-CAlJAjRB.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-BBzFYWMk.js → Audit-tuaWDOAM.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-Dl9wCt0Y.js → BackgroundAgents-CIwRFJ50.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-CAL13Eak.js → Backup-CpBepJlH.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-f_lncpU_.js → BaseInput-eKguCzQc.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-DLEbkiqI.js → Chat-CFrUfXDV.js} +4 -4
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-1tCmIvv1.js → ChatBubbleRenderer-DaRtY87l.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-SNvgd2UG.js → Checkbox-o5FEn6a1.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-BG0D-INl.js → Codegen-Dih8HogC.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-DUBBZz0e.js → Col-D5r-6WZe.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-8LfuBDPs.js → Community-jeQ6bGey.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-GWs7Ka6o.js → Compact-CEP7QsWp.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CXRhB-KC.js → Compliance-B8NydOHd.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-OpW8dLKg.js → Cowork-Bmi1zuPy.js} +2 -2
  22. package/src/assets/web-panel/assets/{Cron-6e47Syc_.js → Cron-BAL9bwSp.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-D-vGH4nC.js → Crosschain-D8WUi2dS.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-zEIa2jNx.js → DID-CQCkYcLY.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-BfUbZxsl.js → Dashboard-DogXg6kh.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BeCD8gf0.js → Dropdown-BJBJyQJn.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-apOBM2r2.js → EmailListRenderer-CxPWquJx.js} +1 -1
  28. package/src/assets/web-panel/assets/{EvolutionSettings-C2dK36po.js → EvolutionSettings-BijH1x8G.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DPMLWPTR.js → FamilyGuardDashboard-DStwf-00.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-CivI2pzm.js → Federation-LU9_sNxC.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-B3zrwBDw.js → FormItemContext-DNfWhj7P.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-jGgdcPck.js → GenericCardRenderer-DWYsPjzk.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-Cpfkrasd.js → Git-CA0O9ulB.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-DG8_7YS3.js → Governance-ECShL7BJ.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-TQgUqPXx.js → Inference-9GA2542e.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-By657fHZ.js → KnowledgeGraph-nC5mTbEH.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-CFJ_70-E.js → Logs-B7IqgnDy.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-BqlqrJkY.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-BWC3xler.js → Marketplace-CEr0suM8.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-B0NkUzeJ.js → McpTools-DhTPQKOE.js} +3 -3
  41. package/src/assets/web-panel/assets/{Memory-DBnXwjWD.js → Memory-mHRZP1w4.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-BNWDrEJ4.js → MobileBridge-BNfX6Rdo.js} +1 -1
  43. package/src/assets/web-panel/assets/{MobileProjects-BaE94B_N.js → MobileProjects-8zG8f5li.js} +1 -1
  44. package/src/assets/web-panel/assets/{Mtc-Bp3OAEYb.js → Mtc-CzkV3wsn.js} +5 -5
  45. package/src/assets/web-panel/assets/{MtcAudit-_1T24zO3.js → MtcAudit-DWYljJik.js} +4 -4
  46. package/src/assets/web-panel/assets/{Multisig-C2i6Yi0B.js → Multisig-kHgtvZY_.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-CBq3ujGE.js → NLProgramming-56uQiPiY.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-BxRmci_W.js → Notes-DxGOZqRf.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-CqBLgOdv.js → NotificationSettings-DabaCpmo.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-cODPlpK7.js → OrderTableRenderer-SzeQNlGT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-DlTnQBlp.js → Organization-D9gnPpK2.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-Df2jS2Ep.js → Overflow-Cqp_bXm4.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BwieT0aA.js → P2P-DTeK-r0G.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-Btw816xR.js → PdhVaultBrowser-CsjG85GT.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-BhVYLcqT.js → Permissions-B4ofZq3j.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-CPbNKPCA.js → PersonalDataHub-Cvas5cYd.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-B1BuhoY3.js → Pipeline-Er3wmAew.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-BWeikVbU.js → Privacy-DMFYeZox.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-BVXcimHE.js → ProjectInit-DaVaYPy0.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-CX87x3rT.js → ProjectSettings-dPx5q2Ac.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-N0JNeCui.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-CGm0Wuer.js → Providers-BPQo_gQa.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-DJxv7J64.js → QrScannerModal-CD-sEsWh.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-DOXBReRk.js → QuickAsk-LOKRJiN_.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend--MiLwmLM.js → Recommend-BwPXqcWy.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-D6LoXH94.js → RemoteSession-BjotndxF.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-G2jToiqh.js → Reputation-BlZ2gcbU.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-B79ZV_lZ.js → Row-D399HM-d.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CHQN68w_.js → RssFeed-C7H-ibnY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Search-j7v5S2Fa.js → Search-CNHCVmM1.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-B2ykFZJH.js → Security-C70eDGYY.js} +3 -3
  72. package/src/assets/web-panel/assets/{Services-H8BK8uX0.js → Services-6xfq9G-H.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-XEUUrOTK.js → Skeleton-BbY2zeZV.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-B387UJPk.js → Skills-DYtyZ7_6.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-CWWBujpe.js → Sla-CkWcl5OH.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-Q2AOv9DV.js → SpeechSettings-CiknYk2P.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-OSNyOUr8.js → SyncSettings-D-8JVip4.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-DfUDrno5.js → Tasks-B2KnR9XC.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-CSTkzDRS.js → Templates-CipXkOE-.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-BR__gCTG.js → Tenant-DbwgIMmx.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-Bv4DM5OI.js → Terminal-OtCriHEE.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-DUnZuAtn.js → TimelineRenderer-B9LU5qrl.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-Dm0sczRV.js → Tokens-B4iFVxvH.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-DsSOp0Ob.js → Trigger-BegM2v8q.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-C0HJtFwV.js → Trust-COkqnnFj.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-BbqIZiX-.js → UkeySign-BzqKPChj.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-D7dDTt3D.js → VideoEditing-D-F2XL3C.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-DJGu0KWq.js → Wallet-22PzRY9T.js} +2 -2
  89. package/src/assets/web-panel/assets/{WebAuthn-x8OoogZU.js → WebAuthn-eSMq_qtz.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-CC3jIUqx.js → WorkflowEditor-BvdAakpq.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-Bqgv5oe8.js → chat-C6jhpF7E.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-CbAMqLFr.js → colors-BbbW2Pfv.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-B-zIDFg3.js → compact-item-CVFeLTqt.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-D_s1ZLtZ.js → createContext-DS0m7NZc.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-D50gzPS9.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-Cj_J9Eb9.js → hasIn-DVouP0t6.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BtJzqXCQ.js → index--AdzSlH7.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-D_igPAXH.js → index-54aHB4FL.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BivQyKes.js → index-8QbwhE3i.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-3o8DjHHt.js → index-B5JRIZXi.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-0je3TLmx.js → index-B8a_c_qZ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cz0blpuN.js → index-BE_u-rXr.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Cu3FtpNc.js → index-BOOsA080.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-KY7udrs-.js → index-BXw6ivB8.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-J4JLWUMK.js → index-BaUah6TO.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C6bAvixK.js → index-Be12HoCS.js} +3 -3
  107. package/src/assets/web-panel/assets/{index-Cy3XOp7S.js → index-BhvnNFfd.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C6lO24YD.js → index-BrIv7C9a.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BPdH-XTd.js → index-BvCgzl0X.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Cg0oYTy5.js → index-Bw-ZGQCH.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-ab6FUgkq.js → index-BwZnPiFd.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DuqVIsHL.js → index-BwozzG6k.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-B6qoyCkx.js → index-ByLsH9CL.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BjfpW5s3.js → index-BzL3LWFX.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BFNO6ycz.js → index-C4xmLgLa.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-dg0JqQDA.js → index-C6q2MkIG.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DtplHZ5o.js → index-C74emdKD.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bi1E5h9V.js → index-CIg4nqyp.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-C-Z13SCI.js → index-CIk7mg6G.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-JdSkHz64.js → index-CPS8E-J6.js} +1 -1
  121. package/src/assets/web-panel/assets/index-CgensV-n.js +1 -0
  122. package/src/assets/web-panel/assets/{index-DVjFV2mg.js → index-CkdYB0_g.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CsHTqPTg.js → index-CpTbnbUI.js} +1 -1
  124. package/src/assets/web-panel/assets/index-Ctkf06Z_.js +1 -0
  125. package/src/assets/web-panel/assets/{index-nEWJobH4.js → index-CwYFDMn_.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BN5sO3kL.js → index-DGYX17YW.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CD_A-N7c.js → index-DR6TDz5H.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-ggeC-_dR.js → index-DUBkae39.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-D9CqHOgd.js → index-DotRL126.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CSzWODfj.js → index-DpReoAGb.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Bw88Mk2t.js → index-Ds4wbrgk.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BGxI_Qxg.js → index-DuVjTDcW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BLwUCYDf.js → index-JeJqXbUU.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-D1t2IqNU.js → index-SdFkCtiC.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CVPI_iIh.js → index-eaXEQFuP.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-DDIGXQ08.js → initDefaultProps-CB5cUnQ5.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-97SXSYE4.js → motion-bn_fWhQV.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-CfDQMFRe.js → move-DY4-Odtu.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-qLYCGwY8.js → mtc-parser-B5l5mjoh.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-xVqy1mCI.js → omit-rJ-Ci8CW.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-DCGlFyfv.js → pickAttrs-BMwGJd6C.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-DYgPuMk3.js → placementArrow-CaiQyGXG.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-7zUIdAWH.js → responsiveObserve-DQTO5wDH.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-TyaiZlSh.js → slide-Dg6ZDtbz.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-BPd13Fae.js → statusUtils-bvjrktKc.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-A44XGgQ0.js → styleChecker-C1geIU_x.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-ZX5EUa8B.js → useFlexGapSupport-BzU3RJRi.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-Sh_fBPqz.js → useFs-B7l6OwLe.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-DhR6Izei.js → usePersonalDataHub-BYF1L_8x.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-DC8g6oRh.js → vnode-6c2GVkT-.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-DRjJmOwj.js → zoom-BYAY6QeD.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/commands/agent.js +21 -10
  154. package/src/data/changelog.json +39 -0
  155. package/src/gateways/ws/session-protocol.js +19 -5
  156. package/src/gateways/ws/ws-agent-handler.js +6 -0
  157. package/src/gateways/ws/ws-session-gateway.js +133 -21
  158. package/src/lib/agent-execution-policy.js +177 -0
  159. package/src/lib/authority-launch-environment.js +99 -0
  160. package/src/lib/auto-mode-config.js +129 -45
  161. package/src/lib/claude-project-auto-memory.js +7 -30
  162. package/src/lib/context-memory-kernel/task-worklog-port.js +73 -24
  163. package/src/lib/diagnostic-excerpt.js +91 -10
  164. package/src/lib/diagnostic-workflow.js +2 -0
  165. package/src/lib/evolution/volcengine-function-replay-store.js +38 -28
  166. package/src/lib/git-tool-input.js +7 -0
  167. package/src/lib/host-tool-policy-authority.js +151 -0
  168. package/src/lib/permission-authority.js +67 -5
  169. package/src/lib/plugin-runtime/settings.js +9 -1
  170. package/src/lib/remote-read-loop-guard.js +59 -14
  171. package/src/lib/sandbox-egress-authority-monitor.js +3 -2
  172. package/src/lib/session-manager.js +20 -5
  173. package/src/lib/settings-loader.cjs +175 -19
  174. package/src/lib/settings-source-observation.cjs +270 -0
  175. package/src/lib/sub-agent-context.js +36 -18
  176. package/src/lib/task-progress-tracker.js +112 -12
  177. package/src/lib/unattended-action-policy.js +456 -38
  178. package/src/repl/agent-repl.js +58 -29
  179. package/src/repl/repl-tool-executor.js +39 -0
  180. package/src/runtime/agent-core.js +272 -5
  181. package/src/runtime/agent-runtime.js +15 -3
  182. package/src/runtime/headless-runner.js +13 -4
  183. package/src/runtime/headless-stream.js +9 -0
  184. package/src/runtime/policies/agent-policy.js +5 -4
  185. package/src/assets/web-panel/assets/MarkdownRenderer-BpRWpN1E.js +0 -1
  186. package/src/assets/web-panel/assets/Projects-3Qo2Mvxb.js +0 -1
  187. package/src/assets/web-panel/assets/devWarning-QMSC9xgn.js +0 -1
  188. package/src/assets/web-panel/assets/index-DVq7UuW0.js +0 -1
  189. package/src/assets/web-panel/assets/index-DYVepsIV.js +0 -1
@@ -1399,12 +1399,26 @@ export function handleSessionPolicyUpdate(server, id, ws, message) {
1399
1399
  return;
1400
1400
  }
1401
1401
 
1402
- const session = server.sessionManager.updateSessionPolicy
1403
- ? server.sessionManager.updateSessionPolicy(
1402
+ let session;
1403
+ try {
1404
+ session = server.sessionManager.updateSessionPolicy
1405
+ ? server.sessionManager.updateSessionPolicy(
1406
+ sessionId,
1407
+ hostManagedToolPolicy,
1408
+ )
1409
+ : null;
1410
+ } catch (error) {
1411
+ server._send(
1412
+ ws,
1413
+ envelopeError(
1414
+ id,
1415
+ error?.code || "SESSION_POLICY_UPDATE_FAILED",
1416
+ "Session policy update could not be committed",
1404
1417
  sessionId,
1405
- hostManagedToolPolicy,
1406
- )
1407
- : null;
1418
+ ),
1419
+ );
1420
+ return;
1421
+ }
1408
1422
 
1409
1423
  if (!session) {
1410
1424
  server._send(
@@ -39,6 +39,7 @@ import {
39
39
  runWithHostHooksV2Workspace,
40
40
  } from "../../lib/hooks-v2-workspace-context.js";
41
41
  import { createWsApprovalGate } from "./ws-approval-gate.js";
42
+ import { createPermissionRulesProvider } from "../../lib/permission-authority.js";
42
43
  import { createSessionMcpLedgerSink } from "../../lib/mcp-call-ledger-store.js";
43
44
  import { createMcpHostRecoveryRuntime } from "../../lib/mcp-host-recovery-runtime.js";
44
45
  import { compactConversationWithProvider } from "../../harness/provider-backed-compaction.js";
@@ -1539,6 +1540,11 @@ export class WSAgentHandler {
1539
1540
  hostResourceBudget: this._hostResourceBudget,
1540
1541
  enabledToolNames: session.enabledToolNames || null,
1541
1542
  hostManagedToolPolicy: session.hostManagedToolPolicy || null,
1543
+ hostManagedToolPolicyAuthority:
1544
+ session.hostManagedToolPolicyAuthority || null,
1545
+ permissionRulesProvider: createPermissionRulesProvider({
1546
+ cwd: session.projectRoot,
1547
+ }),
1542
1548
  extraToolDefinitions: session.externalToolDefinitions || [],
1543
1549
  externalToolDescriptors: session.externalToolDescriptors || {},
1544
1550
  externalToolExecutors: session.externalToolExecutors || {},
@@ -36,6 +36,7 @@ import {
36
36
  deleteSession as dbDeleteSession,
37
37
  } from "../../lib/session-manager.js";
38
38
  import { buildSystemPrompt } from "../../runtime/agent-core.js";
39
+ import { createHostToolPolicyAuthority } from "../../lib/host-tool-policy-authority.js";
39
40
  import { SubAgentRegistry } from "../../lib/sub-agent-registry.js";
40
41
  import {
41
42
  createWorktree,
@@ -71,7 +72,39 @@ import {
71
72
  } from "../../harness/jsonl-session-store.js";
72
73
 
73
74
  export const WS_SESSION_ROLLOUT_EVENT = "ws_session_state";
74
- const WS_SESSION_ROLLOUT_SCHEMA = "chainlesschain.ws-session-rollout/v1";
75
+ const WS_SESSION_ROLLOUT_SCHEMA = "chainlesschain.ws-session-rollout/v2";
76
+ const LEGACY_WS_SESSION_ROLLOUT_SCHEMA = "chainlesschain.ws-session-rollout/v1";
77
+ const WS_HOST_POLICY_SCHEMA = "chainlesschain.ws-host-tool-policy/v1";
78
+ const SESSION_HOST_POLICY_CONTROLLERS = new WeakMap();
79
+
80
+ function bindSessionHostToolPolicy(session, controller) {
81
+ SESSION_HOST_POLICY_CONTROLLERS.set(session, controller);
82
+ Object.defineProperties(session, {
83
+ hostManagedToolPolicyAuthority: { value: controller.authority },
84
+ hostManagedToolPolicy: {
85
+ enumerable: true,
86
+ get: () => controller.authority.getSnapshot().policy,
87
+ },
88
+ });
89
+ }
90
+
91
+ function canonicalHostToolPolicy(journal, fallback = null) {
92
+ if (!journal || !Object.hasOwn(journal, "hostToolPolicy")) return fallback;
93
+ const stored = journal.hostToolPolicy;
94
+ if (
95
+ !stored ||
96
+ stored.schema !== WS_HOST_POLICY_SCHEMA ||
97
+ !Object.hasOwn(stored, "policy")
98
+ ) {
99
+ throw canonicalWsStateError(
100
+ "CC_WS_CANONICAL_STATE_CORRUPT",
101
+ "Canonical host policy is invalid",
102
+ );
103
+ }
104
+ // Validate known authority fields before restoring any execution capability.
105
+ return createHostToolPolicyAuthority(stored.policy).authority.getSnapshot()
106
+ .policy;
107
+ }
75
108
 
76
109
  function canonicalWsStateError(code, message) {
77
110
  const error = new Error(message);
@@ -475,6 +508,9 @@ export class WSSessionManager {
475
508
  throw error;
476
509
  }
477
510
  const type = options.type || "agent";
511
+ const hostPolicyController = createHostToolPolicyAuthority(
512
+ options.hostManagedToolPolicy ?? null,
513
+ );
478
514
  const baseProjectRoot = options.projectRoot || this.defaultProjectRoot;
479
515
  const hostAuthorizedBaseRoot =
480
516
  normalizeHostWorkspaceRoot(baseProjectRoot) ===
@@ -583,7 +619,6 @@ export class WSSessionManager {
583
619
  baseUrl,
584
620
  mcpClient: this.mcpClient,
585
621
  enabledToolNames,
586
- hostManagedToolPolicy: options.hostManagedToolPolicy || null,
587
622
  sessionBudgetRoot: options.sessionBudgetRoot || null,
588
623
  externalToolDefinitions: externalTools.definitions,
589
624
  externalToolDescriptors: externalTools.descriptors,
@@ -605,6 +640,7 @@ export class WSSessionManager {
605
640
  createdAt: new Date().toISOString(),
606
641
  lastActivity: new Date().toISOString(),
607
642
  };
643
+ bindSessionHostToolPolicy(session, hostPolicyController);
608
644
  bindCanonicalHostSystemPrefix(session, messages);
609
645
  this._bindSessionStateJournal(session, createWsSessionState());
610
646
  bindSessionHooksV2Workspace(
@@ -726,14 +762,28 @@ export class WSSessionManager {
726
762
  if (!this.db) return null;
727
763
 
728
764
  try {
729
- const dbSession = dbGetSession(this.db, sessionId);
765
+ const dbSession = dbGetSession(this.db, sessionId, {
766
+ strictMetadata: true,
767
+ });
730
768
  if (!dbSession) return null;
731
769
 
732
770
  const messages =
733
771
  typeof dbSession.messages === "string"
734
772
  ? JSON.parse(dbSession.messages)
735
773
  : dbSession.messages || [];
736
- const metadata = this._normalizeSessionMetadata(dbSession.metadata);
774
+ const metadata = this._normalizeSessionMetadata(dbSession.metadata, {
775
+ strict: true,
776
+ });
777
+ const canonicalSessionState =
778
+ metadata.canonicalJsonlSession === true
779
+ ? this._readCanonicalSessionState(dbSession.id, { required: true })
780
+ : null;
781
+ const hostPolicyController = createHostToolPolicyAuthority(
782
+ canonicalHostToolPolicy(
783
+ canonicalSessionState,
784
+ metadata.hostManagedToolPolicy ?? null,
785
+ ),
786
+ );
737
787
  const baseProjectRoot =
738
788
  metadata.baseProjectRoot ||
739
789
  metadata.projectRoot ||
@@ -744,10 +794,6 @@ export class WSSessionManager {
744
794
  metadata,
745
795
  );
746
796
  const planManager = this._hydratePlanManager(metadata.planSnapshot);
747
- const canonicalSessionState =
748
- metadata.canonicalJsonlSession === true
749
- ? this._readCanonicalSessionState(dbSession.id, { required: true })
750
- : null;
751
797
  const sessionStateJournal = canonicalSessionState
752
798
  ? hydrateCanonicalWsSessionState(canonicalSessionState)
753
799
  : hydrateWsSessionState(
@@ -806,7 +852,6 @@ export class WSSessionManager {
806
852
  enabledToolNames: this._normalizeEnabledToolNames(
807
853
  metadata.enabledToolNames,
808
854
  ),
809
- hostManagedToolPolicy: metadata.hostManagedToolPolicy || null,
810
855
  sessionBudgetRoot: metadata.sessionBudgetRoot || null,
811
856
  externalToolDefinitions: externalTools.definitions,
812
857
  externalToolDescriptors: externalTools.descriptors,
@@ -830,6 +875,7 @@ export class WSSessionManager {
830
875
  createdAt: dbSession.created_at,
831
876
  lastActivity: new Date().toISOString(),
832
877
  };
878
+ bindSessionHostToolPolicy(session, hostPolicyController);
833
879
  if (Array.isArray(metadata.canonicalHostSystemPrefix)) {
834
880
  bindCanonicalHostSystemPrefix(
835
881
  session,
@@ -875,6 +921,10 @@ export class WSSessionManager {
875
921
  : { changed: false };
876
922
  const created = this.createSession({
877
923
  sessionId,
924
+ hostManagedToolPolicy: canonicalHostToolPolicy(
925
+ canonicalSessionState,
926
+ options.hostManagedToolPolicy ?? null,
927
+ ),
878
928
  type: options.type || "agent",
879
929
  provider: options.provider,
880
930
  model: options.model,
@@ -1049,9 +1099,27 @@ export class WSSessionManager {
1049
1099
  const session = this.sessions.get(sessionId);
1050
1100
  if (!session) return null;
1051
1101
 
1052
- session.hostManagedToolPolicy = hostManagedToolPolicy || null;
1102
+ const controller = SESSION_HOST_POLICY_CONTROLLERS.get(session);
1103
+ if (!controller) {
1104
+ const error = new Error("Session host policy authority is unavailable");
1105
+ error.code = "CC_HOST_TOOL_POLICY_AUTHORITY_UNAVAILABLE";
1106
+ throw error;
1107
+ }
1108
+ controller.commit(hostManagedToolPolicy ?? null);
1053
1109
  session.lastActivity = new Date().toISOString();
1054
- this._persistSessionState(sessionId);
1110
+ try {
1111
+ this._persistCanonicalSessionState(
1112
+ session,
1113
+ this._ensureSessionStateJournal(session),
1114
+ );
1115
+ this._persistSessionState(sessionId, { throwOnError: true });
1116
+ } catch (error) {
1117
+ // Do not acknowledge a failed save or allow further execution from its
1118
+ // uncertain policy. The committed revision has already revoked monitors.
1119
+ controller.invalidate();
1120
+ error.code ||= "CC_WS_SESSION_POLICY_PERSISTENCE_FAILED";
1121
+ throw error;
1122
+ }
1055
1123
  return session;
1056
1124
  }
1057
1125
 
@@ -1707,7 +1775,7 @@ export class WSSessionManager {
1707
1775
  };
1708
1776
  }
1709
1777
 
1710
- _persistSessionState(sessionId) {
1778
+ _persistSessionState(sessionId, { throwOnError = false } = {}) {
1711
1779
  const session = this.sessions.get(sessionId);
1712
1780
  if (!session || !this.db) return;
1713
1781
 
@@ -1726,13 +1794,21 @@ export class WSSessionManager {
1726
1794
  );
1727
1795
  persistedMessages = [...hostPrefix, ...conversation];
1728
1796
  }
1729
- dbSaveMessages(
1797
+ const saved = dbSaveMessages(
1730
1798
  this.db,
1731
1799
  sessionId,
1732
1800
  persistedMessages,
1733
1801
  this._serializeSessionMetadata(session),
1734
1802
  );
1735
- } catch (_err) {
1803
+ if (throwOnError && saved?.updated !== true) {
1804
+ const error = new Error(
1805
+ "Session policy persistence did not update a record",
1806
+ );
1807
+ error.code = "CC_WS_SESSION_POLICY_PERSISTENCE_FAILED";
1808
+ throw error;
1809
+ }
1810
+ } catch (error) {
1811
+ if (throwOnError) throw error;
1736
1812
  // Non-critical
1737
1813
  }
1738
1814
 
@@ -1817,12 +1893,35 @@ export class WSSessionManager {
1817
1893
  }
1818
1894
  return null;
1819
1895
  }
1820
- if (event.data?.schema !== WS_SESSION_ROLLOUT_SCHEMA) {
1896
+ if (
1897
+ ![WS_SESSION_ROLLOUT_SCHEMA, LEGACY_WS_SESSION_ROLLOUT_SCHEMA].includes(
1898
+ event.data?.schema,
1899
+ )
1900
+ ) {
1821
1901
  throw canonicalWsStateError(
1822
1902
  "CC_WS_CANONICAL_STATE_CORRUPT",
1823
1903
  `canonical WebSocket session state has an invalid schema: ${sessionId}`,
1824
1904
  );
1825
1905
  }
1906
+ if (
1907
+ !event.data.journal ||
1908
+ typeof event.data.journal !== "object" ||
1909
+ Array.isArray(event.data.journal)
1910
+ ) {
1911
+ throw canonicalWsStateError(
1912
+ "CC_WS_CANONICAL_STATE_CORRUPT",
1913
+ "Canonical WebSocket journal is missing or invalid",
1914
+ );
1915
+ }
1916
+ if (event.data.schema === WS_SESSION_ROLLOUT_SCHEMA) {
1917
+ if (!Object.hasOwn(event.data.journal, "hostToolPolicy")) {
1918
+ throw canonicalWsStateError(
1919
+ "CC_WS_CANONICAL_STATE_CORRUPT",
1920
+ "Canonical host policy is missing",
1921
+ );
1922
+ }
1923
+ canonicalHostToolPolicy(event.data.journal);
1924
+ }
1826
1925
  return event.data.journal;
1827
1926
  }
1828
1927
 
@@ -1833,7 +1932,13 @@ export class WSSessionManager {
1833
1932
  WS_SESSION_ROLLOUT_EVENT,
1834
1933
  {
1835
1934
  schema: WS_SESSION_ROLLOUT_SCHEMA,
1836
- journal: serializeWsSessionState(journal),
1935
+ journal: {
1936
+ ...serializeWsSessionState(journal),
1937
+ hostToolPolicy: {
1938
+ schema: WS_HOST_POLICY_SCHEMA,
1939
+ policy: session.hostManagedToolPolicy,
1940
+ },
1941
+ },
1837
1942
  },
1838
1943
  );
1839
1944
  }
@@ -1914,20 +2019,27 @@ export class WSSessionManager {
1914
2019
  };
1915
2020
  }
1916
2021
 
1917
- _normalizeSessionMetadata(metadata) {
1918
- if (!metadata) {
2022
+ _normalizeSessionMetadata(metadata, { strict = false } = {}) {
2023
+ if (metadata == null || (!strict && !metadata)) {
1919
2024
  return {};
1920
2025
  }
1921
2026
 
1922
2027
  if (typeof metadata === "string") {
1923
2028
  try {
1924
- return JSON.parse(metadata);
1925
- } catch (_err) {
2029
+ const parsed = JSON.parse(metadata);
2030
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
2031
+ throw new TypeError("Invalid session metadata");
2032
+ return parsed;
2033
+ } catch (error) {
2034
+ if (strict) throw error;
1926
2035
  return {};
1927
2036
  }
1928
2037
  }
1929
2038
 
1930
- return typeof metadata === "object" ? metadata : {};
2039
+ if (typeof metadata === "object" && !Array.isArray(metadata))
2040
+ return metadata;
2041
+ if (strict) throw new TypeError("Invalid session metadata");
2042
+ return {};
1931
2043
  }
1932
2044
 
1933
2045
  _hydratePlanManager(snapshot) {
@@ -0,0 +1,177 @@
1
+ import { isProxy } from "node:util/types";
2
+ import { snapshotMcpJsonRpcInput } from "./mcp-call-ledger.js";
3
+ import { captureUnattendedActionPolicy } from "./unattended-action-policy.js";
4
+
5
+ function invalidPolicy(field) {
6
+ const error = new TypeError(`Agent execution policy ${field} is invalid`);
7
+ error.code = "CC_AGENT_EXECUTION_POLICY_INVALID";
8
+ return error;
9
+ }
10
+
11
+ function ownValue(options, field) {
12
+ const descriptor = Object.getOwnPropertyDescriptor(options, field);
13
+ if (!descriptor) {
14
+ if (field in options) throw invalidPolicy(field);
15
+ return undefined;
16
+ }
17
+ if (!("value" in descriptor)) throw invalidPolicy(field);
18
+ return descriptor.value;
19
+ }
20
+
21
+ function objectSnapshot(value, field) {
22
+ if (value == null) return null;
23
+ try {
24
+ const snapshot = snapshotMcpJsonRpcInput(value);
25
+ if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
26
+ throw invalidPolicy(field);
27
+ return snapshot;
28
+ } catch {
29
+ throw invalidPolicy(field);
30
+ }
31
+ }
32
+
33
+ function stringList(value, field) {
34
+ if (value == null) return null;
35
+ try {
36
+ const snapshot = snapshotMcpJsonRpcInput(value);
37
+ if (
38
+ !Array.isArray(snapshot) ||
39
+ snapshot.some((entry) => typeof entry !== "string" || !entry.trim())
40
+ )
41
+ throw invalidPolicy(field);
42
+ return snapshot;
43
+ } catch {
44
+ throw invalidPolicy(field);
45
+ }
46
+ }
47
+
48
+ function booleanFields(value, fields, label) {
49
+ for (const field of fields) {
50
+ if (value[field] !== undefined && typeof value[field] !== "boolean")
51
+ throw invalidPolicy(`${label}.${field}`);
52
+ }
53
+ }
54
+
55
+ function captureSandbox(value) {
56
+ if (value === false) return null;
57
+ const sandbox = objectSnapshot(value, "sandbox");
58
+ if (!sandbox) return null;
59
+ booleanFields(sandbox, ["network"], "sandbox");
60
+ if (sandbox.policy !== undefined) {
61
+ const policy = objectSnapshot(sandbox.policy, "sandbox.policy");
62
+ if (!policy) throw invalidPolicy("sandbox.policy");
63
+ booleanFields(
64
+ policy,
65
+ ["allowUnsandboxedCommands", "failIfUnavailable"],
66
+ "sandbox.policy",
67
+ );
68
+ for (const field of [
69
+ "allowRead",
70
+ "denyRead",
71
+ "allowWrite",
72
+ "denyWrite",
73
+ "allowedDomains",
74
+ "deniedDomains",
75
+ "excludedCommands",
76
+ ]) {
77
+ if (policy[field] !== undefined)
78
+ stringList(policy[field], `sandbox.policy.${field}`);
79
+ }
80
+ }
81
+ return sandbox;
82
+ }
83
+
84
+ function captureToolAdmission(value) {
85
+ const admission = objectSnapshot(value, "toolAdmission");
86
+ if (!admission) return null;
87
+ const flags = [
88
+ "enforce",
89
+ "capabilityGranted",
90
+ "policyAllowed",
91
+ "permissionGranted",
92
+ "budgetOk",
93
+ "uiSupported",
94
+ ];
95
+ booleanFields(admission, flags, "toolAdmission");
96
+ if (admission.tools !== undefined) {
97
+ const tools = objectSnapshot(admission.tools, "toolAdmission.tools");
98
+ if (!tools) throw invalidPolicy("toolAdmission.tools");
99
+ for (const [name, entry] of Object.entries(tools)) {
100
+ const override = objectSnapshot(entry, `toolAdmission.tools.${name}`);
101
+ if (!override) throw invalidPolicy(`toolAdmission.tools.${name}`);
102
+ booleanFields(override, flags, `toolAdmission.tools.${name}`);
103
+ }
104
+ }
105
+ return admission;
106
+ }
107
+
108
+ /**
109
+ * Copy startup/turn data before the first await. Live permission providers,
110
+ * host policy owners, Plan managers and ApprovalGates remain live capabilities.
111
+ * A later user turn may capture a different tool list; this turn's caller-owned
112
+ * arrays cannot change its model surface or execution ceiling midway through.
113
+ */
114
+ export function captureAgentExecutionPolicy(
115
+ options = {},
116
+ { hermetic = false } = {},
117
+ ) {
118
+ if (!options || typeof options !== "object" || isProxy(options))
119
+ throw invalidPolicy("options");
120
+ const isolated = hermetic && ownValue(options, "hermeticExecution") === true;
121
+ const policy = {
122
+ sandbox: captureSandbox(ownValue(options, "sandbox")),
123
+ toolAdmission: isolated
124
+ ? null
125
+ : captureToolAdmission(ownValue(options, "toolAdmission")),
126
+ unattendedActionPolicy: isolated
127
+ ? null
128
+ : captureUnattendedActionPolicy(
129
+ ownValue(options, "unattendedActionPolicy"),
130
+ ),
131
+ shellPolicyOverrides: stringList(
132
+ ownValue(options, "shellPolicyOverrides"),
133
+ "shellPolicyOverrides",
134
+ ),
135
+ };
136
+ const classifyAllShell = ownValue(options, "classifyAllShell");
137
+ if (classifyAllShell != null) {
138
+ if (typeof classifyAllShell !== "boolean")
139
+ throw invalidPolicy("classifyAllShell");
140
+ policy.classifyAllShell = classifyAllShell;
141
+ }
142
+ for (const field of [
143
+ "additionalDirectories",
144
+ "enabledToolNames",
145
+ "disabledTools",
146
+ "allowedTools",
147
+ "disallowedTools",
148
+ "effectiveAllowedToolNames",
149
+ ]) {
150
+ const value = ownValue(options, field);
151
+ if (value !== undefined) policy[field] = stringList(value, field);
152
+ }
153
+ return Object.freeze(policy);
154
+ }
155
+
156
+ /** Explicit lists intersect; deny lists always accumulate. [] means no tools. */
157
+ export function resolveAgentToolSelection(policy = {}, ceiling = null) {
158
+ const lists = [
159
+ ceiling,
160
+ policy.allowedTools,
161
+ policy.enabledToolNames,
162
+ policy.effectiveAllowedToolNames,
163
+ ].filter(Array.isArray);
164
+ const enabledToolNames =
165
+ lists.length === 0
166
+ ? null
167
+ : Object.freeze(
168
+ lists[0].filter((name) => lists.every((list) => list.includes(name))),
169
+ );
170
+ const disabledTools = Object.freeze([
171
+ ...new Set([
172
+ ...(policy.disabledTools || []),
173
+ ...(policy.disallowedTools || []),
174
+ ]),
175
+ ]);
176
+ return Object.freeze({ enabledToolNames, disabledTools });
177
+ }
@@ -0,0 +1,99 @@
1
+ /** Launcher-owned storage locations and permission switches. */
2
+
3
+ export const STORAGE_AUTHORITY_ENV_KEYS = Object.freeze([
4
+ "CHAINLESSCHAIN_HOME",
5
+ "CLAUDE_CONFIG_DIR",
6
+ "CLAUDE_CODE_PROJECT_DIR_NAME",
7
+ "CLAUDE_CODE_DISABLE_AUTO_MEMORY",
8
+ "CC_MANAGED_SETTINGS",
9
+ "ProgramData",
10
+ "PROGRAMDATA",
11
+ "CHAINLESSCHAIN_SECURITY_ANCHOR_HOME",
12
+ "LOCALAPPDATA",
13
+ "XDG_STATE_HOME",
14
+ // os.homedir() uses these launcher values too. Protecting only the explicit
15
+ // anchor override leaves its default location redirectable via settings env.
16
+ "HOME",
17
+ "USERPROFILE",
18
+ "HOMEDRIVE",
19
+ "HOMEPATH",
20
+ ]);
21
+
22
+ const PERMISSION_AUTHORITY_ENV_KEYS = Object.freeze([
23
+ "CC_PERMISSIONS_ALLOW",
24
+ "CC_PERMISSIONS_ASK",
25
+ "CC_PERMISSIONS_DENY",
26
+ "CC_BYPASS_PERMISSIONS",
27
+ ]);
28
+
29
+ function normalizeKey(key, platform) {
30
+ return platform === "win32" ? key.toUpperCase() : key;
31
+ }
32
+
33
+ function storageKeys(platform) {
34
+ return new Map(
35
+ STORAGE_AUTHORITY_ENV_KEYS.map((key) => [normalizeKey(key, platform), key]),
36
+ );
37
+ }
38
+
39
+ /** Native process.env truncates names at NUL; validate before any assignment. */
40
+ export function isValidEnvironmentKey(key) {
41
+ return (
42
+ typeof key === "string" &&
43
+ key.length > 0 &&
44
+ !key.includes("\0") &&
45
+ !key.includes("=")
46
+ );
47
+ }
48
+
49
+ /** Plugins may supply tool defaults, but cannot select a new authority domain. */
50
+ export function isPluginAuthorityEnvironmentKey(
51
+ key,
52
+ { platform = process.platform } = {},
53
+ ) {
54
+ if (typeof key !== "string") return false;
55
+ const normalized = normalizeKey(key, platform);
56
+ return [...STORAGE_AUTHORITY_ENV_KEYS, ...PERMISSION_AUTHORITY_ENV_KEYS].some(
57
+ (candidate) => normalizeKey(candidate, platform) === normalized,
58
+ );
59
+ }
60
+
61
+ export function captureStorageAuthorityEnvironment(
62
+ env = process.env,
63
+ { platform = process.platform } = {},
64
+ ) {
65
+ const keys = storageKeys(platform);
66
+ const snapshot = {};
67
+ for (const [key, value] of Object.entries(env)) {
68
+ const canonicalKey = keys.get(normalizeKey(key, platform));
69
+ if (!canonicalKey || typeof value !== "string") continue;
70
+ if (
71
+ Object.hasOwn(snapshot, canonicalKey) &&
72
+ snapshot[canonicalKey] !== value
73
+ ) {
74
+ const error = new Error(
75
+ "Conflicting launcher storage environment aliases",
76
+ );
77
+ error.code = "CC_STORAGE_AUTHORITY_ENV_AMBIGUOUS";
78
+ throw error;
79
+ }
80
+ snapshot[canonicalKey] = value;
81
+ }
82
+ return Object.freeze(snapshot);
83
+ }
84
+
85
+ /** Remove newly introduced aliases before restoring the trusted snapshot. */
86
+ export function restoreStorageAuthorityEnvironment(
87
+ snapshot,
88
+ env = process.env,
89
+ { platform = process.platform } = {},
90
+ ) {
91
+ const captured = captureStorageAuthorityEnvironment(snapshot || {}, {
92
+ platform,
93
+ });
94
+ const keys = storageKeys(platform);
95
+ for (const key of Object.keys(env)) {
96
+ if (keys.has(normalizeKey(key, platform))) delete env[key];
97
+ }
98
+ Object.assign(env, captured);
99
+ }