chainlesschain 0.162.174 → 0.162.176

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 (281) hide show
  1. package/package.json +10 -10
  2. package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
  5. package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
  6. package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
  23. package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
  24. package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
  40. package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
  41. package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
  42. package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
  54. package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
  78. package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DGXxCBKR.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
  96. package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
  97. package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-xfluRkCT.js} +1 -1
  131. package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
  132. package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-HzI5DlH_.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/auth/npm-auth.js +30 -5
  151. package/src/commands/agenda.js +64 -2
  152. package/src/commands/agent.js +45 -3
  153. package/src/commands/background-session.js +103 -0
  154. package/src/commands/config.js +70 -5
  155. package/src/commands/context.js +36 -2
  156. package/src/commands/hub.js +19 -1
  157. package/src/commands/memory.js +21 -6
  158. package/src/commands/permissions.js +57 -1
  159. package/src/commands/plugin.js +2 -0
  160. package/src/commands/review.js +23 -11
  161. package/src/commands/routine.js +31 -8
  162. package/src/commands/session.js +11 -3
  163. package/src/commands/team.js +20 -7
  164. package/src/commands/update.js +65 -10
  165. package/src/esm-bridge.js +3 -0
  166. package/src/gateways/terminal/PtyManager.js +8 -1
  167. package/src/gateways/ws/message-dispatcher.js +3 -0
  168. package/src/gateways/ws/session-protocol.js +26 -0
  169. package/src/gateways/ws/ws-agent-handler.js +107 -69
  170. package/src/gateways/ws/ws-server.js +92 -4
  171. package/src/harness/jsonl-session-store.js +13 -6
  172. package/src/harness/mcp-client.js +200 -1
  173. package/src/index.js +123 -55
  174. package/src/lazy-dispatch.js +86 -85
  175. package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
  176. package/src/lib/agent-coordinator.js +4 -0
  177. package/src/lib/agent-ipc-bus.js +32 -2
  178. package/src/lib/agent-sandbox.js +16 -2
  179. package/src/lib/agent-schedule-store.js +55 -0
  180. package/src/lib/agent-tool-admission.js +104 -0
  181. package/src/lib/api-key-helper.js +10 -2
  182. package/src/lib/async-hook-supervisor.cjs +26 -4
  183. package/src/lib/background-interaction-resolver.js +71 -0
  184. package/src/lib/background-session-transport.js +59 -1
  185. package/src/lib/changelog.js +19 -11
  186. package/src/lib/channels/channel-manager.js +6 -0
  187. package/src/lib/channels/telegram-channel.js +11 -1
  188. package/src/lib/channels/webhook-channel.js +15 -3
  189. package/src/lib/checkpoint-store.js +10 -2
  190. package/src/lib/cloud/bundle.js +12 -2
  191. package/src/lib/code-review.js +32 -8
  192. package/src/lib/computer-use/control-backend.js +18 -3
  193. package/src/lib/context-breakdown.js +46 -0
  194. package/src/lib/context-source-ledger.js +43 -0
  195. package/src/lib/crash-reporter.js +6 -0
  196. package/src/lib/diff-review-follow-up.js +154 -0
  197. package/src/lib/downloader.js +17 -3
  198. package/src/lib/ensure-utf8.js +11 -3
  199. package/src/lib/event-runtime-producer.js +58 -0
  200. package/src/lib/event-runtime-store.js +354 -0
  201. package/src/lib/event-runtime-worker.js +109 -0
  202. package/src/lib/execution-backend.js +72 -21
  203. package/src/lib/git-integration.js +19 -4
  204. package/src/lib/hook-manager.js +34 -15
  205. package/src/lib/hook-runner.cjs +48 -3
  206. package/src/lib/hooks-v2-producers.js +15 -0
  207. package/src/lib/hooks-v2-runtime.js +70 -21
  208. package/src/lib/host-adb-bridge.js +111 -21
  209. package/src/lib/ide-context.js +128 -1
  210. package/src/lib/interaction-adapter.js +39 -0
  211. package/src/lib/ipc-attach-protocol.js +98 -0
  212. package/src/lib/json-schema-validate.js +190 -36
  213. package/src/lib/lan-pairing-preflight.js +13 -2
  214. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
  215. package/src/lib/lsp/lsp-client.js +18 -1
  216. package/src/lib/lsp/lsp-manager.js +4 -0
  217. package/src/lib/lsp/lsp-server-registry.js +11 -0
  218. package/src/lib/mcp-oauth.js +8 -2
  219. package/src/lib/npm-invocation.js +29 -0
  220. package/src/lib/packer/pkg-runner.js +13 -2
  221. package/src/lib/packer/precheck.js +33 -16
  222. package/src/lib/packer/web-panel-builder.js +16 -2
  223. package/src/lib/permission-rules.cjs +5 -1
  224. package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
  225. package/src/lib/personal-data-hub-wiring.js +27 -3
  226. package/src/lib/plan-mode.js +204 -11
  227. package/src/lib/plugin-monitor-supervisor.js +39 -4
  228. package/src/lib/plugin-runtime/bin.js +45 -0
  229. package/src/lib/plugin-runtime/hooks.js +14 -1
  230. package/src/lib/plugin-runtime/install.js +2 -1
  231. package/src/lib/plugin-runtime/lsp.js +3 -0
  232. package/src/lib/plugin-runtime/mcp.js +8 -1
  233. package/src/lib/plugin-runtime/monitors.js +4 -0
  234. package/src/lib/plugin-runtime/plugin-options.js +74 -7
  235. package/src/lib/plugin-runtime/signature.js +45 -0
  236. package/src/lib/pr-create.js +21 -8
  237. package/src/lib/pr-link-ledger.js +15 -3
  238. package/src/lib/process-execution-broker/credential-agent.js +295 -0
  239. package/src/lib/process-execution-broker/index.js +440 -14
  240. package/src/lib/process-execution-broker/patch-child-process.js +2 -3
  241. package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
  242. package/src/lib/process-manager.js +18 -3
  243. package/src/lib/provenance-api.js +6 -0
  244. package/src/lib/proxy-bootstrap.js +19 -0
  245. package/src/lib/publish-workspace.js +14 -6
  246. package/src/lib/repl-rewind.js +9 -4
  247. package/src/lib/secret-store.js +159 -0
  248. package/src/lib/service-manager.js +64 -29
  249. package/src/lib/session-hooks.js +328 -473
  250. package/src/lib/session-telemetry-middleware.js +6 -0
  251. package/src/lib/settings-hook-events.cjs +61 -1
  252. package/src/lib/settings-hooks.cjs +4 -0
  253. package/src/lib/side-effect-ledger.js +22 -0
  254. package/src/lib/sub-agent-context.js +5 -0
  255. package/src/lib/sub-agent-profiles.js +4 -0
  256. package/src/lib/trace-api.js +6 -0
  257. package/src/lib/turn-context.js +14 -8
  258. package/src/lib/unattended-action-policy.js +83 -0
  259. package/src/lib/update-notice.js +9 -45
  260. package/src/lib/with-file-lock.js +7 -0
  261. package/src/lib/ws-server.js +1 -0
  262. package/src/repl/agent-repl.js +71 -13
  263. package/src/repl/clipboard-copy.js +8 -2
  264. package/src/repl/pr-comments.js +30 -7
  265. package/src/runtime/agent-core.js +439 -87
  266. package/src/runtime/agent-runtime.js +1 -0
  267. package/src/runtime/coding-agent-contract-shared.cjs +52 -0
  268. package/src/runtime/coding-agent-policy.cjs +20 -0
  269. package/src/runtime/diagnostics.js +73 -8
  270. package/src/runtime/headless-runner.js +63 -0
  271. package/src/runtime/headless-stream.js +269 -17
  272. package/src/runtime/mcp-config.js +16 -1
  273. package/src/workers/background-agent-worker.js +80 -1
  274. package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
  275. package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
  276. package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
  277. package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
  278. package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
  279. package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
  280. package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
  281. package/src/assets/web-panel/assets/index-DyQkiW24.js +0 -1
@@ -22,6 +22,10 @@
22
22
  */
23
23
 
24
24
  import { spawn } from "node:child_process";
25
+ import { executionBroker } from "./process-execution-broker/index.js";
26
+ import { EventRuntimeProducer } from "./event-runtime-producer.js";
27
+ import { EventRuntimeStore } from "./event-runtime-store.js";
28
+ import { monitorEventId } from "./monitor-event.js";
25
29
 
26
30
  export const _deps = { spawn };
27
31
 
@@ -36,6 +40,14 @@ export class PluginMonitorSupervisor {
36
40
  this.defaultIntervalMs = opts.defaultIntervalMs || DEFAULT_INTERVAL_MS;
37
41
  this.timeoutMs = opts.timeoutMs || DEFAULT_TIMEOUT_MS;
38
42
  this._spawn = opts.spawn || _deps.spawn;
43
+ this._brokerSpawn =
44
+ opts.brokerSpawn || executionBroker.spawn.bind(executionBroker);
45
+ const eventRuntimeStore =
46
+ opts.eventRuntimeStore ||
47
+ (process.env.CC_EVENT_RUNTIME_DURABLE === "1" ? new EventRuntimeStore() : null);
48
+ this._runtimeProducer = eventRuntimeStore
49
+ ? new EventRuntimeProducer({ store: eventRuntimeStore, emitter: this })
50
+ : null;
39
51
  // id -> { desc, timer?, child?, running }
40
52
  this._monitors = new Map();
41
53
  this._outputs = []; // structured records awaiting drain
@@ -92,13 +104,22 @@ export class PluginMonitorSupervisor {
92
104
  .split(/\r?\n/)
93
105
  .filter((l) => l.length > 0);
94
106
  for (const line of lines) {
95
- this._outputs.push({
107
+ const output = {
96
108
  id: desc.id,
97
109
  plugin: desc.plugin,
98
110
  monitor: desc.name,
99
111
  stream,
100
112
  line,
101
- });
113
+ };
114
+ this._outputs.push(output);
115
+ try {
116
+ this._runtimeProducer?.publish(
117
+ { type: "monitor_output", ...output },
118
+ { origin: "monitor", id: monitorEventId(desc.id, { stream, line }) },
119
+ );
120
+ } catch (error) {
121
+ this._outputs.push({ ...output, stream: "error", line: `durable publish failed: ${error.message}` });
122
+ }
102
123
  if (this._outputs.length > OUTPUT_RING) this._outputs.shift();
103
124
  }
104
125
  }
@@ -107,7 +128,7 @@ export class PluginMonitorSupervisor {
107
128
  const { desc } = entry;
108
129
  let child;
109
130
  try {
110
- child = this._spawn(desc.command, desc.args, {
131
+ child = this._spawnForDescriptor(desc, {
111
132
  cwd: desc.cwd,
112
133
  env: desc.env ? { ...process.env, ...desc.env } : process.env,
113
134
  shell: false,
@@ -140,7 +161,7 @@ export class PluginMonitorSupervisor {
140
161
  this._runningIntervalRuns++;
141
162
  let child;
142
163
  try {
143
- child = this._spawn(desc.command, desc.args, {
164
+ child = this._spawnForDescriptor(desc, {
144
165
  cwd: desc.cwd,
145
166
  env: desc.env ? { ...process.env, ...desc.env } : process.env,
146
167
  shell: false,
@@ -188,6 +209,20 @@ export class PluginMonitorSupervisor {
188
209
  child.on("exit", () => finish());
189
210
  }
190
211
 
212
+ _spawnForDescriptor(desc, options) {
213
+ if (desc?.origin === "plugin:monitor") {
214
+ return this._brokerSpawn(desc.command, desc.args, {
215
+ ...options,
216
+ origin: desc.origin,
217
+ policy: "allow",
218
+ pluginId: desc.pluginId,
219
+ pluginVersion: desc.pluginVersion,
220
+ pluginSource: desc.pluginSource,
221
+ });
222
+ }
223
+ return this._spawn(desc.command, desc.args, options);
224
+ }
225
+
191
226
  /**
192
227
  * Take and clear all buffered monitor output records (for injection into the
193
228
  * next agent turn). Returns [] when nothing has been captured.
@@ -17,6 +17,7 @@
17
17
  */
18
18
 
19
19
  import path from "path";
20
+ import fs from "fs";
20
21
  import { discoverPlugins } from "./scopes.js";
21
22
  import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
22
23
  import { componentCapabilityDenial } from "./capabilities.js";
@@ -135,3 +136,47 @@ export function applyPluginBinPath(opts = {}) {
135
136
  },
136
137
  };
137
138
  }
139
+
140
+ /**
141
+ * Resolve the first executable token of a shell command to a trusted plugin
142
+ * bin. This is intentionally conservative: only an existing file directly
143
+ * under a collected plugin bin directory is attributed.
144
+ *
145
+ * @param {string} command
146
+ * @param {object} [opts] { cwd, scopes }
147
+ * @returns {{pluginId:string,pluginVersion:string,pluginSource:string,scope:string,binPath:string}|null}
148
+ */
149
+ export function resolvePluginBinCommand(command, opts = {}) {
150
+ if (typeof command !== "string") return null;
151
+ const match = command.match(/^\s*(?:"([^"]+)"|'([^']+)'|([^\s]+))/);
152
+ const token = match?.[1] || match?.[2] || match?.[3] || "";
153
+ if (!token) return null;
154
+ const tokenBase = path.basename(token).toLowerCase();
155
+ const candidates = new Set([tokenBase]);
156
+ if (process.platform === "win32" && !path.extname(tokenBase)) {
157
+ candidates.add(`${tokenBase}.exe`);
158
+ candidates.add(`${tokenBase}.cmd`);
159
+ candidates.add(`${tokenBase}.bat`);
160
+ }
161
+ for (const entry of collectPluginBinDirs(opts)) {
162
+ for (const candidateName of candidates) {
163
+ const binPath = path.join(entry.dir, candidateName);
164
+ if (!fs.existsSync(binPath)) continue;
165
+ if (path.isAbsolute(token)) {
166
+ try {
167
+ if (path.resolve(token) !== path.resolve(binPath)) continue;
168
+ } catch {
169
+ continue;
170
+ }
171
+ }
172
+ return {
173
+ pluginId: entry.plugin,
174
+ pluginVersion: entry.version || null,
175
+ pluginSource: entry.dir,
176
+ scope: entry.scope || null,
177
+ binPath,
178
+ };
179
+ }
180
+ }
181
+ return null;
182
+ }
@@ -122,7 +122,20 @@ export function collectPluginHooks(opts = {}) {
122
122
  const map = normalizeHookMap(parsed);
123
123
  for (const [event, entries] of Object.entries(map)) {
124
124
  if (!Array.isArray(entries)) continue;
125
- merged[event] = (merged[event] || []).concat(entries);
125
+ const tagged = entries.map((group) => {
126
+ if (!group || typeof group !== "object" || !Array.isArray(group.hooks)) return group;
127
+ return {
128
+ ...group,
129
+ hooks: group.hooks.map((hook) => ({
130
+ ...hook,
131
+ origin: "plugin:hook",
132
+ pluginId: p.name,
133
+ pluginVersion: p.version || null,
134
+ pluginSource: p.manifest?.manifestPath || null,
135
+ })),
136
+ };
137
+ });
138
+ merged[event] = (merged[event] || []).concat(tagged);
126
139
  }
127
140
  }
128
141
  warnHookCapabilityDeniedOnce(denied);
@@ -29,7 +29,7 @@ import {
29
29
  discoverPlugins,
30
30
  } from "./scopes.js";
31
31
  import { verifyPluginManifest } from "../plugin-security.js";
32
- import { writePluginLock, LOCK_FILENAME } from "./signature.js";
32
+ import { writePluginLock, buildPluginSbom, LOCK_FILENAME } from "./signature.js";
33
33
 
34
34
  export const _deps = {
35
35
  existsSync: fs.existsSync,
@@ -118,6 +118,7 @@ export function installFromDirectory(srcDir, opts = {}) {
118
118
  signatureVerified: verification.signatureVerified === true,
119
119
  signatureBase64: verification.signatureBase64,
120
120
  publicKeyPem: verification.publicKeyPem,
121
+ sbom: buildPluginSbom(dest),
121
122
  });
122
123
  }
123
124
 
@@ -91,6 +91,9 @@ export function ensurePluginLspServers(opts = {}) {
91
91
  args: s.args,
92
92
  extensions: s.extensions,
93
93
  id: s.id,
94
+ pluginId: p.name,
95
+ pluginVersion: p.version,
96
+ pluginSource: s.absPath || p.manifest.manifestPath,
94
97
  });
95
98
  registered.push({ plugin: p.name, languageId: s.languageId, id: s.id });
96
99
  } catch {
@@ -119,7 +119,14 @@ export function collectPluginMcpServers(opts = {}) {
119
119
  for (const [name, cfg] of Object.entries(map)) {
120
120
  if (!cfg || typeof cfg !== "object") continue;
121
121
  if (name in servers) continue; // first plugin wins on a clash
122
- servers[name] = cfg;
122
+ servers[name] = {
123
+ ...cfg,
124
+ origin: "plugin:mcp",
125
+ policy: "allow",
126
+ pluginId: p.name,
127
+ pluginVersion: p.version,
128
+ pluginSource: m.absPath || p.manifest.manifestPath,
129
+ };
123
130
  added++;
124
131
  }
125
132
  if (added > 0 && m.absPath) sources.push(m.absPath);
@@ -81,6 +81,10 @@ function normalizeMonitor(plugin, raw) {
81
81
  intervalMs,
82
82
  env,
83
83
  cwd: plugin.root,
84
+ origin: "plugin:monitor",
85
+ pluginId: plugin.name,
86
+ pluginVersion: plugin.version,
87
+ pluginSource: plugin.manifest?.manifestPath || null,
84
88
  };
85
89
  }
86
90
 
@@ -26,12 +26,18 @@ import {
26
26
  validateOptions,
27
27
  redactSensitiveOptions,
28
28
  } from "./capabilities.js";
29
+ import {
30
+ createSecretStore,
31
+ isSecretRef,
32
+ secretRef,
33
+ } from "../secret-store.js";
29
34
 
30
35
  export const _deps = {
31
36
  existsSync: fs.existsSync,
32
37
  readFileSync: fs.readFileSync,
33
38
  writeFileSync: fs.writeFileSync,
34
39
  mkdirSync: fs.mkdirSync,
40
+ secretStore: () => createSecretStore(),
35
41
  userStorePath: () =>
36
42
  path.join(getElectronUserDataDir(), "plugin-options.json"),
37
43
  projectStorePath: (cwd) =>
@@ -54,20 +60,70 @@ function writeJsonObject(p, obj) {
54
60
  }
55
61
 
56
62
  /** Load a plugin's option VALUES at the given scope (`user` | `project`). */
57
- export function loadPluginOptionValues(name, scope, { cwd } = {}) {
63
+ export function loadPluginOptionValues(name, scope, { cwd, schema, secretStore } = {}) {
58
64
  const p =
59
65
  scope === "project" ? _deps.projectStorePath(cwd) : _deps.userStorePath();
60
66
  const store = readJsonObject(p);
61
67
  const v = store[name];
62
- return v && typeof v === "object" && !Array.isArray(v) ? v : {};
68
+ if (!v || typeof v !== "object" || Array.isArray(v)) return {};
69
+ const out = { ...v };
70
+ const normalized = schema || {};
71
+ for (const [key, desc] of Object.entries(normalized)) {
72
+ if (!desc?.sensitive || !isSecretRef(out[key])) continue;
73
+ try {
74
+ const value = (secretStore || _deps.secretStore)().get(out[key].__cc_secret_ref);
75
+ if (value != null) out[key] = value;
76
+ else delete out[key];
77
+ } catch {
78
+ // Missing/unavailable secret backends fail closed: do not expose a
79
+ // plaintext fallback and let validation keep the option at its default.
80
+ delete out[key];
81
+ }
82
+ }
83
+ return out;
63
84
  }
64
85
 
65
86
  /** Persist a plugin's option VALUES at a scope (replaces the plugin's entry). */
66
- export function setPluginOptionValues(name, values, scope, { cwd } = {}) {
87
+ export function setPluginOptionValues(
88
+ name,
89
+ values,
90
+ scope,
91
+ { cwd, schema, secretStore } = {},
92
+ ) {
67
93
  const p =
68
94
  scope === "project" ? _deps.projectStorePath(cwd) : _deps.userStorePath();
69
95
  const store = readJsonObject(p);
70
- store[name] = values && typeof values === "object" ? values : {};
96
+ const input = values && typeof values === "object" ? values : {};
97
+ const persisted = { ...input };
98
+ const normalized = schema || {};
99
+ let secrets = null;
100
+ const getSecrets = () => {
101
+ if (!secrets) secrets = (secretStore || _deps.secretStore)();
102
+ return secrets;
103
+ };
104
+ const rejectedSensitive = [];
105
+ for (const [key, desc] of Object.entries(normalized)) {
106
+ if (!desc?.sensitive || !Object.prototype.hasOwnProperty.call(input, key)) continue;
107
+ // Project files are shareable and must never receive a sensitive value.
108
+ if (scope === "project") {
109
+ delete persisted[key];
110
+ rejectedSensitive.push(key);
111
+ continue;
112
+ }
113
+ if (input[key] == null || input[key] === "") {
114
+ delete persisted[key];
115
+ try { getSecrets().delete(`${name}/${key}`); } catch {}
116
+ continue;
117
+ }
118
+ getSecrets().set(`${name}/${key}`, input[key]);
119
+ persisted[key] = secretRef(`${name}/${key}`);
120
+ }
121
+ if (rejectedSensitive.length > 0) {
122
+ persisted.__cc_rejected_sensitive = [...new Set(rejectedSensitive)].sort();
123
+ } else if (Object.prototype.hasOwnProperty.call(persisted, "__cc_rejected_sensitive")) {
124
+ delete persisted.__cc_rejected_sensitive;
125
+ }
126
+ store[name] = persisted;
71
127
  writeJsonObject(p, store);
72
128
  return { name, scope, path: p };
73
129
  }
@@ -107,10 +163,21 @@ export function resolvePluginOptions(
107
163
 
108
164
  const warnings = [];
109
165
  const droppedFromProject = [];
166
+ const projectInput = { ...(projectValues || {}) };
167
+ const rejectedSensitive = Array.isArray(projectInput.__cc_rejected_sensitive)
168
+ ? projectInput.__cc_rejected_sensitive
169
+ : [];
170
+ delete projectInput.__cc_rejected_sensitive;
171
+ for (const key of rejectedSensitive) {
172
+ droppedFromProject.push(key);
173
+ warnings.push(
174
+ `project: option "${key}" is sensitive and cannot be set from project config — use user scope / OS keychain`,
175
+ );
176
+ }
110
177
 
111
178
  // Project layer first (lower precedence). validateOptions errors on sensitive/
112
179
  // user-only keys at project scope — those are the drops we surface + refuse.
113
- const proj = acceptedKeys(s, projectValues, "project");
180
+ const proj = acceptedKeys(s, projectInput, "project");
114
181
  for (const err of proj.res.errors) {
115
182
  if (/sensitive|user-scoped/.test(err)) {
116
183
  const m = err.match(/"([^"]+)"/);
@@ -145,7 +212,7 @@ export function resolvePluginOptions(
145
212
  /** Load both scopes' values from disk and resolve against a schema. */
146
213
  export function getResolvedPluginOptions(name, schema, { cwd } = {}) {
147
214
  return resolvePluginOptions(schema, {
148
- userValues: loadPluginOptionValues(name, "user", { cwd }),
149
- projectValues: loadPluginOptionValues(name, "project", { cwd }),
215
+ userValues: loadPluginOptionValues(name, "user", { cwd, schema }),
216
+ projectValues: loadPluginOptionValues(name, "project", { cwd, schema }),
150
217
  });
151
218
  }
@@ -30,8 +30,37 @@ export const _deps = {
30
30
  readFileSync: fs.readFileSync,
31
31
  writeFileSync: fs.writeFileSync,
32
32
  existsSync: fs.existsSync,
33
+ readdirSync: fs.readdirSync,
34
+ statSync: fs.statSync,
33
35
  };
34
36
 
37
+ /** Build a deterministic file-level SBOM for an installed plugin directory. */
38
+ export function buildPluginSbom(root) {
39
+ const files = [];
40
+ const walk = (dir) => {
41
+ for (const entry of _deps.readdirSync(dir, { withFileTypes: true })) {
42
+ const abs = path.join(dir, entry.name);
43
+ const rel = path.relative(root, abs).replace(/\\/g, "/");
44
+ if (rel === LOCK_FILENAME) continue;
45
+ if (entry.isDirectory()) walk(abs);
46
+ else if (entry.isFile()) {
47
+ const bytes = _deps.readFileSync(abs);
48
+ files.push({
49
+ path: rel,
50
+ bytes: bytes.length,
51
+ sha256: createHash("sha256").update(bytes).digest("hex"),
52
+ });
53
+ }
54
+ }
55
+ };
56
+ walk(path.resolve(root));
57
+ files.sort((a, b) => a.path.localeCompare(b.path));
58
+ const digest = createHash("sha256")
59
+ .update(files.map((file) => `${file.path}\0${file.sha256}\n`).join(""))
60
+ .digest("hex");
61
+ return { version: 1, digest, files };
62
+ }
63
+
35
64
  /** Record a verified signature into the version dir. */
36
65
  export function writePluginLock(
37
66
  versionDir,
@@ -42,6 +71,7 @@ export function writePluginLock(
42
71
  signatureVerified,
43
72
  signatureBase64,
44
73
  publicKeyPem,
74
+ sbom = null,
45
75
  },
46
76
  ) {
47
77
  const rel = path.relative(versionDir, manifestFile).replace(/\\/g, "/");
@@ -55,6 +85,7 @@ export function writePluginLock(
55
85
  // lock is just self-asserted JSON and counts as unsigned.
56
86
  signatureBase64: signatureBase64 || null,
57
87
  publicKeyPem: publicKeyPem || null,
88
+ ...(sbom ? { sbom } : {}),
58
89
  };
59
90
  _deps.writeFileSync(
60
91
  path.join(versionDir, LOCK_FILENAME),
@@ -167,6 +198,20 @@ export function verifyInstalledSignature(plugin, opts = {}) {
167
198
  reason: "recorded signature does not verify over the on-disk manifest",
168
199
  };
169
200
  }
201
+ if (lock.sbom) {
202
+ let actualSbom;
203
+ try {
204
+ actualSbom = buildPluginSbom(plugin.root);
205
+ } catch {
206
+ return { signed: false, reason: "plugin SBOM cannot be read" };
207
+ }
208
+ if (
209
+ actualSbom.digest !== lock.sbom.digest ||
210
+ JSON.stringify(actualSbom.files) !== JSON.stringify(lock.sbom.files)
211
+ ) {
212
+ return { signed: false, reason: "plugin component SBOM mismatch" };
213
+ }
214
+ }
170
215
  const trustedKeys = opts.trustedKeys;
171
216
  if (trustedKeys && trustedKeys.size > 0) {
172
217
  if (!trustedKeys.has(publicKeySha256)) {
@@ -4,8 +4,23 @@
4
4
  * @module lib/pr-create
5
5
  */
6
6
 
7
- import { execSync } from "child_process";
8
7
  import { logger } from "./logger.js";
8
+ import { executionBroker } from "./process-execution-broker/index.js";
9
+
10
+ export const _deps = {
11
+ execFileSync: (...args) => executionBroker.execFileSync(...args),
12
+ };
13
+
14
+ function git(args, options = {}) {
15
+ return _deps.execFileSync("git", args, {
16
+ encoding: "utf8",
17
+ ...options,
18
+ origin: "pr:git",
19
+ policy: "allow",
20
+ scope: "pr",
21
+ shell: false,
22
+ });
23
+ }
9
24
 
10
25
  /**
11
26
  * Get current git branch
@@ -13,9 +28,7 @@ import { logger } from "./logger.js";
13
28
  */
14
29
  export function getCurrentBranch() {
15
30
  try {
16
- return execSync("git rev-parse --abbrev-ref HEAD", {
17
- encoding: "utf8",
18
- }).trim();
31
+ return git(["rev-parse", "--abbrev-ref", "HEAD"]).trim();
19
32
  } catch {
20
33
  return "main";
21
34
  }
@@ -27,7 +40,7 @@ export function getCurrentBranch() {
27
40
  */
28
41
  export function getRemoteUrl() {
29
42
  try {
30
- return execSync("git remote get-url origin", { encoding: "utf8" }).trim();
43
+ return git(["remote", "get-url", "origin"]).trim();
31
44
  } catch {
32
45
  return null;
33
46
  }
@@ -58,7 +71,7 @@ export async function preparePullRequest(options = {}) {
58
71
  const repo = parseGitHubRepo();
59
72
 
60
73
  // Check for uncommitted changes
61
- const status = execSync("git status --porcelain", { encoding: "utf8" });
74
+ const status = git(["status", "--porcelain"]);
62
75
  const hasChanges = status.trim().length > 0;
63
76
 
64
77
  if (hasChanges && !options.skipStash) {
@@ -72,13 +85,13 @@ export async function preparePullRequest(options = {}) {
72
85
  const logRange = `${defaultBase}...${branch}`;
73
86
  let commitLog = "";
74
87
  try {
75
- commitLog = execSync(`git log ${logRange} --oneline`, { encoding: "utf8" });
88
+ commitLog = git(["log", "--oneline", "--end-of-options", logRange, "--"]);
76
89
  } catch {
77
90
  commitLog = "";
78
91
  }
79
92
 
80
93
  const prUrl = repo
81
- ? `https://github.com/${repo.owner}/${repo.repo}/compare/${defaultBase}...${branch}?expand=1`
94
+ ? `https://github.com/${repo.owner}/${repo.repo}/compare/${encodeURIComponent(defaultBase)}...${encodeURIComponent(branch)}?expand=1`
82
95
  : null;
83
96
 
84
97
  logger.info(`Branch: ${branch}`);
@@ -17,11 +17,14 @@
17
17
  */
18
18
 
19
19
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
20
- import { execFile } from "node:child_process";
21
20
  import { join } from "node:path";
22
21
  import { getHomeDir } from "./paths.js";
22
+ import { executionBroker } from "./process-execution-broker/index.js";
23
23
 
24
- export const _deps = { execFile, now: () => Date.now() };
24
+ export const _deps = {
25
+ execFile: (...args) => executionBroker.execFile(...args),
26
+ now: () => Date.now(),
27
+ };
25
28
 
26
29
  const MAX_LINKS_PER_SESSION = 20;
27
30
  const MAX_SESSIONS = 500;
@@ -150,7 +153,16 @@ function ghPrForBranch(cwd, timeoutMs = 3000) {
150
153
  _deps.execFile(
151
154
  file,
152
155
  fileArgs,
153
- { cwd, encoding: "utf8", timeout: timeoutMs, windowsHide: true },
156
+ {
157
+ cwd,
158
+ encoding: "utf8",
159
+ timeout: timeoutMs,
160
+ windowsHide: true,
161
+ origin: "pr:link-query",
162
+ policy: "allow",
163
+ scope: "pr",
164
+ shell: false,
165
+ },
154
166
  (err, stdout) => resolve(err ? null : String(stdout || "").trim()),
155
167
  );
156
168
  });