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
@@ -114,6 +114,7 @@ import {
114
114
  handleArtifactShow,
115
115
  } from "./artifact-protocol.js";
116
116
  import { executionBroker } from "../../lib/process-execution-broker/index.js";
117
+ import { collectWorkspacePluginBinSandboxPolicy } from "../../lib/plugin-runtime/bin.js";
117
118
 
118
119
  export const _deps = {
119
120
  spawn: (...args) => executionBroker.spawn(...args),
@@ -1215,7 +1216,15 @@ export class ChainlessChainWSServer extends EventEmitter {
1215
1216
  if (this._taskManager) return this._taskManager;
1216
1217
  const { BackgroundTaskManager } =
1217
1218
  await import("../../harness/background-task-manager.js");
1218
- this._taskManager = new BackgroundTaskManager({ recoverOnStart: true });
1219
+ this._taskManager = new BackgroundTaskManager({
1220
+ recoverOnStart: true,
1221
+ policyCwd: this.projectRoot,
1222
+ resolveSandboxPolicy: ({ workspaceCwd, executionCwd }) =>
1223
+ collectWorkspacePluginBinSandboxPolicy({
1224
+ workspaceCwd,
1225
+ executionCwd,
1226
+ }),
1227
+ });
1219
1228
  this._subscribeTaskNotifications();
1220
1229
  return this._taskManager;
1221
1230
  }
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
12
- import { join } from "node:path";
12
+ import { join, resolve } from "node:path";
13
13
  import { createHash } from "node:crypto";
14
14
  import { EventEmitter } from "node:events";
15
15
  import { getHomeDir } from "../lib/paths.js";
@@ -42,9 +42,55 @@ const RECOVERABLE_TASK_STATUSES = new Set([
42
42
  TaskStatus.RUNNING,
43
43
  ]);
44
44
 
45
+ function validatePinnedSandboxPolicy(policy) {
46
+ if (policy == null) return null;
47
+ if (
48
+ typeof policy !== "object" ||
49
+ Array.isArray(policy) ||
50
+ typeof policy.then === "function" ||
51
+ !Array.isArray(policy.requiredBoundaries) ||
52
+ policy.requiredBoundaries.length === 0 ||
53
+ policy.requiredBoundaries.some(
54
+ (boundary) => typeof boundary !== "string" || boundary.length === 0,
55
+ ) ||
56
+ !Object.isFrozen(policy) ||
57
+ !Object.isFrozen(policy.requiredBoundaries)
58
+ ) {
59
+ const error = new TypeError("invalid_background_task_sandbox_policy");
60
+ error.code = "ERR_BACKGROUND_TASK_SANDBOX_POLICY_INVALID";
61
+ error.sandboxReason = "invalid_background_task_sandbox_policy";
62
+ error.sandboxFailClosed = true;
63
+ throw error;
64
+ }
65
+ return policy;
66
+ }
67
+
68
+ function createUnsupportedSandboxError(sandboxPolicy) {
69
+ const requiredBoundaries = [...sandboxPolicy.requiredBoundaries];
70
+ const error = new Error(
71
+ `Background tasks cannot run without their required sandbox boundaries: ${requiredBoundaries.join(", ")}`,
72
+ );
73
+ error.code = "ERR_BACKGROUND_TASK_SANDBOX_UNSUPPORTED";
74
+ error.sandboxReason = "background_execution_unsupported";
75
+ error.sandboxFailClosed = true;
76
+ error.requiredBoundaries = requiredBoundaries;
77
+ error.actualGuarantees = [];
78
+ error.missingBoundaries = [...requiredBoundaries];
79
+ error.sandboxBackend = null;
80
+ error.sandboxCandidateBackend = null;
81
+ return error;
82
+ }
83
+
45
84
  export class BackgroundTaskManager extends EventEmitter {
46
85
  constructor(options = {}) {
47
86
  super();
87
+ const resolveSandboxPolicy = options.resolveSandboxPolicy ?? null;
88
+ if (
89
+ resolveSandboxPolicy !== null &&
90
+ typeof resolveSandboxPolicy !== "function"
91
+ ) {
92
+ throw new TypeError("resolveSandboxPolicy must be a function or null");
93
+ }
48
94
  this.maxConcurrent = options.maxConcurrent || 3;
49
95
  this.heartbeatTimeout = options.heartbeatTimeout || 60000;
50
96
  this.historyLimit = options.historyLimit || 50;
@@ -54,6 +100,10 @@ export class BackgroundTaskManager extends EventEmitter {
54
100
  `${process.pid}@${process.platform}`;
55
101
  this.recoveryPolicy = options.recoveryPolicy || "claim-stale";
56
102
  this.staleNodeTimeout = options.staleNodeTimeout || 5 * 60 * 1000;
103
+ this._policyCwd = resolveSandboxPolicy
104
+ ? resolve(options.policyCwd || process.cwd())
105
+ : null;
106
+ this._resolveSandboxPolicy = resolveSandboxPolicy;
57
107
  this.tasks = new Map();
58
108
  this.processes = new Map();
59
109
  this._checkInterval = null;
@@ -72,12 +122,15 @@ export class BackgroundTaskManager extends EventEmitter {
72
122
  );
73
123
  }
74
124
 
125
+ const cwd = spec.cwd || process.cwd();
126
+ this._assertSandboxSupported(cwd);
127
+
75
128
  const id = `task-${Date.now()}-${createHash("sha256").update(Math.random().toString()).digest("hex").slice(0, 6)}`;
76
129
  const task = {
77
130
  id,
78
131
  type: spec.type || "shell",
79
132
  command: spec.command,
80
- cwd: spec.cwd || process.cwd(),
133
+ cwd,
81
134
  description: spec.description || spec.command,
82
135
  status: TaskStatus.PENDING,
83
136
  createdAt: Date.now(),
@@ -111,6 +164,8 @@ export class BackgroundTaskManager extends EventEmitter {
111
164
  throw new Error(`Task ${taskId} is not pending (status: ${task.status})`);
112
165
  }
113
166
 
167
+ this._assertSandboxSupported(task.cwd);
168
+
114
169
  task.status = TaskStatus.RUNNING;
115
170
  task.startedAt = Date.now();
116
171
  task.lastHeartbeat = Date.now();
@@ -185,6 +240,19 @@ export class BackgroundTaskManager extends EventEmitter {
185
240
  return task;
186
241
  }
187
242
 
243
+ _assertSandboxSupported(executionCwd) {
244
+ if (!this._resolveSandboxPolicy) return;
245
+ const sandboxPolicy = validatePinnedSandboxPolicy(
246
+ this._resolveSandboxPolicy({
247
+ workspaceCwd: this._policyCwd,
248
+ executionCwd,
249
+ }),
250
+ );
251
+ if (sandboxPolicy) {
252
+ throw createUnsupportedSandboxError(sandboxPolicy);
253
+ }
254
+ }
255
+
188
256
  get(taskId) {
189
257
  return this.tasks.get(taskId) || null;
190
258
  }
@@ -456,7 +456,11 @@ export function previewWorktreeMerge(repoDir, branchName, options = {}) {
456
456
 
457
457
  let mergeStarted = false;
458
458
  try {
459
- gitExec(`merge ${baseBranch} --no-commit --no-ff`, worktree.path);
459
+ // Use argv form here rather than routing through a shell. Besides avoiding
460
+ // another quoting surface, this is important on Windows where a conflicted
461
+ // `git merge` followed immediately by another shell-wrapped git process can
462
+ // race the hosted runner's process/job cleanup and hide the unmerged index.
463
+ gitExecArgs(["merge", baseBranch, "--no-commit", "--no-ff"], worktree.path);
460
464
  mergeStarted = true;
461
465
 
462
466
  return {
@@ -713,7 +717,14 @@ function _hasBranchCommits(repoDir, branchName) {
713
717
 
714
718
  function _collectConflictFiles(repoDir) {
715
719
  try {
716
- const output = gitExec("diff --name-only --diff-filter=U", repoDir);
720
+ // A conflict is expected to make the preceding merge exit non-zero. Query
721
+ // the index with a direct git argv invocation so Windows shell/process
722
+ // teardown cannot turn the authoritative conflict probe into an empty
723
+ // best-effort result.
724
+ const output = gitExecArgs(
725
+ ["diff", "--name-only", "--diff-filter=U"],
726
+ repoDir,
727
+ );
717
728
  return output
718
729
  .split("\n")
719
730
  .map((line) => line.trim())
@@ -988,7 +999,7 @@ function _resolveAutomationCandidate(type, filePath, branchName, candidateId) {
988
999
 
989
1000
  function _abortMergeIfPresent(repoDir) {
990
1001
  try {
991
- gitExec("merge --abort", repoDir);
1002
+ gitExecArgs(["merge", "--abort"], repoDir);
992
1003
  } catch (_e) {
993
1004
  // Ignore if there is no in-progress merge.
994
1005
  }
@@ -12,6 +12,7 @@ export {
12
12
  getAgentToolDefinitions,
13
13
  getAgentToolDescriptors,
14
14
  getCachedPython,
15
+ _resetCachedPythonForTests,
15
16
  getEnvironmentInfo,
16
17
  _environmentProcessDeps,
17
18
  _agentToolProcessDeps,
@@ -48,6 +48,14 @@ function normalizeJitterMs(v) {
48
48
  return Number.isFinite(n) && n > 0 ? n : 0;
49
49
  }
50
50
 
51
+ function normalizeMonitorWorkspaceCwd(value) {
52
+ if (value == null) return null;
53
+ if (typeof value !== "string" || value.length === 0) {
54
+ throw new Error("monitor workspaceCwd must be a non-empty string");
55
+ }
56
+ return path.resolve(value);
57
+ }
58
+
51
59
  /**
52
60
  * A per-task execution policy for wakeup/cron entries — how the spawned
53
61
  * `cc agent` run should behave when this entry fires. Each field maps to a real
@@ -388,6 +396,7 @@ export class AgentScheduleStore {
388
396
 
389
397
  createMonitor({
390
398
  command,
399
+ workspaceCwd = null,
391
400
  watchFile = null,
392
401
  watchUrl = null,
393
402
  watchChange = false,
@@ -443,16 +452,22 @@ export class AgentScheduleStore {
443
452
  if (stopWhen != null) {
444
453
  // Validate the regex up-front so a bad pattern errors at creation, not
445
454
  // silently at the first check.
446
- // eslint-disable-next-line no-new
455
+
447
456
  new RegExp(stopWhen);
448
457
  }
449
458
  const now = this._now();
450
459
  const source = hasFile ? "file" : hasUrl ? "http" : "command";
460
+ const normalizedWorkspaceCwd = hasCommand
461
+ ? normalizeMonitorWorkspaceCwd(workspaceCwd)
462
+ : null;
451
463
  const entry = {
452
464
  id: randomUUID(),
453
465
  kind: "monitor",
454
466
  source,
455
467
  command: hasCommand ? command : null,
468
+ ...(normalizedWorkspaceCwd
469
+ ? { workspaceCwd: normalizedWorkspaceCwd }
470
+ : {}),
456
471
  watchFile: hasFile ? watchFile : null,
457
472
  watchUrl: hasUrl ? watchUrl : null,
458
473
  watchChange: hasFile ? Boolean(watchChange) : false,
@@ -513,28 +528,36 @@ export class AgentScheduleStore {
513
528
  const now = atMs != null ? Number(atMs) : this._now();
514
529
  const ttl = Math.max(1000, Number(leaseMs) || 120000);
515
530
  this._ensureDir();
516
- return withFileLock(path.join(this.dir, ".agenda-claims"), () => {
517
- const claimed = [];
518
- for (const kind of SCHEDULE_KINDS) {
519
- const entries = this._readAll(kind);
520
- let changed = false;
521
- for (const entry of entries) {
522
- if (!isSchedulableStatus(entry) || isEntryExpired(entry, now)) continue;
523
- if (hasLiveExecutionLease(entry, now)) continue;
524
- const fireAt = effectiveFireAt(entry);
525
- if (fireAt == null || fireAt > now) continue;
526
- entry.executionLease = {
527
- owner: `${process.pid}:${randomUUID()}`,
528
- claimedAt: now,
529
- expiresAt: now + ttl,
530
- };
531
- claimed.push({ ...entry, executionLease: { ...entry.executionLease } });
532
- changed = true;
531
+ return withFileLock(
532
+ path.join(this.dir, ".agenda-claims"),
533
+ () => {
534
+ const claimed = [];
535
+ for (const kind of SCHEDULE_KINDS) {
536
+ const entries = this._readAll(kind);
537
+ let changed = false;
538
+ for (const entry of entries) {
539
+ if (!isSchedulableStatus(entry) || isEntryExpired(entry, now))
540
+ continue;
541
+ if (hasLiveExecutionLease(entry, now)) continue;
542
+ const fireAt = effectiveFireAt(entry);
543
+ if (fireAt == null || fireAt > now) continue;
544
+ entry.executionLease = {
545
+ owner: `${process.pid}:${randomUUID()}`,
546
+ claimedAt: now,
547
+ expiresAt: now + ttl,
548
+ };
549
+ claimed.push({
550
+ ...entry,
551
+ executionLease: { ...entry.executionLease },
552
+ });
553
+ changed = true;
554
+ }
555
+ if (changed) this._writeAll(kind, entries);
533
556
  }
534
- if (changed) this._writeAll(kind, entries);
535
- }
536
- return claimed;
537
- }, { failIfUnavailable: true });
557
+ return claimed;
558
+ },
559
+ { failIfUnavailable: true },
560
+ );
538
561
  }
539
562
 
540
563
  /** Release a failed/aborted claim so a later runner can retry it. */
@@ -35,8 +35,12 @@ function runHookProcessSync(file, argsOrOptions, maybeOptions) {
35
35
  });
36
36
  }
37
37
 
38
- runner._deps.run = runHookProcess;
39
- runner._deps.runSync = runHookProcessSync;
38
+ export function _restoreProcessRunners() {
39
+ runner._deps.run = runHookProcess;
40
+ runner._deps.runSync = runHookProcessSync;
41
+ }
42
+
43
+ _restoreProcessRunners();
40
44
 
41
45
  export const {
42
46
  runCommandHook,
@@ -385,7 +385,9 @@ export function generatePkgConfig(ctx) {
385
385
  const assets = [
386
386
  `${posixify(distDir)}/**/*`,
387
387
  `${posixify(templatesDir)}/**/*`,
388
- `${posixify(cliRoot)}/src/lib/process-execution-broker/*.ps1`,
388
+ `${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox-helper.dll`,
389
+ `${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox-helper.exe`,
390
+ `${posixify(cliRoot)}/src/lib/process-execution-broker/windows-sandbox.cs`,
389
391
  ];
390
392
  if (prebuildsDir) assets.push(`${posixify(prebuildsDir)}/**/*`);
391
393
  // Project mode: bundle the collected .chainlesschain/ snapshot as an asset.