chainlesschain 0.162.177 → 0.162.178

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 (207) hide show
  1. package/README.md +10 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DT-VPWuN.js → AIOps-DRftcSue.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-DyOreOVN.js → ActionButton-BFvUaMKR.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DslNsKux.js → Analytics-C0-Rru4P.js} +3 -3
  7. package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
  8. package/src/assets/web-panel/assets/{Artifacts-DoaAtEcY.js → Artifacts-DAJ8B3Un.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DPG3WdJ9.js → Audit-hOk4L1lr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-C_JO6R5G.js → BackgroundAgents-3pbDpM9z.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-Cv3BooyX.js → Backup-BtziGDn9.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-D2uQXWu-.js → BaseInput-kmshphJ3.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B4Vczyf3.js → Chat-d7tGSosA.js} +5 -5
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-p-_PBpX_.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-qTgk4VeP.js → Checkbox-C4Eh4Tz5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DlLWcIzj.js → Codegen-r7gmhZyA.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-DNO73qp7.js → Col-U7mDaGlL.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-vRDNpc4j.js → Community-Bpu8aH1T.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-CEWtIXni.js → Compact-CHb2XBJe.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-KgYC9Fxi.js → Compliance-Cn_r4dey.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-zj5wvkpT.js → Cowork-CdMWfDcz.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-BLDoCozU.js → Cron-BtnREHWy.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BYnff4VY.js → Crosschain-BKI9TSzr.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-C75VFsVm.js → DID-pkNubzzJ.js} +2 -2
  25. package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
  26. package/src/assets/web-panel/assets/{Dropdown-B5dbO4Kx.js → Dropdown-DLyFVxDc.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-BDipZtHJ.js → EmailListRenderer-CtUWfYVq.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DmIzt8jj.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-D9QOS-uW.js → Federation-D8lsDGus.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-B47HRwAm.js → FormItemContext-CRYt_aIw.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-3R4mXmgV.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DrNXZf1C.js → Git-BXj5Dney.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BGd7JR98.js → Governance-Cm-I8RMz.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-D-2he1ed.js → Inference-CPvbhvgt.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-C0sHIbK5.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-DiBQO-jL.js → Logs-BZY_3CRZ.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-DL_5eV2D.js → MarkdownRenderer-up0BW6pv.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-VR59OdrC.js → Marketplace-C5MEJ2Qe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DrPzwSd3.js → McpTools-ihdrn43I.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-CBgKALwQ.js → Memory-Br8bPMlh.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-pQ9Tn-Mn.js → MobileBridge-BNntgrYW.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-mASB6jyj.js → MobileProjects-BdV915mw.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-DTMgE7HC.js → Mtc-A3wDmlqL.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-CwTnCtiL.js → MtcAudit-CF-mBLWM.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-ngm6WU8f.js → Multisig-Iy2k_MSo.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-4YO4Qww9.js → NLProgramming-kk0W7HUb.js} +1 -1
  47. package/src/assets/web-panel/assets/Notes-B5u5t_4S.js +7 -0
  48. package/src/assets/web-panel/assets/{NotificationSettings-r2H8yPKb.js → NotificationSettings-BN0POf6_.js} +1 -1
  49. package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
  50. package/src/assets/web-panel/assets/{Organization-DrO7jRWS.js → Organization-DwWQESuN.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-Cnwu4i4t.js → Overflow-DG6klrcC.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-zi-cDwA_.js → P2P-BwJcKkgZ.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-DBEryDv7.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-lqXK2C3x.js → Permissions-CGMXe4TX.js} +4 -4
  55. package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
  56. package/src/assets/web-panel/assets/{Pipeline-Kep5KAGW.js → Pipeline-BzJfeoGt.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-CHdvOAh1.js → Privacy-DLh3Bblx.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-BhKfdwe9.js → ProjectInit-USVWW36c.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Yavk9K8A.js → ProjectSettings-CiiOn62h.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-Bfym6SQn.js → Providers-CBPWWzpu.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-CLSQcrlR.js → QrScannerModal-QVwoRUq3.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-VPa2WKQN.js → QuickAsk-CXnR-2Vn.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-CGXR8jVU.js → Recommend-ClaNzjmF.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-C_20YfMB.js → RemoteSession-C3rGw8vJ.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-awZh68UV.js → Reputation-Ci-OWAoP.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-Ctb4oiYN.js → Row-DRhAwXOS.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-D3sdjvUV.js → RssFeed-BQLJQ2_y.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-C-zfA4kT.js → Search-QQUpkfFd.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-D9XlmHA3.js → Security-DdXKzuKT.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-C3UKnr41.js → Services-x2Zh62Qd.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-BQxagZfF.js → Skeleton-GdY4KwRz.js} +1 -1
  73. package/src/assets/web-panel/assets/Skills-Bv4tY1Fd.js +1 -0
  74. package/src/assets/web-panel/assets/{Sla-DveENvek.js → Sla-C3QnM-11.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-BFjXLNgF.js → SpeechSettings-Bl3ytvmI.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-BpHgbaP9.js → SyncSettings-Wp9IwTsP.js} +2 -2
  77. package/src/assets/web-panel/assets/Tasks-CF3rIrDe.js +1 -0
  78. package/src/assets/web-panel/assets/{Templates-DEiaoyve.js → Templates-CGfvVVM9.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-ITg774nY.js → Tenant-CVXmwQ3U.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-D3ZBcvnb.js → Terminal-bvwrt03E.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BsLU6JjU.js → TimelineRenderer-D0g74KhH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-Cb5Pquc9.js → Tokens-BH4IwzlT.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-Dwfy-m9N.js → Trigger-DJOpM533.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CnlSRGG0.js → Trust-B43EPRLr.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-Y4TlvKVo.js → UkeySign-BmBFG-em.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-BpKLtTTO.js → VideoEditing-n9oJwB8k.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-LLBzIq8x.js → Wallet-D5QeivHp.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-BeSRiusP.js → WebAuthn-DcNy7igO.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-BK_l1tXO.js → WorkflowEditor-BVjc7-5-.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-DYd-X7Wg.js → chat-Dy5Tfj3m.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-C9uip71j.js → colors-C4c2CNZU.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-JBrfjUP6.js → compact-item-DPa3O5vN.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-D03fbuiq.js → createContext-TLcfNA6_.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DLQOR6l-.js → hasIn-D41LVFkp.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-rIxxfdTN.js → index-0oevYjfT.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CChaISMb.js → index-388pLGJ1.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BfOs_bmg.js → index-B8nLBZbv.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-D-1SqEpQ.js → index-BPTGAjee.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BYv-LWdy.js → index-BPtrOBmW.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Cpn19c9k.js → index-BQiIxHBy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BpYKLrUT.js → index-BSM1cHVK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CS63r8h3.js → index-BYPr9fkz.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Q7mmL6w4.js → index-BsQ7Ev6i.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-SO6lgMg0.js → index-Btk9qLL2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-iahNhZwm.js → index-BvmziZSG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BnQgRjsm.js → index-BvopLC_T.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Ba-Ps_AJ.js → index-C7xhTVyP.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BuNFCZCx.js → index-CNk_ZooP.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CL0ixCxk.js → index-CQrEHoOG.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CChQBM1d.js → index-CSxex23J.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-5YN7F5bO.js → index-CVjgm992.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CwoDpKzW.js → index-CWK4zOPe.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BcBZwlnG.js → index-CX0VsoP4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B46YcgsV.js → index-CXl0YPNG.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-l08afIbV.js → index-Cip7LWml.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-6GuLRpBQ.js → index-Cq_hlWNt.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DYLZY4uh.js → index-CzZ49YZL.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B0X76LjX.js → index-D2Nkivlm.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BdH9l8wl.js → index-DBUgRs4D.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
  122. package/src/assets/web-panel/assets/{index-D4UY5Z60.js → index-DNsBj2Ob.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Ce0Bf1YF.js → index-Di4X8cfI.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ByHO3SqZ.js → index-DljFsVGI.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C2zmOsyD.js → index-Korc3QIe.js} +1 -1
  126. package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
  127. package/src/assets/web-panel/assets/{index-BNCdRmWf.js → index-MKZDje0H.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-D8KvuDz0.js → index-OHAfRu_3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DaokIHt3.js → index-WEJr8PL5.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CILVyK3b.js → index-WinCp6du.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CVZWiUE_.js → index-Yjr6cqSK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CqWk1FLG.js → index-iQ6gtFih.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DNMAAUVk.js → index-pt3s7yvV.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Ck17i0OD.js → index-tQ3igERQ.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-CG9z1c6w.js → initDefaultProps-BFZu87WZ.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-B1Ky7Zff.js → motion-DJIo7qvt.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DME8X2P1.js → move-Cfr5qknL.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-cuJYSWB7.js → mtc-parser-Bgc-OadH.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-UI_EE0uZ.js → omit-X3WI-TNp.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-BIoE_Z_V.js → pickAttrs-pJhU9IxK.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-B48-9HKN.js → placementArrow-BNg_Vj3T.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-D7x_GDgD.js → responsiveObserve-TeSEGQ5-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-DjzC5_7m.js → slide-D_t_P0bv.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-C6BIymhh.js → statusUtils-DrrIMwAT.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-B4dGrdD9.js → styleChecker-BjZCuFRm.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-Bken4aNE.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-BMlqECqv.js → useFs-BidCpfLX.js} +1 -1
  148. package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
  149. package/src/assets/web-panel/assets/{vnode-CKJQmxa0.js → vnode-BrbcRiHZ.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-CaZunuau.js → zoom-PISX7AkR.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/commands/__tests__/hub-wechat.test.js +45 -0
  153. package/src/commands/background-session.js +5 -2
  154. package/src/commands/context.js +33 -1
  155. package/src/commands/hub.js +473 -39
  156. package/src/commands/init.js +212 -110
  157. package/src/commands/llm.js +22 -6
  158. package/src/commands/skill.js +11 -1
  159. package/src/data/changelog.json +76 -270
  160. package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
  161. package/src/harness/golden-transcript.js +3 -0
  162. package/src/index.js +18 -7
  163. package/src/lib/approval-authority-store.js +891 -0
  164. package/src/lib/background-interaction-resolver.js +399 -54
  165. package/src/lib/background-session-transport.js +3 -1
  166. package/src/lib/context-breakdown.js +82 -3
  167. package/src/lib/event-runtime-host.js +225 -0
  168. package/src/lib/event-runtime-store.js +102 -21
  169. package/src/lib/event-runtime-worker.js +70 -2
  170. package/src/lib/hooks-v2-producers.js +33 -8
  171. package/src/lib/hooks-v2-runtime.js +360 -40
  172. package/src/lib/interaction-adapter.js +66 -0
  173. package/src/lib/operation-fingerprint.js +107 -2
  174. package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
  175. package/src/lib/personal-data-hub-wiring.js +327 -52
  176. package/src/lib/process-execution-broker/credential-agent.js +954 -111
  177. package/src/lib/process-execution-broker/index.js +369 -85
  178. package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
  179. package/src/lib/provider-http-error.js +94 -0
  180. package/src/lib/remote-approval-bridge.js +222 -26
  181. package/src/lib/side-effect-ledger-store.js +65 -14
  182. package/src/lib/skill-loader.js +215 -12
  183. package/src/lib/skill-process-broker.js +15 -1
  184. package/src/lib/sub-agent-context.js +42 -0
  185. package/src/lib/turn-binding-store.js +64 -15
  186. package/src/lib/turn-binding.js +85 -16
  187. package/src/repl/agent-repl.js +40 -6
  188. package/src/repl/remote-approval.js +13 -13
  189. package/src/repl/repl-turn-binding.js +46 -16
  190. package/src/runtime/agent-core.js +286 -35
  191. package/src/runtime/coding-agent-contract-shared.cjs +16 -0
  192. package/src/runtime/headless-runner.js +147 -34
  193. package/src/runtime/headless-stream.js +147 -7
  194. package/src/workers/background-agent-worker.js +70 -38
  195. package/src/assets/web-panel/assets/AppLayout-BNJJAYME.js +0 -9
  196. package/src/assets/web-panel/assets/ChatBubbleRenderer-DE6reP99.js +0 -1
  197. package/src/assets/web-panel/assets/Dashboard-C4Gutni2.js +0 -3
  198. package/src/assets/web-panel/assets/Notes-DP1k45mF.js +0 -7
  199. package/src/assets/web-panel/assets/OrderTableRenderer-CoM_Zw0J.js +0 -1
  200. package/src/assets/web-panel/assets/PersonalDataHub-b63T3HJM.js +0 -9
  201. package/src/assets/web-panel/assets/Projects-CN8E_5Mq.js +0 -1
  202. package/src/assets/web-panel/assets/Skills-q6eb6KPZ.js +0 -1
  203. package/src/assets/web-panel/assets/Tasks-DvepRb8-.js +0 -1
  204. package/src/assets/web-panel/assets/devWarning-B8LQ8leS.js +0 -1
  205. package/src/assets/web-panel/assets/index-Bh8BPtqR.js +0 -1
  206. package/src/assets/web-panel/assets/index-CeVrHLzZ.js +0 -1
  207. package/src/assets/web-panel/assets/usePersonalDataHub-DLdrfmMa.js +0 -1
@@ -4,7 +4,8 @@
4
4
  *
5
5
  * 统一拦截所有子进程执行:
6
6
  * - M1: 所有子进程唯一入口,权限检查
7
- * - **P0-1**: 三平台原生沙箱 (macOS Seatbelt / Windows Job Object / Linux seccomp)
7
+ * - **P0-1**: 可审计的平台执行计划(macOS Seatbelt / Linux prlimit;
8
+ * Windows 原生 Job Object 未实现时明确报告 unavailable)
8
9
  * - **P0-1**: 凭据代理 default-on(secrets 永远不裸传给子进程)
9
10
  * - M3: 集成W3C trace context自动传播
10
11
  * - M4: 自动写入Runtime Provenance Ledger (RPL)
@@ -25,7 +26,7 @@ import { EventEmitter } from "node:events";
25
26
  import crypto from "node:crypto";
26
27
  import os from "node:os";
27
28
  import path from "node:path";
28
- import fs from "node:fs";
29
+ import * as fs from "node:fs";
29
30
  import { createRequire } from "node:module";
30
31
 
31
32
  const require = createRequire(import.meta.url);
@@ -110,6 +111,10 @@ class ProcessExecutionBroker extends EventEmitter {
110
111
  // plugin path use the same switches as the general broker path.
111
112
  this._credentialAgentEnabled = true;
112
113
  this._platformSandboxEnabled = true;
114
+ this._sandboxAdapter = {
115
+ applySandbox: _applySandbox,
116
+ postSpawnSandbox: _postSpawnSandbox,
117
+ };
113
118
 
114
119
  this._ensureLogDir();
115
120
  this._loadPermissions();
@@ -118,7 +123,9 @@ class ProcessExecutionBroker extends EventEmitter {
118
123
  _ensureLogDir() {
119
124
  try {
120
125
  fs.mkdirSync(path.dirname(this._logPath), { recursive: true });
121
- } catch {}
126
+ } catch {
127
+ // Audit persistence is best-effort; in-memory audit remains available.
128
+ }
122
129
  }
123
130
 
124
131
  _loadPermissions() {
@@ -167,7 +174,9 @@ class ProcessExecutionBroker extends EventEmitter {
167
174
  (this._stats.byOrigin[entry.origin] || 0) + 1;
168
175
  try {
169
176
  fs.appendFileSync(this._logPath, JSON.stringify(entry) + "\n");
170
- } catch {}
177
+ } catch {
178
+ // Audit persistence is best-effort; the in-memory entry is retained.
179
+ }
171
180
  this.emit("spawn", entry);
172
181
  }
173
182
 
@@ -180,6 +189,283 @@ class ProcessExecutionBroker extends EventEmitter {
180
189
  return safe;
181
190
  }
182
191
 
192
+ _sandboxStrictEnabled() {
193
+ return process.env.CC_SANDBOX_STRICT === "1";
194
+ }
195
+
196
+ _sandboxDisabledByEnvironment() {
197
+ return process.env.CC_SANDBOX_DISABLE === "1";
198
+ }
199
+
200
+ _sandboxUnavailablePlan(command, args, options, reason) {
201
+ return {
202
+ contractVersion: 1,
203
+ applied: false,
204
+ platform: process.platform,
205
+ profile: "default",
206
+ command,
207
+ args: [...(args || [])],
208
+ options: { ...options },
209
+ enforcement: null,
210
+ reason,
211
+ postSpawn: { required: false, mode: "none" },
212
+ };
213
+ }
214
+
215
+ _sandboxError(reason, message = reason) {
216
+ const error = new Error(message);
217
+ error.code = "ERR_PROCESS_SANDBOX";
218
+ error.sandboxReason = reason;
219
+ return error;
220
+ }
221
+
222
+ _validateSandboxPlan(plan) {
223
+ if (!plan || typeof plan !== "object") {
224
+ throw this._sandboxError(
225
+ "invalid_sandbox_plan",
226
+ "Sandbox adapter returned no spawn plan",
227
+ );
228
+ }
229
+ if (plan.contractVersion !== 1) {
230
+ throw this._sandboxError(
231
+ "invalid_sandbox_plan",
232
+ "Sandbox spawn plan contractVersion must be 1",
233
+ );
234
+ }
235
+ if (typeof plan.applied !== "boolean") {
236
+ throw this._sandboxError(
237
+ "invalid_sandbox_plan",
238
+ "Sandbox spawn plan is missing applied:boolean",
239
+ );
240
+ }
241
+ if (typeof plan.command !== "string" || !Array.isArray(plan.args)) {
242
+ throw this._sandboxError(
243
+ "invalid_sandbox_plan",
244
+ "Sandbox spawn plan must provide command and args",
245
+ );
246
+ }
247
+ if (!plan.options || typeof plan.options !== "object") {
248
+ throw this._sandboxError(
249
+ "invalid_sandbox_plan",
250
+ "Sandbox spawn plan must provide options",
251
+ );
252
+ }
253
+ if (plan.applied && typeof plan.enforcement !== "string") {
254
+ throw this._sandboxError(
255
+ "invalid_sandbox_plan",
256
+ "Applied sandbox spawn plan must name its enforcement",
257
+ );
258
+ }
259
+ if (!plan.applied && typeof plan.reason !== "string") {
260
+ throw this._sandboxError(
261
+ "invalid_sandbox_plan",
262
+ "Unavailable sandbox spawn plan must provide a reason",
263
+ );
264
+ }
265
+ const postSpawn = plan.postSpawn || { required: false, mode: "none" };
266
+ if (
267
+ postSpawn.required &&
268
+ postSpawn.mode !== "sync" &&
269
+ postSpawn.mode !== "async"
270
+ ) {
271
+ throw this._sandboxError(
272
+ "invalid_sandbox_plan",
273
+ "Required post-spawn enforcement must declare sync or async mode",
274
+ );
275
+ }
276
+ return {
277
+ ...plan,
278
+ args: [...plan.args],
279
+ options: { ...plan.options },
280
+ postSpawn: { ...postSpawn },
281
+ };
282
+ }
283
+
284
+ _prepareSandboxPlan(command, args, options, { sync = false } = {}) {
285
+ const strict = this._sandboxStrictEnabled();
286
+ let disabledReason = null;
287
+ if (this._sandboxDisabledByEnvironment()) {
288
+ disabledReason = "disabled_by_environment";
289
+ } else if (
290
+ this._sandboxEnabled === false ||
291
+ this._platformSandboxEnabled === false
292
+ ) {
293
+ disabledReason = "disabled_by_broker";
294
+ }
295
+
296
+ if (disabledReason) {
297
+ if (strict) {
298
+ throw this._sandboxError(
299
+ disabledReason,
300
+ `Sandbox is unavailable in strict mode: ${disabledReason}`,
301
+ );
302
+ }
303
+ return this._sandboxUnavailablePlan(
304
+ command,
305
+ args,
306
+ options,
307
+ disabledReason,
308
+ );
309
+ }
310
+
311
+ const plan = this._validateSandboxPlan(
312
+ this._sandboxAdapter.applySandbox(
313
+ command,
314
+ args || [],
315
+ options,
316
+ "default",
317
+ ),
318
+ );
319
+
320
+ if (!plan.applied && strict) {
321
+ throw this._sandboxError(
322
+ plan.reason || "sandbox_unavailable",
323
+ `Sandbox is unavailable in strict mode: ${
324
+ plan.reason || "unknown reason"
325
+ }`,
326
+ );
327
+ }
328
+
329
+ if (plan.applied && plan.postSpawn.required) {
330
+ if (typeof this._sandboxAdapter.postSpawnSandbox !== "function") {
331
+ throw this._sandboxError(
332
+ "post_spawn_adapter_unavailable",
333
+ "Required post-spawn sandbox adapter is unavailable",
334
+ );
335
+ }
336
+ if (sync) {
337
+ throw this._sandboxError(
338
+ "post_spawn_unavailable_for_sync",
339
+ "spawnSync cannot satisfy required post-spawn sandbox enforcement",
340
+ );
341
+ }
342
+ if (strict && plan.postSpawn.mode !== "sync") {
343
+ throw this._sandboxError(
344
+ "async_post_spawn_disallowed_in_strict_mode",
345
+ "Strict sandbox mode requires synchronous post-spawn enforcement",
346
+ );
347
+ }
348
+ }
349
+ return plan;
350
+ }
351
+
352
+ _applySandboxAudit(auditEntry, plan, applied) {
353
+ auditEntry.sandboxed = applied;
354
+ auditEntry.sandboxProfile = plan?.profile || null;
355
+ auditEntry.sandboxEnforcement = applied
356
+ ? plan?.enforcement || "platform"
357
+ : null;
358
+ auditEntry.sandboxReason = applied ? null : plan?.reason || null;
359
+ auditEntry.sandboxState = applied ? "ready" : "unavailable";
360
+ }
361
+
362
+ _recordSandboxDenial(auditEntry, error, startTime) {
363
+ auditEntry.permissionDecision = "deny";
364
+ auditEntry.sandboxed = false;
365
+ auditEntry.sandboxState = "denied";
366
+ auditEntry.sandboxReason =
367
+ error.sandboxReason || "sandbox_initialization_failed";
368
+ auditEntry.deniedReason = `sandbox-init-failed: ${error.message}`;
369
+ auditEntry.endTime = Date.now();
370
+ auditEntry.durationMs = auditEntry.endTime - startTime;
371
+ this._recordAudit(auditEntry);
372
+ this._writeRplEntry(auditEntry, "denied", error);
373
+ }
374
+
375
+ _scheduleSandboxCleanup(proc, cleanup) {
376
+ if (typeof cleanup !== "function") return () => {};
377
+ let cleaned = false;
378
+ const run = () => {
379
+ if (cleaned) return;
380
+ cleaned = true;
381
+ cleanup();
382
+ };
383
+ if (proc && typeof proc.once === "function") {
384
+ proc.once("error", run);
385
+ proc.once("exit", run);
386
+ }
387
+ return run;
388
+ }
389
+
390
+ _runPostSpawnSandbox(proc, plan, auditEntry) {
391
+ if (!plan.applied || !plan.postSpawn.required) {
392
+ this._applySandboxAudit(auditEntry, plan, plan.applied);
393
+ if (plan.applied) this._stats.sandboxed++;
394
+ const ready = Promise.resolve({ applied: plan.applied });
395
+ proc.sandboxReady = ready;
396
+ return;
397
+ }
398
+
399
+ let postSpawnResult;
400
+ try {
401
+ postSpawnResult = this._sandboxAdapter.postSpawnSandbox(proc, plan);
402
+ } catch (error) {
403
+ this._applySandboxAudit(auditEntry, plan, false);
404
+ auditEntry.sandboxState = "failed";
405
+ auditEntry.sandboxReason = `post_spawn_failed: ${error.message}`;
406
+ if (this._sandboxStrictEnabled()) {
407
+ if (typeof proc.once === "function") proc.once("error", () => {});
408
+ try {
409
+ proc.kill?.();
410
+ } catch {
411
+ // The sandbox failure remains fatal even if the child already exited.
412
+ }
413
+ throw this._sandboxError(
414
+ "post_spawn_failed",
415
+ `Post-spawn sandbox setup failed: ${error.message}`,
416
+ );
417
+ }
418
+ process.emitWarning(
419
+ `Post-spawn sandbox setup failed (continuing without): ${error.message}`,
420
+ );
421
+ proc.sandboxReady = Promise.resolve({ applied: false, error });
422
+ return;
423
+ }
424
+
425
+ if (postSpawnResult && typeof postSpawnResult.then === "function") {
426
+ if (this._sandboxStrictEnabled()) {
427
+ Promise.resolve(postSpawnResult).catch(() => {});
428
+ if (typeof proc.once === "function") proc.once("error", () => {});
429
+ try {
430
+ proc.kill?.();
431
+ } catch {
432
+ // The sandbox failure remains fatal even if the child already exited.
433
+ }
434
+ throw this._sandboxError(
435
+ "async_post_spawn_contract_violation",
436
+ "Strict sandbox adapter returned an asynchronous post-spawn result",
437
+ );
438
+ }
439
+ auditEntry.sandboxed = false;
440
+ auditEntry.sandboxState = "pending";
441
+ const ready = Promise.resolve(postSpawnResult).then(
442
+ () => {
443
+ this._applySandboxAudit(auditEntry, plan, true);
444
+ this._stats.sandboxed++;
445
+ return { applied: true };
446
+ },
447
+ (error) => {
448
+ this._applySandboxAudit(auditEntry, plan, false);
449
+ auditEntry.sandboxState = "failed";
450
+ auditEntry.sandboxReason = `post_spawn_failed: ${error.message}`;
451
+ process.emitWarning(
452
+ `Post-spawn sandbox setup failed (continuing without): ${error.message}`,
453
+ );
454
+ throw error;
455
+ },
456
+ );
457
+ // Keep failures observable to callers without creating an unhandled
458
+ // rejection when a legacy caller does not inspect sandboxReady.
459
+ ready.catch(() => {});
460
+ proc.sandboxReady = ready;
461
+ return;
462
+ }
463
+
464
+ this._applySandboxAudit(auditEntry, plan, true);
465
+ this._stats.sandboxed++;
466
+ proc.sandboxReady = Promise.resolve({ applied: true });
467
+ }
468
+
183
469
  _credentialBoundaryEnabled() {
184
470
  return (
185
471
  this._credentialFilteringEnabled !== false &&
@@ -293,7 +579,9 @@ class ProcessExecutionBroker extends EventEmitter {
293
579
  },
294
580
  auditEntry.origin,
295
581
  );
296
- } catch (e) {}
582
+ } catch {
583
+ // Provenance reporting must not hide the process execution result.
584
+ }
297
585
  }
298
586
 
299
587
  _emitHooksEvent(event, data) {
@@ -301,7 +589,9 @@ class ProcessExecutionBroker extends EventEmitter {
301
589
  if (!hooks || !hooks.hooksV2) return;
302
590
  try {
303
591
  hooks.hooksV2.emit(event, data);
304
- } catch {}
592
+ } catch {
593
+ // Hook reporting must not hide the process execution result.
594
+ }
305
595
  }
306
596
 
307
597
  spawn(command, args, options = {}) {
@@ -388,59 +678,57 @@ class ProcessExecutionBroker extends EventEmitter {
388
678
  }
389
679
 
390
680
  // P0-1: Platform sandbox wrapping — apply macOS/Windows/Linux sandbox
391
- const optsForSpawn = { ...spawnOpts };
392
- let sandboxApplied = false;
393
- let sandboxProfile = null;
394
- if (this._platformSandboxEnabled) {
395
- try {
396
- const result = _applySandbox(
397
- command,
398
- args || [],
399
- optsForSpawn,
400
- "default",
401
- );
402
- if (result && result.applied) {
403
- Object.assign(optsForSpawn, result.options || {});
404
- if (result.command) command = result.command;
405
- if (result.args) args = result.args;
406
- sandboxApplied = true;
407
- sandboxProfile = result.profile || null;
408
- this._stats.sandboxed++;
409
- }
410
- auditEntry.sandboxed = sandboxApplied;
411
- auditEntry.sandboxProfile = sandboxProfile;
412
- } catch (sandboxErr) {
413
- // Fail closed: if sandbox setup fails on strict, deny spawn
414
- if (process.env.CC_SANDBOX_STRICT === "1") {
415
- auditEntry.deniedReason = `sandbox-init-failed: ${sandboxErr.message}`;
416
- this._auditLog.push(auditEntry);
417
- const err = new Error(`Sandbox init failed: ${sandboxErr.message}`);
418
- err.auditEntry = auditEntry;
419
- throw err;
420
- }
421
- // Non-strict: warn but allow (development mode)
422
- process.emitWarning(
423
- `Sandbox init failed (continuing without): ${sandboxErr.message}`,
424
- );
681
+ let sandboxPlan;
682
+ try {
683
+ sandboxPlan = this._prepareSandboxPlan(command, args || [], spawnOpts);
684
+ } catch (sandboxErr) {
685
+ if (this._sandboxStrictEnabled()) {
686
+ this._recordSandboxDenial(auditEntry, sandboxErr, startTime);
687
+ sandboxErr.auditEntry = auditEntry;
688
+ throw sandboxErr;
425
689
  }
690
+ process.emitWarning(
691
+ `Sandbox init failed (continuing without): ${sandboxErr.message}`,
692
+ );
693
+ sandboxPlan = this._sandboxUnavailablePlan(
694
+ command,
695
+ args || [],
696
+ spawnOpts,
697
+ `sandbox_init_failed: ${sandboxErr.message}`,
698
+ );
426
699
  }
700
+ command = sandboxPlan.command;
701
+ args = [...sandboxPlan.args];
702
+ const optsForSpawn = { ...sandboxPlan.options };
703
+ this._applySandboxAudit(
704
+ auditEntry,
705
+ sandboxPlan,
706
+ sandboxPlan.applied && !sandboxPlan.postSpawn.required,
707
+ );
427
708
 
428
709
  // Use native spawn from _native (set by patch-child-process.js)
429
710
  const nativeSpawnFn = this._native?.spawn || nativeSpawn;
430
- const proc = nativeSpawnFn(command, args, optsForSpawn);
431
-
432
- // P0-1: Post-spawn sandbox setup (Windows Job Object association, etc.)
433
- if (sandboxApplied && proc.pid) {
434
- try {
435
- _postSpawnSandbox(proc, sandboxProfile);
436
- } catch (postErr) {
437
- process.emitWarning(
438
- `Post-spawn sandbox setup failed: ${postErr.message}`,
439
- );
440
- }
711
+ let proc;
712
+ try {
713
+ proc = nativeSpawnFn(command, args, optsForSpawn);
714
+ } catch (spawnError) {
715
+ sandboxPlan.cleanup?.();
716
+ throw spawnError;
441
717
  }
442
-
443
718
  auditEntry.pid = proc.pid;
719
+ const cleanupSandbox = this._scheduleSandboxCleanup(
720
+ proc,
721
+ sandboxPlan.cleanup,
722
+ );
723
+ try {
724
+ this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
725
+ } catch (postSpawnError) {
726
+ cleanupSandbox();
727
+ this._recordSandboxDenial(auditEntry, postSpawnError, startTime);
728
+ postSpawnError.auditEntry = auditEntry;
729
+ throw postSpawnError;
730
+ }
731
+
444
732
  this._recordAudit(auditEntry);
445
733
  this._writeRplEntry(auditEntry, "started");
446
734
  this._emitHooksEvent("tool:start", {
@@ -563,44 +851,36 @@ class ProcessExecutionBroker extends EventEmitter {
563
851
  }
564
852
 
565
853
  // P0-1: Platform sandbox wrapping (sync path)
566
- const optsForSync = { ...spawnOpts };
567
- let sandboxApplied = false;
568
- let sandboxProfile = null;
569
- if (this._platformSandboxEnabled) {
570
- try {
571
- const result = _applySandbox(
572
- command,
573
- args || [],
574
- optsForSync,
575
- "default",
576
- );
577
- if (result && result.applied) {
578
- Object.assign(optsForSync, result.options || {});
579
- if (result.command) command = result.command;
580
- if (result.args) args = result.args;
581
- sandboxApplied = true;
582
- sandboxProfile = result.profile || null;
583
- this._stats.sandboxed++;
584
- }
585
- auditEntry.sandboxed = sandboxApplied;
586
- auditEntry.sandboxProfile = sandboxProfile;
587
- } catch (sandboxErr) {
588
- if (process.env.CC_SANDBOX_STRICT === "1") {
589
- auditEntry.deniedReason = `sandbox-init-failed: ${sandboxErr.message}`;
590
- this._recordAudit(auditEntry);
591
- const err = new Error(`Sandbox init failed: ${sandboxErr.message}`);
592
- err.auditEntry = auditEntry;
593
- throw err;
594
- }
595
- process.emitWarning(
596
- `Sandbox init failed (sync): ${sandboxErr.message}`,
597
- );
854
+ let sandboxPlan;
855
+ try {
856
+ sandboxPlan = this._prepareSandboxPlan(command, args || [], spawnOpts, {
857
+ sync: true,
858
+ });
859
+ } catch (sandboxErr) {
860
+ if (this._sandboxStrictEnabled()) {
861
+ this._recordSandboxDenial(auditEntry, sandboxErr, startTime);
862
+ sandboxErr.auditEntry = auditEntry;
863
+ throw sandboxErr;
598
864
  }
865
+ process.emitWarning(
866
+ `Sandbox init failed (sync, continuing without): ${sandboxErr.message}`,
867
+ );
868
+ sandboxPlan = this._sandboxUnavailablePlan(
869
+ command,
870
+ args || [],
871
+ spawnOpts,
872
+ `sandbox_init_failed: ${sandboxErr.message}`,
873
+ );
599
874
  }
875
+ command = sandboxPlan.command;
876
+ args = [...sandboxPlan.args];
877
+ const optsForSync = { ...sandboxPlan.options };
878
+ this._applySandboxAudit(auditEntry, sandboxPlan, sandboxPlan.applied);
600
879
 
601
880
  const nativeSpawnSyncFn = this._native?.spawnSync || nativeSpawnSync;
602
881
  try {
603
882
  const result = nativeSpawnSyncFn(command, args, optsForSync);
883
+ if (sandboxPlan.applied) this._stats.sandboxed++;
604
884
  auditEntry.exitCode = result.status;
605
885
  auditEntry.endTime = Date.now();
606
886
  auditEntry.durationMs = auditEntry.endTime - startTime;
@@ -614,6 +894,8 @@ class ProcessExecutionBroker extends EventEmitter {
614
894
  this._recordAudit(auditEntry);
615
895
  this._writeRplEntry(auditEntry, "error", err);
616
896
  throw err;
897
+ } finally {
898
+ sandboxPlan.cleanup?.();
617
899
  }
618
900
  }
619
901
 
@@ -803,7 +1085,9 @@ class ProcessExecutionBroker extends EventEmitter {
803
1085
  completionError.stream = streamName;
804
1086
  try {
805
1087
  proc.kill(options.killSignal || "SIGTERM");
806
- } catch {}
1088
+ } catch {
1089
+ // The maxBuffer error remains authoritative if the child exited.
1090
+ }
807
1091
  }
808
1092
  });
809
1093
  };