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
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Provider HTTP error parsing shared by agent/chat streaming and `cc llm test`.
3
+ * Keep structured provider diagnostics while redacting credential-shaped text.
4
+ */
5
+
6
+ function safePart(value) {
7
+ if (value == null) return "";
8
+ return String(value)
9
+ .replace(/\s+/g, " ")
10
+ .replace(/\b(Bearer\s+)[A-Za-z0-9._~+/-]+=*\b/gi, "$1***")
11
+ .replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gi, "sk-***")
12
+ .trim()
13
+ .slice(0, 400);
14
+ }
15
+
16
+ function errorDetail(payload) {
17
+ if (payload == null) return { code: "", message: "" };
18
+ const raw =
19
+ typeof payload === "object" && payload.error != null
20
+ ? payload.error
21
+ : payload;
22
+ if (typeof raw === "string") {
23
+ return { code: "", message: safePart(raw) };
24
+ }
25
+ if (!raw || typeof raw !== "object") {
26
+ return { code: "", message: safePart(raw) };
27
+ }
28
+ return {
29
+ code: safePart(raw.code || raw.type),
30
+ message: safePart(raw.message || raw.error_description || raw.detail),
31
+ };
32
+ }
33
+
34
+ /**
35
+ * A 403 is not necessarily a bad key: providers also use it for overdue
36
+ * accounts and model-access denials. Preserve the safe code/message so clients
37
+ * can show the real corrective action.
38
+ */
39
+ export function formatProviderHttpError(provider, status, payload = null) {
40
+ const base = `${provider} API error: HTTP ${status}`;
41
+ const detail = errorDetail(payload);
42
+ const detailText = [detail.code, detail.message].filter(Boolean).join(": ");
43
+ const detailSentence = detailText.replace(/[.!?]+$/, "");
44
+ const classified = `${detail.code} ${detail.message}`.toLowerCase();
45
+ const authDetail =
46
+ /unauthori[sz]ed|authentication|invalid.*api[\s_-]*key|api[\s_-]*key.*invalid|incorrect.*api[\s_-]*key|missing.*api[\s_-]*key/.test(
47
+ classified,
48
+ );
49
+ const billingDetail =
50
+ /account.?overdue|overdue balance|insufficient.*balance|billing|payment required/.test(
51
+ classified,
52
+ );
53
+
54
+ if (status === 401 || (status === 403 && authDetail)) {
55
+ return (
56
+ `${base} — authentication failed: the API key for provider "${provider}" ` +
57
+ `is missing or invalid. Check "cc config get llm.provider" and ` +
58
+ `"cc config get llm.apiKey" (or run Configure LLM).` +
59
+ (detailSentence ? ` Provider response: ${detailSentence}.` : "")
60
+ );
61
+ }
62
+ if (status === 403 && billingDetail) {
63
+ return (
64
+ `${base} — ${detailSentence || "the provider account cannot be billed"}. ` +
65
+ "Check the provider account balance/billing status, then retry."
66
+ );
67
+ }
68
+ if (status === 403) {
69
+ return (
70
+ `${base} — access forbidden` +
71
+ (detailSentence ? `: ${detailSentence}` : "") +
72
+ ". Check the API key, model access permissions, and account status/balance."
73
+ );
74
+ }
75
+ if (status === 429) return `${base} — rate limited; please retry shortly.`;
76
+ return detailSentence ? `${base} — ${detailSentence}` : base;
77
+ }
78
+
79
+ export async function formatProviderResponseError(provider, response) {
80
+ let payload = null;
81
+ try {
82
+ const text = await response.text();
83
+ if (text) {
84
+ try {
85
+ payload = JSON.parse(text);
86
+ } catch {
87
+ payload = text;
88
+ }
89
+ }
90
+ } catch {
91
+ // A broken/empty body still retains the HTTP status diagnosis.
92
+ }
93
+ return formatProviderHttpError(provider, response.status, payload);
94
+ }
@@ -23,10 +23,12 @@
23
23
 
24
24
  import { randomBytes } from "crypto";
25
25
  import { WsRpcClient } from "./ws-rpc-client.js";
26
+ import { ORIGIN, approvalBindingDigest } from "./agent-authority.js";
26
27
  import {
27
- fingerprintsMatch,
28
- OperationApprovalRegistry,
29
- } from "./operation-fingerprint.js";
28
+ ApprovalAuthorityStore,
29
+ defaultApprovalAuthorityStatePath,
30
+ } from "./approval-authority-store.js";
31
+ import { OperationApprovalRegistry } from "./operation-fingerprint.js";
30
32
  import {
31
33
  buildDirectPairingUri,
32
34
  pickLanAddress,
@@ -46,6 +48,9 @@ export class RemoteApprovalBridge {
46
48
  decisionTimeoutMs = DEFAULT_DECISION_TIMEOUT_MS,
47
49
  createClient = null,
48
50
  now = Date.now,
51
+ approvalStore = undefined,
52
+ approvalStateFile = null,
53
+ onSecurityError = null,
49
54
  } = {}) {
50
55
  if (!wsUrl) throw new Error("wsUrl is required");
51
56
  if (!agentSessionId) throw new Error("agentSessionId is required");
@@ -63,12 +68,65 @@ export class RemoteApprovalBridge {
63
68
  this._pending = new Map(); // requestId → { resolve, timer, fingerprint }
64
69
  this._counter = 0;
65
70
  this._closed = false;
71
+ this._securityErrors = [];
72
+ this._onSecurityError =
73
+ typeof onSecurityError === "function" ? onSecurityError : null;
74
+ const durableStore =
75
+ approvalStore === undefined
76
+ ? new ApprovalAuthorityStore({
77
+ filePath:
78
+ approvalStateFile ||
79
+ defaultApprovalAuthorityStatePath(agentSessionId),
80
+ now: () => this._now(),
81
+ })
82
+ : approvalStore;
83
+ if (
84
+ !durableStore ||
85
+ typeof durableStore.issueRequest !== "function" ||
86
+ typeof durableStore.resolveRequest !== "function" ||
87
+ typeof durableStore.cancelRequest !== "function"
88
+ ) {
89
+ throw new Error(
90
+ "approvalStore must implement issueRequest/resolveRequest/cancelRequest",
91
+ );
92
+ }
66
93
  // §8.2 cross-device approval registry: full-tuple operation fingerprints,
67
94
  // single-winner across concurrent cards for one logical operation, at-most-
68
95
  // once resolution, and validity-window enforcement — all fail-closed.
69
96
  this._registry = new OperationApprovalRegistry({
70
97
  clock: () => this._now(),
98
+ store: durableStore,
71
99
  });
100
+ this._approvalStore = durableStore;
101
+ }
102
+
103
+ _recordSecurityError({ action, requestId = null, reason, errorCode = null }) {
104
+ const entry = {
105
+ timestamp: this._now(),
106
+ action: String(action || "approval"),
107
+ requestId: requestId ? String(requestId) : null,
108
+ reason: String(reason || "rejected"),
109
+ errorCode: errorCode ? String(errorCode) : null,
110
+ };
111
+ this._securityErrors.push(entry);
112
+ if (this._securityErrors.length > 1000) this._securityErrors.shift();
113
+ if (this._onSecurityError) {
114
+ try {
115
+ this._onSecurityError({ ...entry });
116
+ } catch {
117
+ // Observability is advisory; the approval remains denied.
118
+ }
119
+ }
120
+ return entry;
121
+ }
122
+
123
+ getSecurityErrors(limit = this._securityErrors.length) {
124
+ const count = Math.max(
125
+ 0,
126
+ Math.min(Math.floor(Number(limit) || 0), this._securityErrors.length),
127
+ );
128
+ if (count === 0) return [];
129
+ return this._securityErrors.slice(-count).map((entry) => ({ ...entry }));
72
130
  }
73
131
 
74
132
  /** Connect, register the client-hosted remote session, start listening. */
@@ -123,34 +181,76 @@ export class RemoteApprovalBridge {
123
181
  const requestId = message.event.requestId || message.event.approvalId;
124
182
  const pending = requestId ? this._pending.get(requestId) : null;
125
183
  if (!pending) return;
126
- // Confused-deputy guard: a resolve that echoes a fingerprint must match the
127
- // operation this ask published. A mismatch (stale card / replayed / swapped
128
- // body / different session·workspace·env·policy) is rejected the ask stays
129
- // pending and fails closed on timeout. An absent fingerprint is a legacy
130
- // device: resolved via this ask's own fingerprint (still window-guarded).
131
- if (
132
- message.event.fingerprint != null &&
133
- !fingerprintsMatch(pending.fingerprint, message.event.fingerprint)
134
- ) {
184
+ // The device must echo the complete durable capability tuple. Missing,
185
+ // mismatched, stale, duplicate, or expired resolutions never settle an
186
+ // approval; only the store's successful CAS can return approved=true.
187
+ const rawAnswer = message.event.answer ?? message.event.approved;
188
+ const hasDecision =
189
+ rawAnswer === true ||
190
+ rawAnswer === false ||
191
+ rawAnswer === "true" ||
192
+ rawAnswer === "false" ||
193
+ rawAnswer === "yes" ||
194
+ rawAnswer === "no";
195
+ if (!hasDecision) {
196
+ this._recordSecurityError({
197
+ action: "approval.resolve",
198
+ requestId,
199
+ reason: "decision-required",
200
+ });
135
201
  return;
136
202
  }
137
- // Fail-closed §8.2 enforcement: single-winner (superseded card), at-most-once
138
- // (duplicate), and validity window (not-yet-valid / expired). A rejected
139
- // verdict leaves the ask pending so it still fails closed on timeout.
203
+ const decision =
204
+ rawAnswer === true || rawAnswer === "true" || rawAnswer === "yes";
205
+ const authority = {
206
+ origin: ORIGIN.REMOTE,
207
+ authenticated: true,
208
+ scopes: ["approve"],
209
+ principalId: message.from || "paired-device",
210
+ sessionId: this.agentSessionId,
211
+ };
140
212
  const verdict = this._registry.resolve(pending.fingerprint, {
213
+ requestId,
214
+ fingerprint: message.event.fingerprint,
215
+ binding: message.event.binding,
216
+ sessionId: this.agentSessionId,
217
+ decision,
218
+ authority,
219
+ expectedRevision: message.event.revision,
141
220
  now: this._now(),
142
221
  });
143
- if (!verdict.ok) return;
222
+ if (!verdict.ok) {
223
+ this._recordSecurityError({
224
+ action: "approval.resolve",
225
+ requestId,
226
+ reason: verdict.reason,
227
+ errorCode: verdict.errorCode,
228
+ });
229
+ if (verdict.reason === "state-unavailable") {
230
+ this._settleDeniedForStateFailure(requestId, pending, verdict);
231
+ }
232
+ return;
233
+ }
144
234
  this._pending.delete(requestId);
145
235
  clearTimeout(pending.timer);
146
- const answer = message.event.answer ?? message.event.approved;
147
236
  pending.resolve({
148
- approved: answer === true || answer === "true" || answer === "yes",
237
+ approved: verdict.ok === true && verdict.approved === true,
149
238
  via: "remote",
150
239
  from: message.from || null,
151
240
  });
152
241
  }
153
242
 
243
+ _settleDeniedForStateFailure(requestId, pending, verdict) {
244
+ this._pending.delete(requestId);
245
+ clearTimeout(pending.timer);
246
+ pending.resolve({
247
+ approved: false,
248
+ via: "state-error",
249
+ from: null,
250
+ errorCode: verdict?.errorCode || null,
251
+ });
252
+ }
253
+
154
254
  /** Number of devices that can approve (excludes this host). */
155
255
  async approverCount() {
156
256
  try {
@@ -202,7 +302,42 @@ export class RemoteApprovalBridge {
202
302
  ? askedAt + effectiveTimeout
203
303
  : null,
204
304
  };
205
- const card = this._registry.issue(desc);
305
+ const binding = approvalBindingDigest({
306
+ toolCallId: requestId,
307
+ args: {
308
+ tool: tool || null,
309
+ action,
310
+ detail,
311
+ workspace,
312
+ session: desc.session,
313
+ targetEnv,
314
+ },
315
+ policyDigest: policyVersion,
316
+ });
317
+ let card;
318
+ try {
319
+ // Persist first. A card that was not durably issued must never become
320
+ // visible to a device and can therefore never authorize a side effect.
321
+ card = this._registry.issue(desc, {
322
+ requestId,
323
+ binding,
324
+ now: askedAt,
325
+ });
326
+ } catch (error) {
327
+ const errorCode = error?.code || "CC_APPROVAL_STATE_UNKNOWN";
328
+ this._recordSecurityError({
329
+ action: "approval.request",
330
+ requestId,
331
+ reason: "state-unavailable",
332
+ errorCode,
333
+ });
334
+ return Promise.resolve({
335
+ approved: false,
336
+ via: "state-error",
337
+ from: null,
338
+ errorCode,
339
+ });
340
+ }
206
341
  if (onRequestId) {
207
342
  try {
208
343
  onRequestId(requestId);
@@ -212,6 +347,20 @@ export class RemoteApprovalBridge {
212
347
  }
213
348
  return new Promise((resolve) => {
214
349
  const timer = setTimeout(() => {
350
+ const verdict = this._registry.cancel(card.fingerprint, {
351
+ requestId,
352
+ expectedRevision: card.revision,
353
+ reason: "timeout",
354
+ now: this._now(),
355
+ });
356
+ if (!verdict.ok) {
357
+ this._recordSecurityError({
358
+ action: "approval.cancel",
359
+ requestId,
360
+ reason: verdict.reason,
361
+ errorCode: verdict.errorCode,
362
+ });
363
+ }
215
364
  this._pending.delete(requestId);
216
365
  this._publish({
217
366
  type: "permission.resolved",
@@ -225,6 +374,8 @@ export class RemoteApprovalBridge {
225
374
  this._pending.set(requestId, {
226
375
  timer,
227
376
  fingerprint: card.fingerprint,
377
+ binding,
378
+ revision: card.revision,
228
379
  resolve: (decision) => {
229
380
  this._publish({
230
381
  type: "permission.resolved",
@@ -244,6 +395,8 @@ export class RemoteApprovalBridge {
244
395
  // Full fingerprint (protocol) + short id / secret-free summary (what the
245
396
  // operator eyeballs on the device to confirm it is the SAME card).
246
397
  fingerprint: card.fingerprint,
398
+ binding,
399
+ revision: card.revision,
247
400
  shortId: card.shortId,
248
401
  summary: card.summary,
249
402
  notBefore: desc.notBefore,
@@ -257,12 +410,39 @@ export class RemoteApprovalBridge {
257
410
  resolveLocally(requestId, approved) {
258
411
  const pending = this._pending.get(requestId);
259
412
  if (!pending) return false;
413
+ const verdict = this._registry.resolve(pending.fingerprint, {
414
+ requestId,
415
+ fingerprint: pending.fingerprint,
416
+ binding: pending.binding,
417
+ sessionId: this.agentSessionId,
418
+ decision: approved === true,
419
+ authority: {
420
+ origin: ORIGIN.USER,
421
+ principalId: "local-terminal",
422
+ sessionId: this.agentSessionId,
423
+ },
424
+ expectedRevision: pending.revision,
425
+ now: this._now(),
426
+ });
427
+ if (!verdict.ok) {
428
+ this._recordSecurityError({
429
+ action: "approval.resolve",
430
+ requestId,
431
+ reason: verdict.reason,
432
+ errorCode: verdict.errorCode,
433
+ });
434
+ if (verdict.reason === "state-unavailable") {
435
+ this._settleDeniedForStateFailure(requestId, pending, verdict);
436
+ }
437
+ return false;
438
+ }
260
439
  this._pending.delete(requestId);
261
440
  clearTimeout(pending.timer);
262
- // Consume the registry card so a late remote resolve for the SAME operation
263
- // is a `duplicate`, never a second settle.
264
- this._registry.resolve(pending.fingerprint, { now: this._now() });
265
- pending.resolve({ approved, via: "local", from: null });
441
+ pending.resolve({
442
+ approved: verdict.ok === true && verdict.approved === true,
443
+ via: "local",
444
+ from: null,
445
+ });
266
446
  return true;
267
447
  }
268
448
 
@@ -327,10 +507,12 @@ export class RemoteApprovalBridge {
327
507
  const decision = await Promise.race([remote, local]);
328
508
  // Local answer won → settle the remote ask too (publishes
329
509
  // permission.resolved so device UIs clear the pending card).
330
- if (decision.via === "local" && requestId) {
331
- this.resolveLocally(requestId, decision.approved);
510
+ if (decision.via === "local") {
511
+ if (!requestId) return false;
512
+ const persisted = this.resolveLocally(requestId, decision.approved);
513
+ return persisted && decision.approved === true;
332
514
  }
333
- return decision.approved;
515
+ return decision.approved === true;
334
516
  };
335
517
  }
336
518
 
@@ -338,6 +520,20 @@ export class RemoteApprovalBridge {
338
520
  this._closed = true;
339
521
  for (const [requestId, pending] of this._pending) {
340
522
  clearTimeout(pending.timer);
523
+ const verdict = this._registry.cancel(pending.fingerprint, {
524
+ requestId,
525
+ expectedRevision: pending.revision,
526
+ reason: "closed",
527
+ now: this._now(),
528
+ });
529
+ if (!verdict.ok) {
530
+ this._recordSecurityError({
531
+ action: "approval.cancel",
532
+ requestId,
533
+ reason: verdict.reason,
534
+ errorCode: verdict.errorCode,
535
+ });
536
+ }
341
537
  pending.resolve({ approved: false, via: "closed", from: null });
342
538
  this._pending.delete(requestId);
343
539
  }
@@ -17,10 +17,10 @@
17
17
  * All process/fs access goes through `_deps` for tests.
18
18
  */
19
19
 
20
- import { spawnSync as spawnSyncDefault } from "child_process";
21
20
  import fsDefault from "fs";
22
21
  import pathDefault from "path";
23
22
  import { findProjectRoot } from "./project-instructions.js";
23
+ import executionBroker from "./process-execution-broker/index.js";
24
24
 
25
25
  export const BANG_TIMEOUT_MS = 120_000;
26
26
  export const BANG_MAX_BUFFER = 10 * 1024 * 1024;
@@ -32,7 +32,7 @@ export const BANG_OUTPUT_CAP = 30_000;
32
32
  export const MEMO_NOTE_MAX = 4_000;
33
33
 
34
34
  export const _deps = {
35
- spawnSync: spawnSyncDefault,
35
+ spawnSync: (...args) => executionBroker.spawnSync(...args),
36
36
  fs: fsDefault,
37
37
  path: pathDefault,
38
38
  };
@@ -83,12 +83,20 @@ export function runBangCommand(line, opts = {}) {
83
83
  timeout: BANG_TIMEOUT_MS,
84
84
  maxBuffer: BANG_MAX_BUFFER,
85
85
  cwd,
86
+ origin: "repl:bang-command",
87
+ policy: "allow",
88
+ scope: "repl",
89
+ shell: false,
86
90
  })
87
91
  : spawnSync("/bin/sh", ["-c", cmd], {
88
92
  encoding: "utf-8",
89
93
  timeout: BANG_TIMEOUT_MS,
90
94
  maxBuffer: BANG_MAX_BUFFER,
91
95
  cwd,
96
+ origin: "repl:bang-command",
97
+ policy: "allow",
98
+ scope: "repl",
99
+ shell: false,
92
100
  });
93
101
 
94
102
  const exitCode = res.status == null ? (res.error ? -1 : 0) : res.status;
@@ -19,6 +19,23 @@ import {
19
19
  GoalConditionEngine,
20
20
  GOAL_DECISION,
21
21
  } from "./goal-condition-engine.js";
22
+ import executionBroker from "./process-execution-broker/index.js";
23
+
24
+ const brokerRunner = executionBroker.spawnSync.bind(executionBroker);
25
+
26
+ export const _processDeps = {
27
+ run: brokerRunner,
28
+ };
29
+
30
+ function runReplGoalCommand(command, options = {}) {
31
+ return _processDeps.run(command, [], {
32
+ ...options,
33
+ timeout: options.timeout ?? 30000,
34
+ origin: "repl-goal:exit-zero",
35
+ policy: "allow",
36
+ scope: "repl-goal",
37
+ });
38
+ }
22
39
 
23
40
  // Interactive sessions are human-paced, so the turn-count budget is generous —
24
41
  // it exists only as a backstop (the engine hard-caps at 100 regardless). The
@@ -94,7 +111,7 @@ export function renderGoalVerdict(decision, events) {
94
111
  /**
95
112
  * Evaluate the session goal against a completed turn's final text. Deterministic
96
113
  * conditions run inline (contains/regex on the text; exit-zero/file-exists via
97
- * injected `spawnSync`/`existsSync`); a model condition delegates to `judge`.
114
+ * injected process runner/`existsSync`); a model condition delegates to `judge`.
98
115
  *
99
116
  * @param {GoalConditionEngine} engine
100
117
  * @param {string} finalText the assistant's answer this turn
@@ -110,7 +127,7 @@ export async function evaluateReplGoalTurn(engine, finalText, deps = {}) {
110
127
  evaluation = runDeterministicCheck(cond, {
111
128
  lastOutput: finalText,
112
129
  cwd: deps.cwd,
113
- spawnSync: deps.spawnSync,
130
+ spawnSync: deps.spawnSync || runReplGoalCommand,
114
131
  existsSync: deps.existsSync,
115
132
  });
116
133
  } else if (typeof deps.judge === "function") {
@@ -17,7 +17,8 @@
17
17
  */
18
18
 
19
19
  const { collectHooks } = require("./settings-hooks.cjs");
20
- const { runHooks } = require("./hook-runner.cjs");
20
+ const hookRunner = require("./hook-runner.cjs");
21
+ const _deps = { runHooks: hookRunner.runHooks };
21
22
  const { buildHookEnvelope } = require("./hook-event-bus.cjs");
22
23
  const hookEventLog = require("./hook-event-log.cjs");
23
24
 
@@ -143,7 +144,7 @@ function runUserPromptSubmitHooks(
143
144
  },
144
145
  { sessionId },
145
146
  );
146
- const outcome = runHooks(sync, payload, {
147
+ const outcome = _deps.runHooks(sync, payload, {
147
148
  cwd,
148
149
  event: "UserPromptSubmit",
149
150
  });
@@ -211,7 +212,10 @@ function runSessionStartHooks(settingsHooks, { source, cwd, sessionId } = {}) {
211
212
  },
212
213
  { sessionId },
213
214
  );
214
- const outcome = runHooks(matched, payload, { cwd, event: "SessionStart" });
215
+ const outcome = _deps.runHooks(matched, payload, {
216
+ cwd,
217
+ event: "SessionStart",
218
+ });
215
219
  return { additionalContext: aggregateContext(outcome.results) };
216
220
  }
217
221
 
@@ -247,7 +251,7 @@ function runCwdChangedHooks(
247
251
  },
248
252
  { sessionId },
249
253
  );
250
- const outcome = runHooks(sync, payload, {
254
+ const outcome = _deps.runHooks(sync, payload, {
251
255
  cwd: newCwd || cwd,
252
256
  event: "CwdChanged",
253
257
  });
@@ -291,7 +295,7 @@ function runWorktreeCreateHooks(
291
295
  },
292
296
  { sessionId },
293
297
  );
294
- const outcome = runHooks(sync, payload, {
298
+ const outcome = _deps.runHooks(sync, payload, {
295
299
  cwd: cwd || worktreePath,
296
300
  event: "WorktreeCreate",
297
301
  });
@@ -337,7 +341,7 @@ function runWorktreeRemoveHooks(
337
341
  },
338
342
  { sessionId },
339
343
  );
340
- const outcome = runHooks(sync, payload, {
344
+ const outcome = _deps.runHooks(sync, payload, {
341
345
  cwd: cwd || worktreePath,
342
346
  event: "WorktreeRemove",
343
347
  });
@@ -386,7 +390,7 @@ function runInstructionsLoadedHooks(
386
390
  },
387
391
  { sessionId },
388
392
  );
389
- const outcome = runHooks(sync, payload, {
393
+ const outcome = _deps.runHooks(sync, payload, {
390
394
  cwd,
391
395
  event: "InstructionsLoaded",
392
396
  });
@@ -417,7 +421,7 @@ function runObserveHooks(
417
421
  const matched = collectHooks(settingsHooks, event, matchTarget || "");
418
422
  const { sync } = partitionAsyncHooks(matched);
419
423
  if (sync.length === 0) return { decision: "continue", results: [] };
420
- return runHooks(
424
+ return _deps.runHooks(
421
425
  sync,
422
426
  withDeliveryId(
423
427
  event,
@@ -440,4 +444,5 @@ module.exports = {
440
444
  aggregateContext,
441
445
  partitionAsyncHooks,
442
446
  dispatchAsyncHooks,
447
+ _deps,
443
448
  };
@@ -0,0 +1,20 @@
1
+ import { runHooks } from "./hook-runner.js";
2
+ import events from "./settings-hook-events.cjs";
3
+
4
+ events._deps.runHooks = runHooks;
5
+
6
+ export const {
7
+ withDeliveryId,
8
+ runUserPromptSubmitHooks,
9
+ runSessionStartHooks,
10
+ runCwdChangedHooks,
11
+ runWorktreeCreateHooks,
12
+ runWorktreeRemoveHooks,
13
+ runInstructionsLoadedHooks,
14
+ runObserveHooks,
15
+ aggregateContext,
16
+ partitionAsyncHooks,
17
+ dispatchAsyncHooks,
18
+ } = events;
19
+
20
+ export default events;