chainlesschain 0.162.176 → 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 (260) 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-BDLu5Elz.js → AIOps-DRftcSue.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-BFvUaMKR.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.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-Br2YBbh_.js → Artifacts-DAJ8B3Un.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-hOk4L1lr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-3pbDpM9z.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-BtziGDn9.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-kmshphJ3.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-d7tGSosA.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CGHYrugQ.js → ChatBubbleRenderer-p-_PBpX_.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-C4Eh4Tz5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-r7gmhZyA.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-U7mDaGlL.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-Bpu8aH1T.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CHb2XBJe.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-Cn_r4dey.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-CdMWfDcz.js} +4 -4
  22. package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BtnREHWy.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BKI9TSzr.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-pA-oD8ke.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-EweJcsek.js → Dropdown-DLyFVxDc.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-CtUWfYVq.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D8lsDGus.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-CRYt_aIw.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-BXj5Dney.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-Cm-I8RMz.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-CPvbhvgt.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-BZY_3CRZ.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-up0BW6pv.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-C5MEJ2Qe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-ihdrn43I.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-Br8bPMlh.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-BNntgrYW.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-BdV915mw.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-A3wDmlqL.js} +5 -5
  44. package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CF-mBLWM.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-Iy2k_MSo.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-kk0W7HUb.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-B5u5t_4S.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.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-Cds0_tXr.js → Organization-DwWQESuN.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-DG6klrcC.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-BwJcKkgZ.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.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-BOx8HOgL.js → Pipeline-BzJfeoGt.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-DLh3Bblx.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-USVWW36c.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.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-Ct8xqY-E.js → Providers-CBPWWzpu.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-QVwoRUq3.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-CXnR-2Vn.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-ClaNzjmF.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C3rGw8vJ.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-Ci-OWAoP.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-DRhAwXOS.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-BQLJQ2_y.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-QQUpkfFd.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-DdXKzuKT.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-x2Zh62Qd.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-GdY4KwRz.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-BDHh17P0.js → Skills-Bv4tY1Fd.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-C3QnM-11.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-Bl3ytvmI.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-Wp9IwTsP.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-DYQ_6lxj.js → Tasks-CF3rIrDe.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-CGfvVVM9.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-CVXmwQ3U.js} +1 -1
  80. package/src/assets/web-panel/assets/Terminal-bvwrt03E.js +3 -0
  81. package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-D0g74KhH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-BH4IwzlT.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-DJOpM533.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-B43EPRLr.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-BmBFG-em.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-n9oJwB8k.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-D5QeivHp.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-DcNy7igO.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BVjc7-5-.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-Dy5Tfj3m.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C4c2CNZU.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-DPa3O5vN.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-DGXxCBKR.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-SBDJB1y4.js → hasIn-D41LVFkp.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-0oevYjfT.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-388pLGJ1.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-B8nLBZbv.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-BPTGAjee.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BPtrOBmW.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-BQiIxHBy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BSM1cHVK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-BYPr9fkz.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-BsQ7Ev6i.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-Btk9qLL2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-BvmziZSG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BvopLC_T.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-C7xhTVyP.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-CNk_ZooP.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CQrEHoOG.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CSxex23J.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-CVjgm992.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CWK4zOPe.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-CX0VsoP4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-CXl0YPNG.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-Cip7LWml.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-Cq_hlWNt.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-CzZ49YZL.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-D2Nkivlm.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BYqz4Wrr.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-CdGY9P8a.js → index-DNsBj2Ob.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Di4X8cfI.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-DljFsVGI.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DnjPdvR6.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-VMfwIH5G.js → index-MKZDje0H.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-OHAfRu_3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-WEJr8PL5.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-WinCp6du.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-Yjr6cqSK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-iQ6gtFih.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-pt3s7yvV.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-tQ3igERQ.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-BFZu87WZ.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-DJIo7qvt.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-Cfr5qknL.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-Bgc-OadH.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-X3WI-TNp.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-pJhU9IxK.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-BNg_Vj3T.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-TeSEGQ5-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-D_t_P0bv.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-DrrIMwAT.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-BjZCuFRm.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-Baxglj2V.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-mIRkdT7o.js → vnode-BrbcRiHZ.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-HzI5DlH_.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/agenda.js +22 -6
  154. package/src/commands/agent.js +3 -3
  155. package/src/commands/background-session.js +16 -6
  156. package/src/commands/batch.js +79 -27
  157. package/src/commands/changelog.js +15 -4
  158. package/src/commands/context.js +33 -1
  159. package/src/commands/eval.js +21 -6
  160. package/src/commands/hook.js +2 -2
  161. package/src/commands/hub.js +473 -39
  162. package/src/commands/init.js +212 -110
  163. package/src/commands/llm.js +22 -6
  164. package/src/commands/loop.js +9 -2
  165. package/src/commands/skill.js +13 -1
  166. package/src/commands/statusline.js +3 -3
  167. package/src/data/changelog.json +53 -5
  168. package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
  169. package/src/harness/background-task-manager.js +18 -6
  170. package/src/harness/background-task-worker.js +11 -18
  171. package/src/harness/golden-transcript.js +3 -0
  172. package/src/harness/mcp-client.js +9 -15
  173. package/src/harness/worktree-isolator.js +18 -21
  174. package/src/index.js +18 -7
  175. package/src/lib/agent-core.js +5 -0
  176. package/src/lib/agent-ipc-bus.js +12 -3
  177. package/src/lib/agent-team/team-worktree.js +28 -6
  178. package/src/lib/agent-worktree.js +20 -19
  179. package/src/lib/approval-authority-store.js +891 -0
  180. package/src/lib/async-hook-supervisor.cjs +134 -24
  181. package/src/lib/async-hook-supervisor.js +47 -0
  182. package/src/lib/background-agent-supervisor.js +35 -12
  183. package/src/lib/background-interaction-resolver.js +399 -54
  184. package/src/lib/background-session-transport.js +3 -1
  185. package/src/lib/background-task-manager.js +5 -1
  186. package/src/lib/changelog.js +57 -0
  187. package/src/lib/chrome-connector.js +6 -2
  188. package/src/lib/claude-code-bridge.js +24 -8
  189. package/src/lib/cli-anything-bridge.js +82 -25
  190. package/src/lib/context-breakdown.js +82 -3
  191. package/src/lib/doctor-checkup.js +18 -6
  192. package/src/lib/eval/tasks.js +25 -31
  193. package/src/lib/event-runtime-host.js +225 -0
  194. package/src/lib/event-runtime-store.js +102 -21
  195. package/src/lib/event-runtime-worker.js +70 -2
  196. package/src/lib/hook-runner.cjs +71 -36
  197. package/src/lib/hook-runner.js +55 -0
  198. package/src/lib/hooks-v2-producers.js +33 -8
  199. package/src/lib/hooks-v2-runtime.js +360 -40
  200. package/src/lib/host-adb-bridge.js +18 -3
  201. package/src/lib/interaction-adapter.js +66 -0
  202. package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
  203. package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
  204. package/src/lib/lsp/benchmark.js +20 -4
  205. package/src/lib/lsp/lsp-client.js +6 -4
  206. package/src/lib/lsp/lsp-server-registry.js +0 -2
  207. package/src/lib/operation-fingerprint.js +107 -2
  208. package/src/lib/orchestrator.js +8 -2
  209. package/src/lib/packer/pack-update-applier.js +14 -2
  210. package/src/lib/packer/smoke-runner.js +18 -5
  211. package/src/lib/paths.js +1 -1
  212. package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
  213. package/src/lib/personal-data-hub-wiring.js +327 -52
  214. package/src/lib/plugin-monitor-supervisor.js +20 -13
  215. package/src/lib/plugin-runtime/install.js +10 -3
  216. package/src/lib/process-execution-broker/credential-agent.js +954 -111
  217. package/src/lib/process-execution-broker/index.js +369 -85
  218. package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
  219. package/src/lib/provider-http-error.js +94 -0
  220. package/src/lib/remote-approval-bridge.js +222 -26
  221. package/src/lib/repl-bang-memorize.js +10 -2
  222. package/src/lib/repl-goal.js +19 -2
  223. package/src/lib/settings-hook-events.cjs +13 -8
  224. package/src/lib/settings-hook-events.js +20 -0
  225. package/src/lib/side-effect-ledger-store.js +65 -14
  226. package/src/lib/skill-loader.js +215 -12
  227. package/src/lib/skill-packs/generator.js +18 -9
  228. package/src/lib/skill-process-broker.js +85 -0
  229. package/src/lib/slash-commands.js +10 -2
  230. package/src/lib/status-line.cjs +28 -7
  231. package/src/lib/status-line.js +33 -0
  232. package/src/lib/sub-agent-context.js +42 -0
  233. package/src/lib/turn-binding-store.js +64 -15
  234. package/src/lib/turn-binding.js +85 -16
  235. package/src/repl/agent-repl.js +88 -49
  236. package/src/repl/remote-approval.js +13 -13
  237. package/src/repl/repl-turn-binding.js +46 -16
  238. package/src/runtime/agent-core.js +419 -84
  239. package/src/runtime/coding-agent-contract-shared.cjs +16 -0
  240. package/src/runtime/headless-runner.js +172 -44
  241. package/src/runtime/headless-stream.js +221 -11
  242. package/src/runtime/session-slash-commands.js +506 -0
  243. package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
  244. package/src/skills/video-editing/extractors/video-extractor.js +13 -3
  245. package/src/skills/video-editing/media-process.js +20 -0
  246. package/src/skills/video-editing/render/audio-mix.js +13 -3
  247. package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
  248. package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
  249. package/src/workers/background-agent-worker.js +76 -40
  250. package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +0 -9
  251. package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +0 -3
  252. package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
  253. package/src/assets/web-panel/assets/OrderTableRenderer-C48mu09U.js +0 -1
  254. package/src/assets/web-panel/assets/PersonalDataHub-AX3ypUDV.js +0 -9
  255. package/src/assets/web-panel/assets/Projects-Cc7FC9-e.js +0 -1
  256. package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
  257. package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
  258. package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
  259. package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
  260. package/src/assets/web-panel/assets/usePersonalDataHub-B4NkcLaP.js +0 -1
@@ -43,6 +43,7 @@ import {
43
43
  autoFailStuckRequestsV2,
44
44
  getLlmProvidersStatsV2,
45
45
  } from "../lib/llm-providers.js";
46
+ import { formatProviderResponseError } from "../lib/provider-http-error.js";
46
47
 
47
48
  /**
48
49
  * Resolve the effective `cc llm test` target from CLI flags + persisted config.
@@ -58,7 +59,12 @@ import {
58
59
  * @param {object} [env] process.env (for apiKeyEnv lookup)
59
60
  * @returns {{provider,model,baseUrl,apiKey,isOllama,label}}
60
61
  */
61
- export function resolveLlmTestTarget(options = {}, config = {}, builtIns = {}, env = {}) {
62
+ export function resolveLlmTestTarget(
63
+ options = {},
64
+ config = {},
65
+ builtIns = {},
66
+ env = {},
67
+ ) {
62
68
  const llm = config.llm || {};
63
69
  const provider = options.provider || llm.provider || "ollama";
64
70
  const isOllama = provider === "ollama";
@@ -73,11 +79,15 @@ export function resolveLlmTestTarget(options = {}, config = {}, builtIns = {}, e
73
79
  if (isOllama) {
74
80
  // Only inherit config.baseUrl when the CONFIGURED provider is also ollama —
75
81
  // otherwise `--provider ollama` would probe another provider's endpoint.
76
- const configOllamaBase = llm.provider === "ollama" ? llm.baseUrl : undefined;
82
+ const configOllamaBase =
83
+ llm.provider === "ollama" ? llm.baseUrl : undefined;
77
84
  baseUrl = options.baseUrl || configOllamaBase || "http://localhost:11434";
78
85
  } else {
79
86
  baseUrl =
80
- options.baseUrl || llm.baseUrl || builtIn?.baseUrl || "https://api.openai.com/v1";
87
+ options.baseUrl ||
88
+ llm.baseUrl ||
89
+ builtIn?.baseUrl ||
90
+ "https://api.openai.com/v1";
81
91
  }
82
92
 
83
93
  const apiKey = isOllama
@@ -166,7 +176,9 @@ export function registerLlmCommand(program) {
166
176
  // probe instead of only special-casing openai.
167
177
  llm
168
178
  .command("test")
169
- .description("Test LLM provider connectivity (defaults to configured provider)")
179
+ .description(
180
+ "Test LLM provider connectivity (defaults to configured provider)",
181
+ )
170
182
  .option("--provider <provider>", "LLM provider (default: configured)")
171
183
  .option("--model <model>", "Model to test (default: configured)")
172
184
  .option("--base-url <url>", "API base URL (default: configured/provider)")
@@ -195,7 +207,9 @@ export function registerLlmCommand(program) {
195
207
  });
196
208
 
197
209
  if (!response.ok) {
198
- throw new Error(`HTTP ${response.status}`);
210
+ throw new Error(
211
+ await formatProviderResponseError("ollama", response),
212
+ );
199
213
  }
200
214
 
201
215
  const data = await response.json();
@@ -226,7 +240,9 @@ export function registerLlmCommand(program) {
226
240
  });
227
241
 
228
242
  if (!response.ok) {
229
- throw new Error(`HTTP ${response.status}`);
243
+ throw new Error(
244
+ await formatProviderResponseError(target.provider, response),
245
+ );
230
246
  }
231
247
 
232
248
  const data = await response.json();
@@ -23,10 +23,10 @@
23
23
  * only builds the concrete iteration (spawn + tee output) and wires SIGINT.
24
24
  */
25
25
 
26
- import { spawn } from "node:child_process";
27
26
  import { fileURLToPath } from "node:url";
28
27
  import chalk from "chalk";
29
28
  import { logger } from "../lib/logger.js";
29
+ import executionBroker from "../lib/process-execution-broker/index.js";
30
30
  import {
31
31
  runLoop,
32
32
  parseDuration,
@@ -42,6 +42,10 @@ import {
42
42
  sessionExists,
43
43
  } from "../harness/jsonl-session-store.js";
44
44
 
45
+ export const _deps = {
46
+ spawn: executionBroker.spawn.bind(executionBroker),
47
+ };
48
+
45
49
  /**
46
50
  * Appended to the prompt under `--dynamic` so the model can self-pace: it ends
47
51
  * its reply with at most one control directive the loop parses (parseLoopDirectives).
@@ -66,10 +70,13 @@ const BIN_PATH = fileURLToPath(
66
70
  */
67
71
  function spawnIteration(cmd, args, { shell, onChild, capture }) {
68
72
  return new Promise((resolve) => {
69
- const child = spawn(cmd, args, {
73
+ const child = _deps.spawn(cmd, args, {
70
74
  shell,
71
75
  stdio: capture ? ["inherit", "pipe", "pipe"] : "inherit",
72
76
  env: process.env,
77
+ origin: "loop:iteration",
78
+ policy: "allow",
79
+ scope: "loop",
73
80
  });
74
81
  if (onChild) onChild(child);
75
82
 
@@ -10,6 +10,7 @@ import chalk from "chalk";
10
10
  import ora from "ora";
11
11
  import fs from "fs";
12
12
  import path from "path";
13
+ import { createSkillProcessBroker } from "../lib/skill-process-broker.js";
13
14
  import { logger } from "../lib/logger.js";
14
15
  import {
15
16
  CLISkillLoader,
@@ -326,7 +327,7 @@ export function registerSkillCommand(program) {
326
327
  .option("--json", "Output as JSON")
327
328
  .action(async (name, inputParts, options) => {
328
329
  const skills = loader.loadAll();
329
- const s = skills.find((sk) => sk.id === name || sk.dirName === name);
330
+ let s = skills.find((sk) => sk.id === name || sk.dirName === name);
330
331
 
331
332
  if (!s) {
332
333
  logger.error(`Skill not found: ${name}`);
@@ -345,6 +346,16 @@ export function registerSkillCommand(program) {
345
346
  process.exit(1);
346
347
  }
347
348
 
349
+ try {
350
+ s = loader.materializeSkill(s, {
351
+ loadedBecause: "cli_skill_run",
352
+ bodyIncluded: false,
353
+ });
354
+ } catch (error) {
355
+ logger.error(`Skill "${s.id}" body could not be loaded: ${error.message}`);
356
+ process.exit(1);
357
+ }
358
+
348
359
  const spinner = ora(`Running ${s.displayName}...`).start();
349
360
  const input = inputParts.join(" ");
350
361
 
@@ -368,6 +379,7 @@ export function registerSkillCommand(program) {
368
379
  projectRoot: process.cwd(),
369
380
  workspacePath: process.cwd(),
370
381
  workspaceRoot: process.cwd(),
382
+ processBroker: createSkillProcessBroker(s),
371
383
  };
372
384
 
373
385
  const result = await handler.execute(task, context, s);
@@ -27,12 +27,12 @@ export function registerStatuslineCommand(program) {
27
27
  .action(async (options) => {
28
28
  try {
29
29
  const { loadStatusLineConfig, buildContext, renderStatusLine } =
30
- await import("../lib/status-line.cjs");
30
+ await import("../lib/status-line.js");
31
31
  const cfg = loadStatusLineConfig({ cwd: process.cwd() });
32
32
  if (!cfg) {
33
33
  logger.log(
34
34
  chalk.gray(
35
- 'No statusLine configured. Add to .claude/settings.json:\n' +
35
+ "No statusLine configured. Add to .claude/settings.json:\n" +
36
36
  ' { "statusLine": { "type": "command", "command": "./status.sh" } }',
37
37
  ),
38
38
  );
@@ -73,7 +73,7 @@ export function registerStatuslineCommand(program) {
73
73
  .option("--json", "Output as JSON")
74
74
  .action(async (options) => {
75
75
  try {
76
- const { loadStatusLineConfig } = await import("../lib/status-line.cjs");
76
+ const { loadStatusLineConfig } = await import("../lib/status-line.js");
77
77
  const cfg = loadStatusLineConfig({ cwd: process.cwd() });
78
78
  if (options.json) {
79
79
  console.log(JSON.stringify(cfg, null, 2));
@@ -2,8 +2,21 @@
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
4
  {
5
- "productVersion": "Unreleased",
6
- "cliVersion": "0.162.170",
5
+ "productVersion": null,
6
+ "cliVersion": "0.162.178",
7
+ "cliVersions": ["0.162.178"],
8
+ "date": null,
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Fixed — cc CLI 0.162.178 + IDE provider 403 diagnosis hotfix",
13
+ "body": "- Preserve structured provider error codes/messages for failed LLM requests and\n `cc llm test`, with credential-shaped text redacted before display.\n- Do not classify every HTTP 403 as an invalid API key: overdue accounts,\n billing failures, and model-access denials now retain their real corrective\n action in CLI, VS Code, and JetBrains.\n- Release VS Code 0.37.33 and JetBrains 0.4.70 with corrected setup guidance."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "productVersion": "v5.0.3.135",
19
+ "cliVersion": "0.162.177",
7
20
  "cliVersions": [
8
21
  "0.4.46",
9
22
  "0.4.51",
@@ -28,11 +41,46 @@
28
41
  "0.162.167",
29
42
  "0.162.168",
30
43
  "0.162.169",
31
- "0.162.170"
44
+ "0.162.170",
45
+ "0.162.171",
46
+ "0.162.172",
47
+ "0.162.173",
48
+ "0.162.174",
49
+ "0.162.175",
50
+ "0.162.176",
51
+ "0.162.177"
32
52
  ],
33
- "date": null,
34
- "title": "",
53
+ "date": "2026-07-24",
54
+ "title": "Python Agent SDK 0.1.0 + CLI/IDE 运行时收口 + 跨端 CI 稳定性",
35
55
  "sections": [
56
+ {
57
+ "heading": "Fixed — cc CLI 0.162.177:技能生成子进程统一纳入 Process Broker(CLI-only npm 发版)",
58
+ "body": "> `chainlesschain` 0.162.176 → **0.162.177**(2026-07-23)。本版把 CLI-Anything 与 CLI 技能包生成器的同步子进程执行统一收进宿主 Process Broker,补齐技能执行链路最后一处直接 `child_process` 入口。\n\n- **宿主拥有执行来源**:技能只拿到窄化、冻结的进程 facade;`origin`、`scope`、插件 id/version/source 等来源元数据由宿主写入,处理器不能伪造或绕过。\n- **CLI-Anything 无 shell 执行**:生成的 handler 把输入解析成字面 argv,经 `runFileSync(..., shell:false)` 执行;保留危险字符与未闭合引号拒绝,缺少 Broker 时 fail closed。\n- **CLI 技能包统一接线**:direct/hybrid 生成 handler 改经 `processBroker.runSync` 调用 CLI,命令行与 agent 两条技能执行入口都注入同一 Broker facade,并补齐单元/集成回归。"
59
+ },
60
+ {
61
+ "heading": "Added — cc CLI 0.162.176:统一进程执行边界 + durable runtime 事件 + IDE plan/diff review 完整链路(CLI-only npm 发版)",
62
+ "body": "> `chainlesschain` 0.162.175 → **0.162.176**(2026-07-23)。本版把 CLI 内分散的子进程入口收进统一 broker,并补齐 durable event、插件来源治理、结构化输出与 IDE 评审链路;同时修复 Windows changelog fallback、MCP 初始化顺序及多项跨平台执行回归。\n\n- **统一进程执行与安全边界**:后台 agent、batch、worktree、LSP/MCP、hook、发布、远程执行、凭据 helper 等宿主命令统一经 process broker;远程 argv、凭据过滤、同步/异步 exec-file 契约和跨平台 probe 一并加固。\n- **durable runtime / plugin 治理**:外部事件持久队列与 backpressure、MCP durable 事件生产者、plugin secret/process boundary、hook broker、plugin bin provenance 与 SBOM 接线。\n- **结构化输出与 IDE 评审**:JSON Schema 支持 local/dynamic/external refs;plan review 流式进度、批准计划锁定、diff 生命周期/关联/追问持久化和工具准入 host signal 接线。\n- **稳定性修复**:Windows 全局安装遇到父级 Node.js `CHANGELOG.md` 时回退包内数据;MCP 先初始化再注册 elicitation;修复 ESM cycle、workspace publishing、stream debug stack 与 broker portability。"
63
+ },
64
+ {
65
+ "heading": "Fixed — cc CLI 0.162.175:Windows hook 输出与 Node.js 22 启动链路加固",
66
+ "body": "> `chainlesschain` 0.162.174 → **0.162.175**(2026-07-21)。\n\n- 修复 Windows hook 输出处理、Node.js 22 JSON import 语法、platform sandbox/process broker 残余语法错误及命令注册回归。\n- 后台 cowork attach 可把 `askUserQuestion` 真实交给用户;Setup/Notification hooks、跨平台 sandbox 与 credential agent 默认链路完成接线。\n- 清理发布门的跨平台/并发 flake,恢复 CLI 启动、测试与发版契约。"
67
+ },
68
+ {
69
+ "heading": "Fixed — cc CLI 0.162.174:移除失效的 session notification import",
70
+ "body": "> `chainlesschain` 0.162.173 → **0.162.174**(2026-07-20)。\n\n- 移除 session notification 的陈旧导入,避免启动期模块解析失败。"
71
+ },
72
+ {
73
+ "heading": "Fixed — cc CLI 0.162.173:修复 observability 启动回归",
74
+ "body": "> `chainlesschain` 0.162.172 → **0.162.173**(2026-07-20)。\n\n- 修复 observability 模块缺失导出、循环依赖与 `traceContext is not defined`,恢复 CLI 正常启动。"
75
+ },
76
+ {
77
+ "heading": "Added — cc CLI 0.162.172:cowork 远程控制 + Runtime Convergence M5/M6",
78
+ "body": "> `chainlesschain` 0.162.171 → **0.162.172**(2026-07-20)。\n\n- 完成 cowork 远程控制、Hook System v2、Notification 事件与 Permission UX。\n- 接入分布式追踪、性能指标、OTLP exporter,以及 M5/M6 四层 runtime convergence 运行参数。"
79
+ },
80
+ {
81
+ "heading": "Added — cc CLI 0.162.171:后台 Agent 安全 worktree 交接 + turn/approval 持久绑定",
82
+ "body": "> `chainlesschain` 0.162.170 → **0.162.171**(2026-07-19)。\n\n- 后台 Agent 增加生产级 bootstrap 与安全 worktree transfer。\n- REPL 成为 turn-binding 生产者,`/rewind` 消费持久化绑定表;WebSocket approval binding 补齐真实生产者。\n- IDE lockfile sandbox 与 CLI worktree 边界同步加固。"
83
+ },
36
84
  {
37
85
  "heading": "Added — cc CLI 0.162.170:后台 Agent stop 自杀守卫 + 可注入 kill seam + smoke-runner 死 pid 守卫;发版门 flake 治本后首个无 skip_tests 发版(CLI-only npm 发版)",
38
86
  "body": "> `chainlesschain` 0.162.169 → **0.162.170** 发 npm `latest`(经 `npm-publish.yml`,`--provenance --access public`)。CLI-only:`packages/cli/src` 仅两文件(+ vitest 4.1.5→4.1.10 devDep 升级与测试);未触 `pdh/lib` → 无 Android bundle / 无 USR_VERSION。**无新增顶层命令,命令数 175 不变**;默认路径字节不变(守卫只在损坏/异常记录上改变行为)。本版同时是 CI 发版门 worker-death flake(卡了 .167/.168/.169 三个发版、cli-ci 30+ 连败)治本(trap #34)后的**验证发版**——test 门应首跑即绿、无需 `skip_tests`。\n\n- **后台 Agent stop 自杀守卫(真实世界加固)**:`stopBackgroundAgent` 现拒绝向 `pid === process.pid` 的记录发信号——合法的 worker 记录不可能指向执行 stop 的进程自身,命中即判损坏记录(标 `lost`/`self-pid-corrupt-record`、不杀任何进程)。此前一份损坏/手改的 state 文件能让 `cc daemon stop` 对用户自己的 shell 树发 SIGTERM(POSIX)或 `taskkill /T /F`(Windows)。agentPid 组杀同样加 `!== process.pid` 守卫;`defaultKillProcessTree` 同款自杀守卫。\n- **可注入 kill seam**:supervisor 全部 POSIX 信号从裸 `process.kill` 收进 `_deps.kill` 单一 seam——测试可注入(正是 flake 根因之一:`_deps.spawnSync` stub 只盖 Windows taskkill 分支、POSIX 裸 kill 拦不住),生产行为不变。\n- **smoke-runner 死 pid 守卫**:子进程已退出(`exitCode`/`signalCode` 非 null)时跳过 Windows `taskkill /T /F`——Windows 秒级复用 pid,对死尸 pid 的树杀会误杀顶替者全树(CI 上即另一 vitest worker / 无辜测试子进程)。\n- **vitest 4.1.5 → 4.1.10**(root workspace 全体 devDep):含 4.1.9 的真 pool 修复(worker 崩溃挂起、per-task error 监听、STOPPED 态、回收 isTerminated 守卫);非 flake 解药但保留为正确卫生。agent-sdk 刻意保持 `^3` 钉版;独立 web-panel 不动。"
@@ -23,6 +23,7 @@ import {
23
23
  } from "../../lib/personal-data-hub-wiring.js";
24
24
  import { importPdh } from "../../lib/pdh-load-error.js";
25
25
  import { getAIChatWizard } from "../../lib/personal-data-hub-aichat-wizard.js";
26
+ import { runDedicatedBatchCollectors } from "../../lib/pdh-dedicated-batch-collectors.js";
26
27
  import {
27
28
  existsSync,
28
29
  unlinkSync,
@@ -224,7 +225,10 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
224
225
  }),
225
226
 
226
227
  "personal-data-hub.sync-all": async (msg) =>
227
- withHub(async (hub) => await hub.registry.syncAll(msg.options || {})),
228
+ withHub(async (hub) => {
229
+ const reports = await hub.registry.syncAll(msg.options || {});
230
+ return await runDedicatedBatchCollectors(hub, reports);
231
+ }),
228
232
 
229
233
  "personal-data-hub.register-mock": async (msg) =>
230
234
  withHub((hub) => {
@@ -361,6 +365,9 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
361
365
  }),
362
366
  ),
363
367
 
368
+ "personal-data-hub.activate-email": async (msg) =>
369
+ withHub(async (hub) => await hub.activateEmailAdapter(msg.email)),
370
+
364
371
  "personal-data-hub.unregister-email": async (msg) =>
365
372
  withHub(async (hub) => await hub.unregisterEmailAdapter(msg.email)),
366
373
 
@@ -381,6 +388,9 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
381
388
  }),
382
389
  ),
383
390
 
391
+ "personal-data-hub.activate-alipay": async (msg) =>
392
+ withHub(async (hub) => await hub.activateAlipayAdapter(msg.email)),
393
+
384
394
  "personal-data-hub.unregister-alipay": async (msg) =>
385
395
  withHub(async (hub) => await hub.unregisterAlipayAdapter(msg.email)),
386
396
 
@@ -414,6 +424,15 @@ export const PERSONAL_DATA_HUB_HANDLERS = {
414
424
  }),
415
425
  ),
416
426
 
427
+ "personal-data-hub.activate-wechat": async (msg) =>
428
+ withHub(
429
+ async (hub) =>
430
+ await hub.activateWechatAdapter(msg.uin, {
431
+ fridaOpts: msg.fridaOpts,
432
+ keyProviderOverride: msg.keyProviderOverride,
433
+ }),
434
+ ),
435
+
417
436
  "personal-data-hub.unregister-wechat": async (msg) =>
418
437
  withHub(async (hub) => await hub.unregisterWechatAdapter(msg.uin)),
419
438
 
@@ -658,7 +677,8 @@ export const PERSONAL_DATA_HUB_STREAMING_HANDLERS = {
658
677
  }
659
678
  };
660
679
  try {
661
- const reports = await hub.registry.syncAll(msg.options || {});
680
+ const registryReports = await hub.registry.syncAll(msg.options || {});
681
+ const reports = await runDedicatedBatchCollectors(hub, registryReports);
662
682
  return { result: reports };
663
683
  } finally {
664
684
  hub.registry.onSyncEvent = original;
@@ -1,19 +1,23 @@
1
1
  /**
2
2
  * Background Task Manager - daemon task queue with completion notifications.
3
3
  *
4
- * Tasks run in child_process.fork() for isolation.
4
+ * Tasks run in a brokered Node child with an IPC channel for isolation.
5
5
  * Queue persisted to .chainlesschain/tasks/queue.jsonl.
6
6
  * Completion notifications delivered to REPL callback.
7
7
  *
8
8
  * Feature-flag gated: BACKGROUND_TASKS
9
9
  */
10
10
 
11
- import { fork } from "node:child_process";
12
11
  import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
13
12
  import { join } from "node:path";
14
13
  import { createHash } from "node:crypto";
15
14
  import { EventEmitter } from "node:events";
16
15
  import { getHomeDir } from "../lib/paths.js";
16
+ import executionBroker from "../lib/process-execution-broker/index.js";
17
+
18
+ export const _deps = {
19
+ spawn: executionBroker.spawn.bind(executionBroker),
20
+ };
17
21
 
18
22
  function getTasksDir() {
19
23
  const dir = join(getHomeDir(), "tasks");
@@ -114,13 +118,21 @@ export class BackgroundTaskManager extends EventEmitter {
114
118
  task.recoverySourceStatus = null;
115
119
  this._recordHistory(task, "started", { status: task.status });
116
120
 
117
- const child = fork(
118
- join(import.meta.dirname || ".", "background-task-worker.js"),
119
- [task.command, task.cwd, task.type],
121
+ const workerPath = join(
122
+ import.meta.dirname || ".",
123
+ "background-task-worker.js",
124
+ );
125
+ const child = _deps.spawn(
126
+ process.execPath,
127
+ [...process.execArgv, workerPath, task.command, task.cwd, task.type],
120
128
  {
121
129
  cwd: task.cwd,
122
- silent: true,
130
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
123
131
  env: { ...process.env, CC_TASK_ID: taskId },
132
+ origin: "background-task:worker",
133
+ policy: "allow",
134
+ scope: "background-task",
135
+ shell: false,
124
136
  },
125
137
  );
126
138
 
@@ -5,7 +5,7 @@
5
5
  * Sends messages to parent: { type: "heartbeat"|"result"|"error", ... }
6
6
  */
7
7
 
8
- import { execSync } from "node:child_process";
8
+ import executionBroker from "../lib/process-execution-broker/index.js";
9
9
 
10
10
  const [command, cwd, type] = process.argv.slice(2);
11
11
 
@@ -14,23 +14,16 @@ const heartbeat = setInterval(() => {
14
14
  }, 5000);
15
15
 
16
16
  try {
17
- let result;
18
-
19
- if (type === "shell") {
20
- result = execSync(command, {
21
- cwd: cwd || process.cwd(),
22
- encoding: "utf-8",
23
- timeout: 300000,
24
- maxBuffer: 10 * 1024 * 1024,
25
- });
26
- } else {
27
- result = execSync(command, {
28
- cwd: cwd || process.cwd(),
29
- encoding: "utf-8",
30
- timeout: 300000,
31
- maxBuffer: 10 * 1024 * 1024,
32
- });
33
- }
17
+ const result = executionBroker.execSync(command, {
18
+ cwd: cwd || process.cwd(),
19
+ encoding: "utf-8",
20
+ timeout: 300000,
21
+ maxBuffer: 10 * 1024 * 1024,
22
+ origin: `background-task:command:${type || "unknown"}`,
23
+ policy: "allow",
24
+ scope: "background-task",
25
+ shell: true,
26
+ });
34
27
 
35
28
  if (process.send) {
36
29
  process.send({ type: "result", data: result || "Done" });
@@ -18,6 +18,9 @@ const VOLATILE_KEYS = new Set([
18
18
  "updatedAt",
19
19
  "duration",
20
20
  "durationMs",
21
+ "permission_decision_id",
22
+ "tool_use_id",
23
+ "turn_id",
21
24
  "toolTelemetryRecord",
22
25
  ]);
23
26
 
@@ -8,7 +8,6 @@
8
8
  * thin re-export shim for backwards compatibility.
9
9
  */
10
10
 
11
- import { spawn } from "child_process";
12
11
  import { executionBroker } from "../lib/process-execution-broker/index.js";
13
12
  import { AsyncLocalStorage } from "node:async_hooks";
14
13
  import { EventEmitter } from "events";
@@ -21,7 +20,7 @@ import { EventRuntimeProducer } from "../lib/event-runtime-producer.js";
21
20
  * `fetch` defaults to the global fetch (Node 18+).
22
21
  */
23
22
  export const _deps = {
24
- spawn,
23
+ spawn: executionBroker.spawn.bind(executionBroker),
25
24
  fetch: (...args) => globalThis.fetch(...args),
26
25
  // Backoff sleep seam (tests override with a no-op so retries don't wait).
27
26
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
@@ -486,10 +485,7 @@ export class MCPClient extends EventEmitter {
486
485
  `stdio transport requires a command (server "${name}")`,
487
486
  );
488
487
  }
489
- const spawnFn = String(config.origin || "").startsWith("plugin:")
490
- ? executionBroker.spawn.bind(executionBroker)
491
- : _deps.spawn;
492
- const proc = spawnFn(config.command, config.args || [], {
488
+ const proc = _deps.spawn(config.command, config.args || [], {
493
489
  stdio: ["pipe", "pipe", "pipe"],
494
490
  // process.env < agent identity (CLAUDECODE / session id) < the
495
491
  // server's own config.env, so an explicit per-server override wins.
@@ -498,15 +494,13 @@ export class MCPClient extends EventEmitter {
498
494
  ...this._agentIdentityEnv(),
499
495
  ...(config.env || {}),
500
496
  },
501
- ...(config.origin
502
- ? {
503
- origin: config.origin,
504
- policy: config.policy || "allow",
505
- pluginId: config.pluginId,
506
- pluginVersion: config.pluginVersion,
507
- pluginSource: config.pluginSource,
508
- }
509
- : {}),
497
+ origin: config.origin || `mcp:server:${name}`,
498
+ policy: config.policy || "allow",
499
+ scope: config.scope || "mcp",
500
+ shell: false,
501
+ pluginId: config.pluginId,
502
+ pluginVersion: config.pluginVersion,
503
+ pluginSource: config.pluginSource,
510
504
  });
511
505
 
512
506
  entry.process = proc;
@@ -7,7 +7,6 @@
7
7
  * Feature-flag gated: WORKTREE_ISOLATION
8
8
  */
9
9
 
10
- import { execSync } from "node:child_process";
11
10
  import { existsSync, rmSync, symlinkSync, mkdirSync } from "node:fs";
12
11
  import { resolve, dirname } from "node:path";
13
12
  import {
@@ -93,10 +92,10 @@ export function removeWorktree(repoDir, worktreePath, options = {}) {
93
92
  let branch = null;
94
93
  if (deleteBranch) {
95
94
  try {
96
- branch = execSync("git rev-parse --abbrev-ref HEAD", {
97
- cwd: worktreePath,
98
- encoding: "utf-8",
99
- }).trim();
95
+ branch = gitExecArgs(
96
+ ["rev-parse", "--abbrev-ref", "HEAD"],
97
+ worktreePath,
98
+ ).trim();
100
99
  } catch (_e) {
101
100
  // Can't determine branch, skip branch deletion.
102
101
  }
@@ -215,11 +214,7 @@ function _worktreeCleanupState(repoDir, wt) {
215
214
 
216
215
  // Dirty state: separate tracked modifications from untracked files.
217
216
  try {
218
- const porcelain = execSync("git status --porcelain", {
219
- cwd: wt.path,
220
- encoding: "utf-8",
221
- maxBuffer: 64 * 1024 * 1024,
222
- });
217
+ const porcelain = gitExecArgs(["status", "--porcelain"], wt.path);
223
218
  const lines = porcelain.split("\n").filter((l) => l.trim().length > 0);
224
219
  state.untracked = lines.some((l) => l.startsWith("??"));
225
220
  state.uncommitted = lines.some((l) => !l.startsWith("??"));
@@ -393,8 +388,16 @@ export function mergeWorktree(repoDir, branchName, options = {}) {
393
388
  };
394
389
  } catch (err) {
395
390
  const errMsg = err.message || String(err);
396
- if (errMsg.includes("CONFLICT") || errMsg.includes("conflict")) {
397
- const conflictPaths = _collectConflictFiles(repoDir);
391
+ // Git can report merge conflicts on stdout while execSync's Error.message
392
+ // contains only the failed command (and localized installations need not
393
+ // include the English word "conflict"). The unmerged index is the
394
+ // authoritative signal.
395
+ const conflictPaths = _collectConflictFiles(repoDir);
396
+ if (
397
+ conflictPaths.length > 0 ||
398
+ errMsg.includes("CONFLICT") ||
399
+ errMsg.includes("conflict")
400
+ ) {
398
401
  if (conflictPaths.length === 0) {
399
402
  conflictPaths.push(..._extractConflictPathsFromMessage(errMsg));
400
403
  }
@@ -690,15 +693,9 @@ function _fileStatus(repoDir, base, branch, filePath) {
690
693
 
691
694
  function _hasUncommittedChanges(worktreePath) {
692
695
  try {
693
- const output = execSync("git status --porcelain", {
694
- cwd: worktreePath,
695
- encoding: "utf-8",
696
- // A worktree with many dirty files produces >1 MB of porcelain output and
697
- // would ENOBUFS on the default cap — the catch below then reports "clean"
698
- // (fail-OPEN), which could let a caller discard a worktree full of
699
- // uncommitted work. Give it the same 64 MB headroom as gitExec.
700
- maxBuffer: 64 * 1024 * 1024,
701
- });
696
+ // gitExecArgs carries the shared 64 MB maxBuffer, avoiding a fail-open
697
+ // "clean" result when a large worktree exceeds Node's default output cap.
698
+ const output = gitExecArgs(["status", "--porcelain"], worktreePath);
702
699
  return output.trim().length > 0;
703
700
  } catch (_e) {
704
701
  return false;
package/src/index.js CHANGED
@@ -9,6 +9,10 @@ import { pathToFileURL } from "node:url";
9
9
  import { dirname, join } from "node:path";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import manifest from "./command-manifest.json" with { type: "json" };
12
+ import {
13
+ startDefaultEventRuntimeHost,
14
+ stopDefaultEventRuntimeHost,
15
+ } from "./lib/event-runtime-host.js";
12
16
 
13
17
  // The manifest entry is the canonical registration point for learning. Keep
14
18
  // these names visible here for tooling that audits the CLI's command surface:
@@ -132,12 +136,19 @@ const isDirectRun =
132
136
  process.argv[1].endsWith("\\cli\\bin\\cli.js"));
133
137
 
134
138
  if (isDirectRun) {
139
+ // One lifecycle owner for every CLI surface. The timer is unref'ed, so a
140
+ // short command is never kept alive solely by the Event Runtime; resident
141
+ // commands keep draining while their own handles are active.
142
+ startDefaultEventRuntimeHost();
135
143
  const program = createProgram();
136
- program.parseAsync(process.argv).catch((err) => {
137
- console.error(chalk.red("\nUnexpected error:"), err.message);
138
- if (process.env.DEBUG) {
139
- console.error(err.stack);
140
- }
141
- process.exit(1);
142
- });
144
+ program
145
+ .parseAsync(process.argv)
146
+ .catch((err) => {
147
+ console.error(chalk.red("\nUnexpected error:"), err.message);
148
+ if (process.env.DEBUG) {
149
+ console.error(err.stack);
150
+ }
151
+ process.exitCode = 1;
152
+ })
153
+ .finally(() => stopDefaultEventRuntimeHost({ drain: true }));
143
154
  }
@@ -13,6 +13,8 @@ export {
13
13
  getAgentToolDescriptors,
14
14
  getCachedPython,
15
15
  getEnvironmentInfo,
16
+ _environmentProcessDeps,
17
+ _agentToolProcessDeps,
16
18
  getBaseSystemPrompt,
17
19
  buildSystemPrompt,
18
20
  executeTool,
@@ -29,6 +31,9 @@ export {
29
31
  killBackgroundShellTask,
30
32
  killAllBackgroundShellTasks,
31
33
  killAllBackgroundShellTasksSync,
34
+ _backgroundProcessDeps,
35
+ _runBackgroundTaskkill,
36
+ _gitProcessDeps,
32
37
  reapIdleBackgroundShellTasks,
33
38
  _ingestSearchOutput,
34
39
  writeFileVerified,
@@ -13,6 +13,11 @@ import { EventEmitter } from "node:events";
13
13
  import crypto from "node:crypto";
14
14
  import { EventRuntimeProducer } from "./event-runtime-producer.js";
15
15
  import { EventRuntimeStore } from "./event-runtime-store.js";
16
+ import executionBroker from "./process-execution-broker/index.js";
17
+
18
+ export const _deps = {
19
+ spawn: executionBroker.spawn.bind(executionBroker),
20
+ };
16
21
 
17
22
  /**
18
23
  * @typedef {Object} InteractionRequest
@@ -170,12 +175,12 @@ class AgentIPCBus extends EventEmitter {
170
175
  * @returns {Promise<{process: ChildProcess, agentId: string}>}
171
176
  */
172
177
  async spawnAgentProcess(command, args = [], options = {}) {
173
- const { spawn } = await import("node:child_process");
174
178
  const agentId = options.agentId || crypto.randomUUID();
175
179
  const heartbeatMs = options.heartbeatMs || 30000;
176
180
 
177
181
  return new Promise((resolve, reject) => {
178
- const child = spawn(command, args, {
182
+ const spawnOptions = options.spawnOptions || {};
183
+ const child = _deps.spawn(command, args, {
179
184
  stdio: ["pipe", "pipe", "pipe"],
180
185
  env: {
181
186
  ...process.env,
@@ -184,7 +189,11 @@ class AgentIPCBus extends EventEmitter {
184
189
  CHAINLESSCHAIN_IPC_PROTOCOL: "jsonrpc-stdio-v1",
185
190
  ...options.env,
186
191
  },
187
- ...options.spawnOptions,
192
+ ...spawnOptions,
193
+ origin: spawnOptions.origin || "agent-ipc:subagent",
194
+ policy: spawnOptions.policy || "allow",
195
+ scope: spawnOptions.scope || "agent-ipc",
196
+ shell: spawnOptions.shell === true,
188
197
  });
189
198
 
190
199
  let buffer = "";