chainlesschain 0.162.181 → 0.162.182

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 (180) hide show
  1. package/package.json +2 -1
  2. package/scripts/build-windows-sandbox-helper.ps1 +163 -0
  3. package/src/assets/web-panel/assets/{AIOps-cq0dwbnf.js → AIOps-DzZ5_xoj.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CvcgGl3w.js → ActionButton-DeLXddIg.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-hM2-jFqg.js → Analytics-rvDCmet1.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-B9_Gsd_g.js → AppLayout-Yt6QVDnp.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-B7bu52Og.js → Artifacts-BS112K5L.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-DThfDgqB.js → Audit-0wJuQrNu.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DjlFiD4v.js → BackgroundAgents-B90PMgbn.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CK9xJKnG.js → Backup-TkgMglQQ.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DEiSU8K8.js → BaseInput-CQVS9p1l.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CpT96czj.js → Chat-YTjQHoC7.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BKPPNmZI.js → ChatBubbleRenderer-PR074hUN.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-C1GfDnO0.js → Checkbox-5bwaOabq.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-3DAKgiLx.js → Codegen-BFmNQ_Xe.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-74cOwZU1.js → Col-BT_u4Dzp.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-tn9Kkz9j.js → Community-CJP52u5b.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BcoXH7m4.js → Compact-BpzhJE9i.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DIPGUBgi.js → Compliance-Cg7rfslp.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-doD5_91c.js → Cowork-JisxL6Yy.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-C-IDvubz.js → Cron-Bu7Ug_MC.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CdcCoBdj.js → Crosschain-CvuqoLdj.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DdH5aMMA.js → DID-C2u9G8Pu.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-DHLA4mm0.js → Dashboard-BFt5Yv3d.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-dEeCt7Md.js → Dropdown-DIaT9Wxq.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BMaecFv9.js → EmailListRenderer-D_A601Y4.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DUaUukTN.js → FamilyGuardDashboard--IyQ8I8w.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-CMBE0_rp.js → Federation-BihWHxuY.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-PG-JDbXq.js → FormItemContext-BB8dOXc_.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-Bcb0p88m.js → GenericCardRenderer-DQYhj1HH.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Bgv15myB.js → Git-B-2QZxGf.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-DB8YTArI.js → Governance-CusSb-nG.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BQMwCWaS.js → Inference-BAjmvPPL.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-B1_ZziiB.js → KnowledgeGraph-DoNYWKYq.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DovEEnt_.js → Logs-B8fKWD-n.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-D201OL4T.js → MarkdownRenderer-BlJm1J7E.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BlCXSpyB.js → Marketplace-CyOscbSL.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-CsCR09Wj.js → McpTools-Ex6Om5da.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-CBVRLKno.js → Memory-CDcD8l8r.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-C9OIafgA.js → MobileBridge-xfBqoFDg.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-D_zoJ8Xs.js → MobileProjects-BwObMMA2.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-vE-HdvLj.js → Mtc-CIWd36OV.js} +5 -5
  43. package/src/assets/web-panel/assets/{MtcAudit-CPLaekCd.js → MtcAudit-CPX0ouuA.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-C_UP9C2o.js → Multisig-BDJsIUuW.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-2nODJcU1.js → NLProgramming-DEkbuD3N.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-BhE-SJGu.js → Notes-DJpHRhH1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-D21q7BNU.js → NotificationSettings-C1UZ-Qd5.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-0b62GYOD.js → OrderTableRenderer-GlJtqLjT.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-CEqmw_sb.js → Organization-Bbhj0fac.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-MW-gMDO_.js → Overflow-1H04x3kx.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CY0hjI_G.js → P2P-CDpPe3et.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-BbWh7Man.js → PdhVaultBrowser-MUX0Bpvw.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-ChqEA_4Q.js → Permissions-A07-0Ci1.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-B3YrbYfD.js → PersonalDataHub-DhhDWxAZ.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-B8WBhhlW.js → Pipeline-CyfbJfe-.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-Cmb0PXNx.js → Privacy-CNFps3ED.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-hF6zW3Nz.js → ProjectInit--T-u3Dr5.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-BFSVfpW0.js → ProjectSettings-DJmrK2fC.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-DAWkVFkc.js → Projects-Qx_MdX9k.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-B8yux8Dx.js → Providers-DLzzbOZd.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-N76cQluO.js → QrScannerModal-CexOomKS.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-ClvZ0KYR.js → QuickAsk-QklGi19_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-B-GfgBpT.js → Recommend-Bb9kwSw8.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-mlglCdQi.js → RemoteSession-DZuVNNN5.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-DJIZzQeG.js → Reputation-Dr5cLP0N.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-COzxu_bb.js → Row-oCQHYv5t.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CoYsJQuE.js → RssFeed-IFDEykIR.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DC77Mq9S.js → Search-CspVIxDc.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Loy2EdMO.js → Security-Bm66o_DH.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-GUD07Eu0.js → Services-DvanNqXl.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-DWzkptYU.js → Skeleton-CHjEe9_O.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CEDn1r-Z.js → Skills-Cb8jWjMX.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-ub_k4pXh.js → Sla-DxZm1491.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-D7HLX9CA.js → SpeechSettings-DWxEEclC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-DbwOvl6m.js → SyncSettings-FIvOFw5p.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-CBQzoAu5.js → Tasks-CyuLnDFR.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-BNVeIhud.js → Templates-CaNjzV_t.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-PS9AzhXU.js → Tenant-DjlP6TmH.js} +1 -1
  79. package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +3 -0
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CrmXMOkg.js → TimelineRenderer-DoZ8y7y8.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-DD-VDHw1.js → Tokens-390cg2TC.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-BsoN_n-n.js → Trigger-CLrtCj5_.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-n8LmN4ZV.js → Trust-DpESfSPn.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-C9_7MImA.js → UkeySign-CN6279O0.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DyBteNgn.js → VideoEditing-DPtAUlSe.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BS5ixeXI.js → Wallet-nKOMV_1n.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-spc4UImU.js → WebAuthn-HuXlSOc4.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-D7iVvaBO.js → WorkflowEditor-CUfFjARi.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-6CmBkHrL.js → chat-6Eq0PcZJ.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BGoCLkxI.js → colors-BP_Sf6Iy.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-fYZBetMO.js → compact-item-BufMKIh5.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BeM-1UVj.js → createContext-BBMXxWSW.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-CE7ZuEnV.js → hasIn-fUK_tRO2.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-QIpnpZgz.js → index-2A5ph8b2.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BU_2qiDk.js → index-3FuwBewR.js} +1 -1
  97. package/src/assets/web-panel/assets/{index--lap6cf7.js → index-6GmBa4Kg.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-De0quFDw.js → index-B2vS66eI.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D1r9tT3J.js → index-B7Etk0Te.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-YjcumOZ4.js → index-B9WYSn4m.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-MtOuq2i6.js → index-BHy6yNiF.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-RMZ8a7Yt.js → index-BMLHv389.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-C0v6YKKO.js → index-BWKoBU8R.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CRnUE8Cb.js → index-Bkg4ZePE.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BsMfoaeo.js → index-C44atv4k.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DoXk5KJ8.js → index-CE2DdTP2.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-B4wiTEOM.js → index-CGjmILDm.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-zb7rVOhV.js → index-CW_G-MXw.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-ATcSr_2O.js → index-CZ6Yt17L.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C9Y3k0HI.js → index-CeASi4fr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-B2U-ObMq.js → index-CgiECHu2.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Puq6Luf1.js → index-Cp8vhyZy.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BV551878.js → index-CwSf5pnf.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BowH1eLQ.js → index-D4_MuGkd.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B3CDgvNW.js → index-D9vU25ij.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-WUrJ6S1j.js → index-DASluSqY.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CRLjEP1H.js → index-DLpIs_P_.js} +1 -1
  118. package/src/assets/web-panel/assets/index-DOZTSoS7.js +1 -0
  119. package/src/assets/web-panel/assets/{index-DT3zPSVX.js → index-DPdUNk1i.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BunaQCa0.js → index-DVsqvI4M.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DhpvjpqI.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CIpVrf5P.js → index-DmkMXwnR.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-lJBjB1QX.js → index-DocdRcbd.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BEVm0lCS.js → index-Dyngbd29.js} +19 -19
  125. package/src/assets/web-panel/assets/{index-C4SJVjs4.js → index-GwdRUZ-x.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-ukg99D1V.js → index-LvCBfTLo.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BfPL-m46.js → index-cpEli44X.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CpIGIB85.js → index-fzaMtSJ8.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BNZDILcO.js → index-pum7HYBA.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Dw1PyYPm.js → index-t8N1tSeX.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cip8emOQ.js → index-uCbEN7cY.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DsvfrESp.js → index-wKTLbKyc.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-B8BsdNV_.js → index-wV6iGdpY.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CYHMs1ag.js → initDefaultProps-V5Fo95FM.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-DDB2Ffk5.js → motion-BYWU0hUT.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Bg3cD-dX.js → move-Cr1M-J2h.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-B5nedjTS.js → mtc-parser-BysQKi2N.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BHyuUILu.js → omit-D1zHU8GC.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-C9YQnEN9.js → pickAttrs-CUArxtfi.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-DBUFYUe7.js → placementArrow-ChoYEys0.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-nBs2Obnk.js → responsiveObserve-BQRs3Mo7.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DkCEaXNU.js → slide-B8zbsCkg.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-aqE1Wi6U.js → statusUtils-C2U8Gs6h.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-CN5bhfHB.js → styleChecker-Dd8MgL_V.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-B_oX_kvJ.js → useFlexGapSupport-hknqY5NH.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-rCuXHeme.js → useFs-CLTAmcfw.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-DZR9Abyd.js → usePersonalDataHub-ByegHbiB.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-ConCYQlX.js → vnode-DqlAy5DP.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-CUdDxG5M.js → zoom-DiXiztQn.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agenda.js +115 -3
  152. package/src/commands/agent.js +6 -0
  153. package/src/data/changelog.json +13 -0
  154. package/src/gateways/terminal/PtyManager.js +45 -4
  155. package/src/gateways/ws/ws-server.js +10 -1
  156. package/src/harness/background-task-manager.js +70 -2
  157. package/src/harness/worktree-isolator.js +14 -3
  158. package/src/lib/agent-core.js +1 -0
  159. package/src/lib/agent-schedule-store.js +45 -22
  160. package/src/lib/hook-runner.js +6 -2
  161. package/src/lib/packer/pkg-config-generator.js +3 -1
  162. package/src/lib/plugin-runtime/bin.js +1148 -70
  163. package/src/lib/plugin-runtime/manifest.js +68 -12
  164. package/src/lib/plugin-runtime/scopes.js +20 -10
  165. package/src/lib/process-execution-broker/index.js +375 -48
  166. package/src/lib/process-execution-broker/platform-sandbox.js +3831 -276
  167. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  168. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  169. package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
  170. package/src/lib/repl-bang-memorize.js +67 -10
  171. package/src/lib/slash-commands.js +27 -4
  172. package/src/repl/agent-repl.js +4 -3
  173. package/src/runtime/agent-core.js +376 -52
  174. package/src/runtime/agent-runtime.js +13 -1
  175. package/src/runtime/headless-runner.js +4 -3
  176. package/src/assets/web-panel/assets/Terminal-Cgb4eLB_.js +0 -3
  177. package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +0 -1
  178. package/src/assets/web-panel/assets/index-DacrAdc-.js +0 -1
  179. package/src/assets/web-panel/assets/index-EHzNJozo.js +0 -1
  180. package/src/lib/process-execution-broker/windows-sandbox.ps1 +0 -999
@@ -21,6 +21,7 @@ import fsDefault from "fs";
21
21
  import pathDefault from "path";
22
22
  import { findProjectRoot } from "./project-instructions.js";
23
23
  import executionBroker from "./process-execution-broker/index.js";
24
+ import { collectPluginBinSandboxPolicy as collectDefaultPluginBinSandboxPolicy } from "./plugin-runtime/bin.js";
24
25
 
25
26
  export const BANG_TIMEOUT_MS = 120_000;
26
27
  export const BANG_MAX_BUFFER = 10 * 1024 * 1024;
@@ -33,6 +34,8 @@ export const MEMO_NOTE_MAX = 4_000;
33
34
 
34
35
  export const _deps = {
35
36
  spawnSync: (...args) => executionBroker.spawnSync(...args),
37
+ collectPluginBinSandboxPolicy: (opts) =>
38
+ collectDefaultPluginBinSandboxPolicy(opts),
36
39
  fs: fsDefault,
37
40
  path: pathDefault,
38
41
  };
@@ -44,6 +47,46 @@ function cap(s) {
44
47
  : str;
45
48
  }
46
49
 
50
+ function resolveWindowsCommandShell(opts = {}) {
51
+ const path = opts.deps?.path || _deps.path;
52
+ const env = opts.env || process.env;
53
+ const normalizeLocalPath = (candidate) => {
54
+ const value =
55
+ typeof candidate === "string"
56
+ ? candidate.trim()
57
+ : String(candidate || "");
58
+ // `path.win32.isAbsolute("\\foo")` is true even though the result still
59
+ // depends on the process's current drive. Require a drive-qualified local
60
+ // path so the helper receives one deterministic executable identity.
61
+ if (!/^[a-z]:[\\/]/i.test(value)) return null;
62
+ return path.win32.normalize(value);
63
+ };
64
+
65
+ for (const candidate of [opts.comSpec, env.ComSpec, env.COMSPEC]) {
66
+ const value = normalizeLocalPath(candidate);
67
+ if (value && path.win32.basename(value).toLowerCase() === "cmd.exe") {
68
+ return value;
69
+ }
70
+ }
71
+
72
+ for (const candidate of [
73
+ opts.systemRoot,
74
+ env.SystemRoot,
75
+ env.SYSTEMROOT,
76
+ env.WINDIR,
77
+ "C:\\Windows",
78
+ ]) {
79
+ const value = normalizeLocalPath(candidate);
80
+ if (value) {
81
+ return path.win32.join(value, "System32", "cmd.exe");
82
+ }
83
+ }
84
+
85
+ // The literal fallback above is absolute, so this is unreachable with Node's
86
+ // path.win32 implementation. Keep a fail-closed guard for injected path seams.
87
+ throw new Error("No absolute Windows command shell is available");
88
+ }
89
+
47
90
  /** True when the REPL line is a `!` bash passthrough. */
48
91
  export function isBangCommand(trimmed) {
49
92
  return (
@@ -70,24 +113,37 @@ export function isMemorizeLine(trimmed) {
70
113
  */
71
114
  export function runBangCommand(line, opts = {}) {
72
115
  const spawnSync = opts.deps?.spawnSync || _deps.spawnSync;
116
+ const collectPluginBinSandboxPolicy =
117
+ opts.deps?.collectPluginBinSandboxPolicy ||
118
+ _deps.collectPluginBinSandboxPolicy;
73
119
  const cwd = opts.cwd || process.cwd();
74
120
  const isWin =
75
121
  opts.platform != null
76
122
  ? opts.platform === "win32"
77
123
  : process.platform === "win32";
78
124
  const cmd = String(line).replace(/^!/, "").trim();
125
+ // A bang command is another arbitrary workspace process surface. Collect the
126
+ // tighten-only Plugin bin boundary union before the shell starts so it cannot
127
+ // bypass a policy that run_shell already pins for the same workspace.
128
+ const sandboxPolicy = collectPluginBinSandboxPolicy({ cwd });
129
+ const sandboxOptions = sandboxPolicy ? { sandboxPolicy } : {};
79
130
 
80
131
  const res = isWin
81
- ? spawnSync("cmd.exe", ["/d", "/s", "/c", `chcp 65001 >nul && ${cmd}`], {
82
- encoding: "utf-8",
83
- timeout: BANG_TIMEOUT_MS,
84
- maxBuffer: BANG_MAX_BUFFER,
85
- cwd,
86
- origin: "repl:bang-command",
87
- policy: "allow",
88
- scope: "repl",
89
- shell: false,
90
- })
132
+ ? spawnSync(
133
+ resolveWindowsCommandShell(opts),
134
+ ["/d", "/s", "/c", `chcp 65001 >nul && ${cmd}`],
135
+ {
136
+ encoding: "utf-8",
137
+ timeout: BANG_TIMEOUT_MS,
138
+ maxBuffer: BANG_MAX_BUFFER,
139
+ cwd,
140
+ origin: "repl:bang-command",
141
+ policy: "allow",
142
+ scope: "repl",
143
+ shell: false,
144
+ ...sandboxOptions,
145
+ },
146
+ )
91
147
  : spawnSync("/bin/sh", ["-c", cmd], {
92
148
  encoding: "utf-8",
93
149
  timeout: BANG_TIMEOUT_MS,
@@ -97,6 +153,7 @@ export function runBangCommand(line, opts = {}) {
97
153
  policy: "allow",
98
154
  scope: "repl",
99
155
  shell: false,
156
+ ...sandboxOptions,
100
157
  });
101
158
 
102
159
  const exitCode = res.status == null ? (res.error ? -1 : 0) : res.status;
@@ -24,11 +24,14 @@ import { homedir } from "node:os";
24
24
  import { expandFileRefs } from "../runtime/file-ref-expander.js";
25
25
  import { projectRootBase } from "./project-root.cjs";
26
26
  import executionBroker from "./process-execution-broker/index.js";
27
+ import { collectPluginBinSandboxPolicy as collectDefaultPluginBinSandboxPolicy } from "./plugin-runtime/bin.js";
27
28
 
28
29
  const _deps = {
29
30
  fs: fsDefault,
30
31
  path: pathDefault,
31
32
  execSync: (...args) => executionBroker.execSync(...args),
33
+ collectPluginBinSandboxPolicy: (opts) =>
34
+ collectDefaultPluginBinSandboxPolicy(opts),
32
35
  };
33
36
 
34
37
  /**
@@ -186,8 +189,16 @@ export function substituteArgs(text, args = []) {
186
189
  return out;
187
190
  }
188
191
 
192
+ function isSandboxFailClosedError(error) {
193
+ return (
194
+ error?.sandboxFailClosed === true ||
195
+ (typeof error?.code === "string" &&
196
+ error.code.startsWith("ERR_PROCESS_SANDBOX"))
197
+ );
198
+ }
199
+
189
200
  /** Run every `!`cmd`` and replace it with the command's stdout (best-effort). */
190
- function runBangs(text, { cwd, execSync }) {
201
+ function runBangs(text, { cwd, execSync, sandboxPolicy }) {
191
202
  return text.replace(/!`([^`]+)`/g, (_, cmd) => {
192
203
  try {
193
204
  const out = execSync(cmd, {
@@ -199,9 +210,13 @@ function runBangs(text, { cwd, execSync }) {
199
210
  policy: "allow",
200
211
  scope: "slash-command",
201
212
  shell: true,
213
+ ...(sandboxPolicy ? { sandboxPolicy } : {}),
202
214
  });
203
215
  return String(out).trim();
204
216
  } catch (err) {
217
+ // Broker boundary failures are security decisions, not ordinary command
218
+ // failures. Preserve the exact structured error for the caller.
219
+ if (isSandboxFailClosedError(err)) throw err;
205
220
  return `[command failed: ${cmd} — ${err.message?.split("\n")[0] || err}]`;
206
221
  }
207
222
  });
@@ -215,18 +230,26 @@ function runBangs(text, { cwd, execSync }) {
215
230
  *
216
231
  * @param {object} command output of getCommand/parseCommandFile (needs .body)
217
232
  * @param {string[]} args
218
- * @param {object} [opts] { cwd, allowBang, deps:{ execSync } }
233
+ * @param {object} [opts] { cwd, allowBang,
234
+ * deps:{ execSync, collectPluginBinSandboxPolicy } }
219
235
  * @returns {{ prompt:string, warnings:string[] }}
220
236
  */
221
237
  export function expandCommand(command, args = [], opts = {}) {
222
238
  const cwd = opts.cwd || process.cwd();
223
239
  const execSync = opts.deps?.execSync || _deps.execSync;
240
+ const collectPluginBinSandboxPolicy =
241
+ opts.deps?.collectPluginBinSandboxPolicy ||
242
+ _deps.collectPluginBinSandboxPolicy;
224
243
  const warnings = [];
225
244
 
226
245
  let text = substituteArgs(command.body || "", args);
227
246
 
228
- if (opts.allowBang !== false) {
229
- text = runBangs(text, { cwd, execSync });
247
+ if (opts.allowBang !== false && /!`[^`]+`/.test(text)) {
248
+ // Resolve and pin once before the first bang. Every expansion in this macro
249
+ // receives the same immutable policy object, so no earlier command can run
250
+ // before a later discovery failure or observe a weaker boundary set.
251
+ const sandboxPolicy = collectPluginBinSandboxPolicy({ cwd });
252
+ text = runBangs(text, { cwd, execSync, sandboxPolicy });
230
253
  }
231
254
 
232
255
  // @file expansion appends a <referenced-files> block when anything resolves.
@@ -915,8 +915,9 @@ export async function startAgentRepl(options = {}) {
915
915
  _pluginMonitors = null;
916
916
  }
917
917
 
918
- // Put trusted plugins' bin/ executables on PATH for the session (Phase 3.3n),
919
- // restored at SessionEnd. Trust-gated inside collectPluginBinDirs.
918
+ // Preserve PATH compatibility for trusted legacy bin components without a
919
+ // sandboxPolicy, restored at SessionEnd. Policy-bearing bins stay off PATH
920
+ // and use agent-core's exact direct Broker route.
920
921
  try {
921
922
  const { applyPluginBinPath } = await import("../lib/plugin-runtime/bin.js");
922
923
  const res = applyPluginBinPath({ cwd: process.cwd() });
@@ -3876,7 +3877,7 @@ export async function startAgentRepl(options = {}) {
3876
3877
  /* monitor restart is best-effort */
3877
3878
  }
3878
3879
 
3879
- // Re-apply plugin bin PATH (a newly-trusted plugin's executables).
3880
+ // Re-apply legacy plugin bin PATH; strict bins remain direct-only.
3880
3881
  try {
3881
3882
  const { applyPluginBinPath } =
3882
3883
  await import("../lib/plugin-runtime/bin.js");