chainlesschain 0.165.6 → 0.165.9

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 (251) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-vfoDb6HZ.js → AIOps-DxwjrnEA.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-Cm5f7p93.js → ActionButton-JdbYowzn.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-yRuvgWxa.js → Analytics-C06GCahv.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BROsC4h1.js → AppLayout-BUVEEyi1.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-CimHApb1.js → Artifacts-D_ORzkJd.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-DI8kr8zI.js → Audit-8o_Y5ejG.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DSLzKy-n.js → BackgroundAgents-DrkHd5VU.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-DkH_n2r1.js → Backup-CKBZCX11.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-CKSrUoRA.js → BaseInput-C8HkI399.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-ClwfMXUS.js → Chat-zb2H2Wux.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CjMaqfL7.js → ChatBubbleRenderer-BDcNpU_F.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-BYTehcQG.js → Checkbox-MwPtQmNz.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-B8AMcp6J.js → Codegen-3p5QCkFK.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-BNSogPo3.js → Col-BPLlhn52.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-JxPvGb8O.js → Community-C-3dBNOM.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-DF7bFAgE.js → Compact-BUcy-F_b.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Bvhqnwrq.js → Compliance-CI8NxT8m.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-BDS0CJvM.js → Cowork-DaDEBS-Q.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DqvRfxoQ.js → Cron-BSv9HXu5.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CDcIvnqS.js → Crosschain-yuiKlJmv.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-D7jaUxU3.js → DID-D6LfldB0.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-B5A18wEV.js → Dashboard-CBhLqG61.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-_6IVkGag.js → Dropdown-BG8pIl3O.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-C9PeiKCG.js → EmailListRenderer-CY92VIE6.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DXjuEHrX.js → FamilyGuardDashboard-1Q_ehauM.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-B4IAR9zv.js → Federation-D3XirJIU.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-CxQeSNx1.js → FormItemContext-DfI9UuGZ.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-B8GS-Y3N.js → GenericCardRenderer-IeCZk2m7.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-BS8SouUX.js → Git-DzK4IJAZ.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-Dq9aYb5Q.js → Governance-BHf5KfmQ.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BrCEe9AJ.js → Inference-BmaxSALS.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DybOpiY2.js → KnowledgeGraph-BgePFLA9.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DBpzbRfx.js → Logs-nqgxpOc4.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-xkX6izBt.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-Cc7CCSCu.js → Marketplace-Bu8to-86.js} +1 -1
  38. package/src/assets/web-panel/assets/McpTools-BFWTzEk0.js +4 -0
  39. package/src/assets/web-panel/assets/{Memory-KCqlp9ol.js → Memory-B026G2GA.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-Bys84ySN.js → MobileBridge-CM2Eeg6I.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-B-6qU-je.js → MobileProjects-B79Ob3hy.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-BgY-fvCq.js → Mtc-CxevSZuV.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-B8pCmqQJ.js → MtcAudit-X396cPEX.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BbOmYutA.js → Multisig-HWIB_aZ1.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-BocLQz_M.js → NLProgramming-gnYD1Xwy.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-CSwbxEop.js → Notes-Dn2Gf_J1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-CqFNSYG3.js → NotificationSettings-BRKBQ5rq.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-C6gMfAk7.js → OrderTableRenderer-Dy___Cgo.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-QrDXVdMJ.js → Organization-cqfccxnt.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-Cxntotjt.js → Overflow-CSX4FHN3.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CIdBOwNq.js → P2P-Bwa4aghp.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-CT5aP8rD.js → PdhVaultBrowser-Dhszyjig.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-DH7OM8XU.js → Permissions-CXzTyk6e.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-CnJqbWce.js → PersonalDataHub-CFCAAJbb.js} +4 -4
  55. package/src/assets/web-panel/assets/{Pipeline-5C3HG1kH.js → Pipeline-BPJbx6xt.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-B4yIp7xK.js → Privacy-BbiXvEHz.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BMvt-2M0.js → ProjectInit-B-s7-wSD.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-CvSTEMRG.js → ProjectSettings-Dyug206y.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-BKBJxEek.js → Projects-BtAI5Fwo.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-BdwUqFWN.js → Providers-JpIPmz6N.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-DtnCKlTm.js → QrScannerModal-CZdoN64A.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-sTbgwyNr.js → QuickAsk-BwvnoRIT.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-Bzr14gSb.js → Recommend-ASMlMQrD.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-C_TF5IaJ.js → RemoteSession-BiJzKFKi.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-GCAM4H2K.js → Reputation-C80TWLIO.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-Dir0r6OQ.js → Row-C1VNmjmX.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CpGnlecX.js → RssFeed-T2MyGUlG.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DMMamC6u.js → Search-DXM6O83L.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-yqay5yG-.js → Security-nv69kU7W.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-C5i2wh9G.js → Services-AyHWe7Qj.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-vUqk35yj.js → Skeleton-D6PWLxFI.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-DzcSkhot.js → Skills-BqVeOmNQ.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-CB6qbYNr.js → Sla-BegIPl9M.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-BHUI7cox.js → SpeechSettings-CKJn3xk-.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-D-RrsxTJ.js → SyncSettings-Th4cnAMl.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-DFxdOJiq.js → Tasks-BuKfBroh.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-SKAob_Aq.js → Templates-CMuWN8Ac.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-BPfsfHQ-.js → Tenant-C4je8E8Q.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-8iw7FpUf.js → Terminal-agJESOcO.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-C4Gjj5Su.js → TimelineRenderer-D2qDuVZ_.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-COYhN18e.js → Tokens-Cvmn99rH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-B-JzXcf6.js → Trigger-D_QYIHH8.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-BJ5bg0nI.js → Trust-BmzvQLnX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-BG_ByRMf.js → UkeySign-D_LopHwH.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-B3kOnSiU.js → VideoEditing-DoWl3PhQ.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-CcoGFnK7.js → Wallet-5NYcAkxe.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-DdT8vRC_.js → WebAuthn-B-_Q3ewp.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CZu3M9N8.js → WorkflowEditor-CHET-gi2.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-DxJt3Qba.js → chat-C6nvb-n6.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-DdYfwJaB.js → colors-CTDE9LTX.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BG3SUzwj.js → compact-item-KnemdF8D.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-By51z2-1.js → createContext-DUJR3Uek.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-1DqLH1KX.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-B0apZ3KJ.js → hasIn-CFNTaby8.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-ZxtP8jG7.js → index-65HO56Bv.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-Da_WBdLX.js → index-B8RtbSkV.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BBPf3TpM.js → index-BHqSqnW7.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BP94CrBV.js → index-BTetEUWd.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-p1_8SbI1.js → index-BXWg1crv.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BWF8_mkx.js → index-BdiC4LOs.js} +1 -1
  101. package/src/assets/web-panel/assets/index-BhJtcPWo.js +1 -0
  102. package/src/assets/web-panel/assets/{index-SQqOlR3d.js → index-BuizJo2E.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CpjZhgNd.js → index-BwZM1rod.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CzmQElZy.js → index-C96N9xeL.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-bP_VlDb4.js → index-CHfUdnJH.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-ZFbps9po.js → index-CKvBF3Ov.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DaIz0NAW.js → index-CSD9_I2_.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BewKYrX9.js → index-Cc7dbl_p.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CNIxXMmN.js → index-CcF0D7UZ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Q2SCX-MI.js → index-Ceu92a8D.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DE76D-kA.js → index-CnLpuTAU.js} +1 -1
  112. package/src/assets/web-panel/assets/index-Cq8MWPDT.js +1 -0
  113. package/src/assets/web-panel/assets/{index-BkvcEo4p.js → index-CquKnw5r.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Cp6e-hGw.js → index-CyEtHvEE.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BLIbGOLX.js → index-DF-fcTvQ.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DCn8IcxV.js → index-DF1Y0Vuw.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bissefox.js → index-DJyPeBBk.js} +3 -3
  118. package/src/assets/web-panel/assets/{index-BZ_0qm4g.js → index-DP-PbO11.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-kf57LJ93.js → index-DZgCRMxk.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BYINoRLK.js → index-DfJzS3Qa.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-3jWkIu5j.js → index-DqPpJkte.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B5rLiEo0.js → index-DzReoLyh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CW93tZDv.js → index-JGTiDeOW.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C1C9i79A.js → index-NUR0If7O.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CAhHirVH.js → index-NtAcnJYW.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-RD6O-0C6.js → index-OmuhFYKE.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-oxRrmFO9.js → index-Wlc7o_C8.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-B3rWuPMW.js → index-bxTPfdri.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BIrJfqO4.js → index-k6uorYmf.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BfWYsB9t.js → index-ox6mIwE2.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Bos5_aMV.js → index-rVDD7AAR.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CWEuZWCK.js → index-u0h6QqVV.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-Dz49VOyQ.js → index-v-mtxmWH.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-BWJktcg8.js → initDefaultProps-qEt8dI-t.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BEXBzUFV.js → motion-DetKPWy-.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-BUKwn2sx.js → move-BeNYeDV2.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-FTI7btqQ.js → mtc-parser-C0q0MK_T.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-CsLtSPH3.js → omit-DLKkrKpE.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-DWZxsT_S.js → pickAttrs-Bw1tWsY8.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-Bcfs43CX.js → placementArrow-DeesBLbd.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-a9bcC1p-.js → responsiveObserve-bqLhxHhn.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-BDTzgOXN.js → slide-DGCXRoQm.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-Iq1j_HUg.js → statusUtils-H-re3Egl.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-DAZEYxeh.js → styleChecker-BXg4qGX_.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DVkjyDrh.js → useFlexGapSupport-CKLb2KA6.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-wXTpNTHt.js → useFs-CTAhHeyw.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-CtQM_aZr.js → usePersonalDataHub-BQ4pDh5g.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-hjEoG85v.js → vnode-jrSK6j4j.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-BHVpyKg_.js → zoom-fOQE24pw.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +3 -3
  152. package/src/commands/agent.js +91 -60
  153. package/src/commands/git.js +39 -0
  154. package/src/commands/plugin.js +17 -2
  155. package/src/commands/session-group.js +131 -0
  156. package/src/commands/session-location.js +48 -0
  157. package/src/commands/session.js +11 -0
  158. package/src/commands/sync-providers.js +4 -1
  159. package/src/commands/update.js +1 -0
  160. package/src/data/changelog.json +40 -1
  161. package/src/gateways/ws/mcp-topic-handlers.js +167 -0
  162. package/src/gateways/ws/ws-agent-handler.js +20 -12
  163. package/src/harness/jsonl-session-store.js +279 -37
  164. package/src/harness/mcp-client.js +701 -91
  165. package/src/harness/session-index.js +15 -4
  166. package/src/lib/agent-network.js +166 -29
  167. package/src/lib/agent-router.js +62 -6
  168. package/src/lib/agent-sandbox.js +7 -1
  169. package/src/lib/agent-worktree.js +8 -1
  170. package/src/lib/auto-mode-safety-classifier.js +3 -17
  171. package/src/lib/background-agent-keeper-protocol.js +26 -6
  172. package/src/lib/background-agent-supervisor.js +17 -1
  173. package/src/lib/browser-evidence.js +1405 -0
  174. package/src/lib/chrome-connector.js +465 -79
  175. package/src/lib/claude-code-bridge.js +159 -54
  176. package/src/lib/claude-project-auto-memory.js +481 -0
  177. package/src/lib/claude-project-storage-layout.js +104 -0
  178. package/src/lib/cloud/cloud-client.js +40 -0
  179. package/src/lib/cowork-workflow.js +69 -6
  180. package/src/lib/execution-location-local-supervisor.mjs +226 -0
  181. package/src/lib/execution-location-runner-lifecycle.js +991 -0
  182. package/src/lib/execution-location-target-preflight.js +333 -0
  183. package/src/lib/execution-location-target.js +783 -13
  184. package/src/lib/external-agent-adapters.js +269 -0
  185. package/src/lib/file-lines.js +6 -1
  186. package/src/lib/gateway-client-resilience.js +571 -0
  187. package/src/lib/gitlab-mr-worktree.js +176 -0
  188. package/src/lib/hooks-v2-producers.js +119 -15
  189. package/src/lib/hooks-v2-workspace-context.js +44 -1
  190. package/src/lib/host-resource-budget.js +295 -0
  191. package/src/lib/ide-context.js +15 -2
  192. package/src/lib/ipfs-storage.js +127 -25
  193. package/src/lib/llm-config-defaults.js +43 -0
  194. package/src/lib/mcp-lifecycle-authority.js +887 -0
  195. package/src/lib/mcp-oauth.js +101 -20
  196. package/src/lib/mcp-tls.js +103 -3
  197. package/src/lib/orchestrator.js +47 -0
  198. package/src/lib/paths.js +260 -32
  199. package/src/lib/permission-request.js +48 -0
  200. package/src/lib/plugin-runtime/bin.js +3 -1
  201. package/src/lib/plugin-runtime/hooks.js +3 -1
  202. package/src/lib/plugin-runtime/install.js +117 -1
  203. package/src/lib/plugin-runtime/lsp.js +4 -4
  204. package/src/lib/plugin-runtime/marketplace-archive-source.js +40 -5
  205. package/src/lib/plugin-runtime/marketplace-catalog.js +13 -2
  206. package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
  207. package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
  208. package/src/lib/plugin-runtime/marketplace-source-adapter.js +33 -8
  209. package/src/lib/plugin-runtime/mcp.js +3 -1
  210. package/src/lib/plugin-runtime/monitors.js +3 -1
  211. package/src/lib/plugin-runtime/remote-source.js +151 -6
  212. package/src/lib/plugin-runtime/settings.js +3 -1
  213. package/src/lib/plugin-runtime/trust.js +274 -13
  214. package/src/lib/process-execution-broker/credential-agent.js +210 -41
  215. package/src/lib/process-execution-broker/index.js +15 -1
  216. package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
  217. package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
  218. package/src/lib/project-mcp-trust.js +165 -10
  219. package/src/lib/resume-session.js +9 -6
  220. package/src/lib/session-core-singletons.js +26 -11
  221. package/src/lib/session-host-lease.js +52 -16
  222. package/src/lib/session-lifecycle-scope.js +153 -0
  223. package/src/lib/session-message-fabric.js +168 -21
  224. package/src/lib/session-projection.js +244 -4
  225. package/src/lib/session-store-guard.js +3 -1
  226. package/src/lib/session-workbench-store.js +466 -0
  227. package/src/lib/shell-approval.js +7 -5
  228. package/src/lib/spellcheck.js +211 -0
  229. package/src/lib/sub-agent-context.js +9 -9
  230. package/src/lib/sync-cli-db.js +485 -129
  231. package/src/lib/sync-credentials.js +31 -20
  232. package/src/lib/web-fetch.js +112 -40
  233. package/src/lib/web-search.js +127 -61
  234. package/src/lib/workflow-engine.js +42 -11
  235. package/src/lib/workspace-trust.js +793 -0
  236. package/src/repl/agent-repl.js +124 -5
  237. package/src/repl/permission-prompt.js +10 -12
  238. package/src/runtime/agent-core.js +311 -18
  239. package/src/runtime/agent-runtime.js +12 -1
  240. package/src/runtime/bootstrap.js +37 -13
  241. package/src/runtime/coding-agent-contract-shared.cjs +11 -4
  242. package/src/runtime/headless-runner.js +234 -36
  243. package/src/runtime/headless-stream.js +181 -6
  244. package/src/runtime/mcp-config.js +298 -8
  245. package/src/runtime/policies/agent-policy.js +8 -0
  246. package/src/runtime/status-diagnostics-lite.js +9 -1
  247. package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +0 -1
  248. package/src/assets/web-panel/assets/McpTools-DFaIhOfu.js +0 -7
  249. package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +0 -1
  250. package/src/assets/web-panel/assets/index-BETiL0a3.js +0 -1
  251. package/src/assets/web-panel/assets/index-BhAVHuW8.js +0 -1
@@ -20,7 +20,8 @@
20
20
  import { existsSync, readdirSync, statSync } from "node:fs";
21
21
  import { join, basename } from "node:path";
22
22
  import { createRequire } from "node:module";
23
- import { getHomeDir } from "../lib/paths.js";
23
+ import { ensureClaudeProjectStorageTree, getHomeDir } from "../lib/paths.js";
24
+ import { resolveClaudeProjectStorageDir } from "../lib/claude-project-storage-layout.js";
24
25
  import { ensurePrivateDirectory, ensurePrivateFile } from "../lib/secure-fs.js";
25
26
  import { readVerifiedProjection } from "./jsonl-session-store.js";
26
27
 
@@ -39,12 +40,22 @@ export const _deps = {
39
40
  };
40
41
 
41
42
  function sessionsDir() {
42
- return join(getHomeDir(), "sessions");
43
+ const homeDir = getHomeDir();
44
+ return resolveClaudeProjectStorageDir(homeDir) || join(homeDir, "sessions");
43
45
  }
44
46
 
45
47
  function indexPath() {
46
- const dir = getHomeDir();
47
- ensurePrivateDirectory(dir);
48
+ const homeDir = getHomeDir();
49
+ const projectDir = resolveClaudeProjectStorageDir(homeDir);
50
+ if (projectDir) {
51
+ ensureClaudeProjectStorageTree(homeDir, projectDir);
52
+ }
53
+ const dir = projectDir || homeDir;
54
+ if (!projectDir) ensurePrivateDirectory(dir);
55
+ // Keep the long-standing global cache path for legacy sessions. A
56
+ // Claude-compatible project layout must not make one project's index scan
57
+ // another project's transcripts, so its derived index lives beside those
58
+ // project-local JSONL files.
48
59
  return join(dir, "session-index.db");
49
60
  }
50
61
 
@@ -14,6 +14,38 @@
14
14
  */
15
15
 
16
16
  import crypto from "crypto";
17
+ import { createSecretStore } from "./secret-store.js";
18
+
19
+ let configuredAgentNetworkSecretStore = null;
20
+
21
+ export function setAgentNetworkSecretStore(secretStore) {
22
+ if (
23
+ !secretStore ||
24
+ typeof secretStore.set !== "function" ||
25
+ typeof secretStore.get !== "function" ||
26
+ typeof secretStore.delete !== "function"
27
+ ) {
28
+ throw new TypeError("Agent Network requires a SecretStore");
29
+ }
30
+ configuredAgentNetworkSecretStore = secretStore;
31
+ }
32
+
33
+ function getAgentNetworkSecretStore() {
34
+ if (!configuredAgentNetworkSecretStore) {
35
+ configuredAgentNetworkSecretStore = createSecretStore({
36
+ service: "chainlesschain-agent-network",
37
+ });
38
+ }
39
+ return configuredAgentNetworkSecretStore;
40
+ }
41
+
42
+ function didPrivateKeyRef(did) {
43
+ return `agent-network/did/${crypto.createHash("sha256").update(did).digest("hex")}`;
44
+ }
45
+
46
+ function authTokenHash(token) {
47
+ return crypto.createHash("sha256").update(String(token)).digest("hex");
48
+ }
17
49
 
18
50
  /* ── Constants ───────────────────────────────────────────── */
19
51
 
@@ -77,7 +109,8 @@ export function ensureAgentNetworkTables(db) {
77
109
  CREATE TABLE IF NOT EXISTS agent_dids (
78
110
  did TEXT PRIMARY KEY,
79
111
  public_key TEXT NOT NULL,
80
- private_key TEXT NOT NULL,
112
+ private_key TEXT NOT NULL DEFAULT '',
113
+ private_key_ref TEXT NOT NULL,
81
114
  did_document TEXT NOT NULL,
82
115
  metadata TEXT,
83
116
  status TEXT NOT NULL,
@@ -124,7 +157,8 @@ export function ensureAgentNetworkTables(db) {
124
157
  CREATE TABLE IF NOT EXISTS agent_auth_sessions (
125
158
  session_id TEXT PRIMARY KEY,
126
159
  agent_did TEXT NOT NULL,
127
- token TEXT NOT NULL,
160
+ token TEXT NOT NULL DEFAULT '',
161
+ token_hash TEXT NOT NULL,
128
162
  challenge TEXT NOT NULL,
129
163
  status TEXT NOT NULL,
130
164
  expires_at INTEGER NOT NULL,
@@ -161,6 +195,81 @@ export function ensureAgentNetworkTables(db) {
161
195
  completed_at INTEGER
162
196
  )
163
197
  `);
198
+
199
+ for (const [table, column, definition] of [
200
+ ["agent_dids", "private_key_ref", "TEXT"],
201
+ ["agent_auth_sessions", "token_hash", "TEXT"],
202
+ ]) {
203
+ const columns = db.prepare(`PRAGMA table_info(${table})`).all();
204
+ if (columns.length > 0 && !columns.some((entry) => entry.name === column)) {
205
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
206
+ }
207
+ }
208
+
209
+ migrateAgentNetworkSecrets(db);
210
+ }
211
+
212
+ export function migrateAgentNetworkSecrets(db, { dryRun = false } = {}) {
213
+ db.exec("PRAGMA secure_delete = ON");
214
+ const didRows = db
215
+ .prepare("SELECT did, private_key, private_key_ref FROM agent_dids")
216
+ .all()
217
+ .filter((row) => row.private_key && !row.private_key_ref);
218
+ const authRows = db
219
+ .prepare("SELECT session_id, token, token_hash FROM agent_auth_sessions")
220
+ .all()
221
+ .filter((row) => row.token && !row.token_hash);
222
+
223
+ if (dryRun) {
224
+ return {
225
+ pendingPrivateKeys: didRows.length,
226
+ pendingTokens: authRows.length,
227
+ migratedPrivateKeys: 0,
228
+ migratedTokens: 0,
229
+ dryRun: true,
230
+ };
231
+ }
232
+
233
+ if (
234
+ (didRows.length > 0 || authRows.length > 0) &&
235
+ typeof db.transaction !== "function"
236
+ ) {
237
+ throw new Error(
238
+ "Agent Network secret migration requires transactional database support",
239
+ );
240
+ }
241
+
242
+ const secretStore = didRows.length > 0 ? getAgentNetworkSecretStore() : null;
243
+ const stagedKeyRefs = [];
244
+ try {
245
+ for (const row of didRows) {
246
+ const keyRef = didPrivateKeyRef(row.did);
247
+ secretStore.set(keyRef, row.private_key);
248
+ stagedKeyRefs.push(keyRef);
249
+ }
250
+
251
+ const applyMigration = db.transaction(() => {
252
+ for (const row of didRows) {
253
+ const keyRef = didPrivateKeyRef(row.did);
254
+ db.prepare(
255
+ "UPDATE agent_dids SET private_key = ?, private_key_ref = ? WHERE did = ?",
256
+ ).run("", keyRef, row.did);
257
+ }
258
+ for (const row of authRows) {
259
+ db.prepare(
260
+ "UPDATE agent_auth_sessions SET token = ?, token_hash = ? WHERE session_id = ?",
261
+ ).run("", authTokenHash(row.token), row.session_id);
262
+ }
263
+ });
264
+ applyMigration();
265
+ } catch (error) {
266
+ for (const keyRef of stagedKeyRefs) secretStore.delete(keyRef);
267
+ throw error;
268
+ }
269
+ return {
270
+ migratedPrivateKeys: didRows.length,
271
+ migratedTokens: authRows.length,
272
+ };
164
273
  }
165
274
 
166
275
  /* ── Helpers ─────────────────────────────────────────────── */
@@ -258,6 +367,7 @@ export function createAgentDID(db, { displayName, metadata = {} } = {}) {
258
367
  .slice(0, 32);
259
368
  const did = `did:chainless:${idHash}`;
260
369
  const now = _now();
370
+ const privateKeyRef = didPrivateKeyRef(did);
261
371
 
262
372
  const didDocument = {
263
373
  "@context": ["https://www.w3.org/ns/did/v1"],
@@ -284,20 +394,28 @@ export function createAgentDID(db, { displayName, metadata = {} } = {}) {
284
394
  : [],
285
395
  };
286
396
 
287
- db.prepare(
288
- `INSERT INTO agent_dids
289
- (did, public_key, private_key, did_document, metadata, status, created_at, updated_at)
290
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
291
- ).run(
292
- did,
293
- publicKey,
294
- privateKey,
295
- JSON.stringify(didDocument),
296
- _json({ displayName, ...metadata }),
297
- DID_STATUS.ACTIVE,
298
- now,
299
- now,
300
- );
397
+ const secretStore = getAgentNetworkSecretStore();
398
+ secretStore.set(privateKeyRef, privateKey);
399
+ try {
400
+ db.prepare(
401
+ `INSERT INTO agent_dids
402
+ (did, public_key, private_key, private_key_ref, did_document, metadata, status, created_at, updated_at)
403
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
404
+ ).run(
405
+ did,
406
+ publicKey,
407
+ "",
408
+ privateKeyRef,
409
+ JSON.stringify(didDocument),
410
+ _json({ displayName, ...metadata }),
411
+ DID_STATUS.ACTIVE,
412
+ now,
413
+ now,
414
+ );
415
+ } catch (error) {
416
+ secretStore.delete(privateKeyRef);
417
+ throw error;
418
+ }
301
419
 
302
420
  return { did, publicKey, didDocument };
303
421
  }
@@ -351,12 +469,19 @@ export function deactivateAgentDID(db, did) {
351
469
 
352
470
  export function signWithAgent(db, did, data) {
353
471
  const row = db
354
- .prepare(`SELECT private_key, status FROM agent_dids WHERE did = ?`)
472
+ .prepare(`SELECT private_key_ref, status FROM agent_dids WHERE did = ?`)
355
473
  .get(did);
356
474
  if (!row) throw new Error(`Unknown agent DID: ${did}`);
357
475
  if (row.status !== DID_STATUS.ACTIVE)
358
476
  throw new Error(`Agent DID is not active: ${did}`);
359
- return _signEd25519(row.private_key, data);
477
+ if (!row.private_key_ref) {
478
+ throw new Error(`Agent DID private key reference is missing: ${did}`);
479
+ }
480
+ const privateKey = getAgentNetworkSecretStore().get(row.private_key_ref);
481
+ if (!privateKey) {
482
+ throw new Error(`Agent DID private key is unavailable: ${did}`);
483
+ }
484
+ return _signEd25519(privateKey, data);
360
485
  }
361
486
 
362
487
  export function verifyWithAgent(db, did, data, signature) {
@@ -557,14 +682,13 @@ export function startAuth(db, did) {
557
682
  throw new Error(`Agent DID not active: ${did}`);
558
683
  const sessionId = _uuid();
559
684
  const challenge = _hex(crypto.randomBytes(32));
560
- const token = _hex(crypto.randomBytes(24));
561
685
  const now = _now();
562
686
  const expires = now + SESSION_TTL_MS;
563
687
  db.prepare(
564
688
  `INSERT INTO agent_auth_sessions
565
- (session_id, agent_did, token, challenge, status, expires_at, created_at)
566
- VALUES (?, ?, ?, ?, ?, ?, ?)`,
567
- ).run(sessionId, did, token, challenge, AUTH_STATUS.PENDING, expires, now);
689
+ (session_id, agent_did, token, token_hash, challenge, status, expires_at, created_at)
690
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
691
+ ).run(sessionId, did, "", "", challenge, AUTH_STATUS.PENDING, expires, now);
568
692
  return { sessionId, challenge, expiresAt: expires };
569
693
  }
570
694
 
@@ -584,21 +708,23 @@ export function completeAuth(db, sessionId, signatureHex) {
584
708
  }
585
709
  const ok = verifyWithAgent(db, row.agent_did, row.challenge, signatureHex);
586
710
  if (!ok) throw new Error(`Signature verification failed`);
711
+ const token = _hex(crypto.randomBytes(24));
587
712
  db.prepare(
588
- `UPDATE agent_auth_sessions SET status = ? WHERE session_id = ?`,
589
- ).run(AUTH_STATUS.ACTIVE, sessionId);
713
+ `UPDATE agent_auth_sessions SET status = ?, token = ?, token_hash = ? WHERE session_id = ?`,
714
+ ).run(AUTH_STATUS.ACTIVE, "", authTokenHash(token), sessionId);
590
715
  return {
591
716
  sessionId,
592
- token: row.token,
717
+ token,
593
718
  agentDid: row.agent_did,
594
719
  expiresAt: row.expires_at,
595
720
  };
596
721
  }
597
722
 
598
723
  export function validateSession(db, token) {
724
+ if (typeof token !== "string" || token.length === 0) return null;
599
725
  const row = db
600
- .prepare(`SELECT * FROM agent_auth_sessions WHERE token = ?`)
601
- .get(token);
726
+ .prepare(`SELECT * FROM agent_auth_sessions WHERE token_hash = ?`)
727
+ .get(authTokenHash(token));
602
728
  if (!row) return null;
603
729
  const now = _now();
604
730
  if (row.status !== AUTH_STATUS.ACTIVE) return null;
@@ -659,13 +785,24 @@ export function issueCredential(
659
785
  if (!issuerDid) throw new Error("issuerDid is required");
660
786
  if (!subjectDid) throw new Error("subjectDid is required");
661
787
  const issuer = db
662
- .prepare(`SELECT private_key, status FROM agent_dids WHERE did = ?`)
788
+ .prepare(`SELECT private_key_ref, status FROM agent_dids WHERE did = ?`)
663
789
  .get(issuerDid);
664
790
  if (!issuer) throw new Error(`Unknown issuer DID: ${issuerDid}`);
665
791
  if (issuer.status !== DID_STATUS.ACTIVE)
666
792
  throw new Error(`Issuer DID not active: ${issuerDid}`);
667
793
  const subject = resolveAgentDID(db, subjectDid);
668
794
  if (!subject) throw new Error(`Unknown subject DID: ${subjectDid}`);
795
+ if (!issuer.private_key_ref) {
796
+ throw new Error(
797
+ `Issuer DID private key reference is missing: ${issuerDid}`,
798
+ );
799
+ }
800
+ const issuerPrivateKey = getAgentNetworkSecretStore().get(
801
+ issuer.private_key_ref,
802
+ );
803
+ if (!issuerPrivateKey) {
804
+ throw new Error(`Issuer DID private key is unavailable: ${issuerDid}`);
805
+ }
669
806
  const now = _now();
670
807
  const id = `vc:${_uuid()}`;
671
808
  const payload = {
@@ -677,7 +814,7 @@ export function issueCredential(
677
814
  issuedAt: now,
678
815
  expiresAt,
679
816
  };
680
- const proof = _credentialProof(issuer.private_key, payload);
817
+ const proof = _credentialProof(issuerPrivateKey, payload);
681
818
  db.prepare(
682
819
  `INSERT INTO agent_credentials
683
820
  (id, issuer_did, subject_did, type, claims, proof, status, issued_at, expires_at)
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Routes coding subtasks across multiple agent backends in parallel:
5
5
  * - claude (Claude Code CLI — best for complex reasoning)
6
- * - codex (GitHub Copilot CLI — good for repo context)
6
+ * - codex (OpenAI Codex CLI — good for repo context)
7
7
  * - gemini (Google Gemini via ChainlessChain LLM provider)
8
8
  * - openai (GPT-4o via ChainlessChain LLM provider)
9
9
  * - ollama (Local LLM — offline / private)
@@ -32,6 +32,12 @@ import {
32
32
  detectCodex,
33
33
  } from "./claude-code-bridge.js";
34
34
  import { createChatFn } from "./cowork-adapter.js";
35
+ import runtimeClaimsContract from "@chainlesschain/session-core/runtime-claims";
36
+
37
+ const { RUNTIME_MODE, createRuntimeClaims } = runtimeClaimsContract;
38
+ const SIMULATED_API_CLAIMS = createRuntimeClaims({
39
+ mode: RUNTIME_MODE.SIMULATED,
40
+ });
35
41
 
36
42
  // ─── Backend type constants ───────────────────────────────────────
37
43
  export const BACKEND_TYPE = {
@@ -70,6 +76,37 @@ const TYPE_KEYWORDS = {
70
76
  research: ["research", "investigate", "explore", "compare"],
71
77
  };
72
78
 
79
+ export const AGENT_ROUTER_ERROR = Object.freeze({
80
+ WRITE_ISOLATION_REQUIRED: "AGENT_ROUTER_WRITE_ISOLATION_REQUIRED",
81
+ });
82
+
83
+ function normalizedScopes(task) {
84
+ if (!Array.isArray(task?.scopePaths) || task.scopePaths.length === 0) {
85
+ return null;
86
+ }
87
+ return task.scopePaths.map(
88
+ (scope) => String(scope).replace(/\\/g, "/").replace(/\/+$/u, "") + "/",
89
+ );
90
+ }
91
+
92
+ export function assignmentsHaveDisjointWrites(assignments) {
93
+ if (assignments.every(({ task }) => task?.effects === "read-only")) {
94
+ return true;
95
+ }
96
+ const scopes = assignments.map(({ task }) => normalizedScopes(task));
97
+ if (scopes.some((scope) => scope === null)) return false;
98
+ for (let i = 0; i < scopes.length; i += 1) {
99
+ for (let j = i + 1; j < scopes.length; j += 1) {
100
+ for (const left of scopes[i]) {
101
+ for (const right of scopes[j]) {
102
+ if (left.startsWith(right) || right.startsWith(left)) return false;
103
+ }
104
+ }
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+
73
110
  function detectTaskType(description) {
74
111
  const lower = description.toLowerCase();
75
112
  for (const [type, keywords] of Object.entries(TYPE_KEYWORDS)) {
@@ -116,20 +153,26 @@ async function executeViaAPI(task, options) {
116
153
  ]);
117
154
 
118
155
  return {
119
- success: true,
156
+ success: false,
157
+ status: "simulated",
120
158
  output,
121
159
  exitCode: 0,
122
160
  duration: Date.now() - startTime,
123
161
  agentId: `api-${provider}`,
162
+ runtimeClaims: SIMULATED_API_CLAIMS,
163
+ terminalEvidence: [],
124
164
  };
125
165
  } catch (err) {
126
166
  return {
127
167
  success: false,
168
+ status: "failed",
128
169
  output: "",
129
170
  exitCode: -1,
130
171
  duration: Date.now() - startTime,
131
172
  agentId: `api-${provider}`,
132
173
  error: err.message,
174
+ runtimeClaims: SIMULATED_API_CLAIMS,
175
+ terminalEvidence: [],
133
176
  };
134
177
  }
135
178
  }
@@ -257,6 +300,13 @@ export class AgentRouter extends EventEmitter {
257
300
 
258
301
  /** Parallel-all: run every task on ALL backends; return best result per task. */
259
302
  async _dispatchParallelAll(subtasks, { cwd }) {
303
+ if (this._backends.length > 1) {
304
+ const error = new Error(
305
+ "parallel-all requires per-attempt worktrees and accepted-winner merge",
306
+ );
307
+ error.code = AGENT_ROUTER_ERROR.WRITE_ISOLATION_REQUIRED;
308
+ throw error;
309
+ }
260
310
  const results = [];
261
311
  for (const task of subtasks) {
262
312
  const allResults = await Promise.all(
@@ -276,10 +326,15 @@ export class AgentRouter extends EventEmitter {
276
326
 
277
327
  async _runAssignments(assignments, { cwd }) {
278
328
  const results = new Array(assignments.length);
279
-
280
- // Process in parallel batches
281
- for (let i = 0; i < assignments.length; i += this.maxParallel) {
282
- const batch = assignments.slice(i, i + this.maxParallel);
329
+ const concurrency = assignmentsHaveDisjointWrites(assignments)
330
+ ? this.maxParallel
331
+ : 1;
332
+
333
+ // Shared writable cwd tasks are serialized unless their declared write
334
+ // scopes are statically disjoint. Candidate fan-out is rejected above
335
+ // until it has per-attempt worktrees and winner-only merge semantics.
336
+ for (let i = 0; i < assignments.length; i += concurrency) {
337
+ const batch = assignments.slice(i, i + concurrency);
283
338
  const batchResults = await Promise.all(
284
339
  batch.map(({ task, backend }) =>
285
340
  this._runSingleTask(task, backend, { cwd }),
@@ -332,6 +387,7 @@ export class AgentRouter extends EventEmitter {
332
387
  maxParallel: 1,
333
388
  cliCommand: type === BACKEND_TYPE.CODEX ? "codex" : "claude",
334
389
  model: cfg.model || null,
390
+ sandbox: cfg.sandbox || null,
335
391
  });
336
392
  pool.on("agent:output", (ev) => this.emit("agent:output", ev));
337
393
  return {
@@ -259,7 +259,13 @@ export function normalizeAgentSandbox(value, options = {}) {
259
259
  */
260
260
  export function normalizeAgentSandboxMode(mode, value, options = {}) {
261
261
  if (mode == null || mode === "") {
262
- return normalizeAgentSandbox(value, options);
262
+ // Public agent execution defaults to a real, fail-closed workspace
263
+ // sandbox. Bare-host execution remains available only through the
264
+ // explicit `off` mode below, where managed policy can prohibit it.
265
+ return normalizeAgentSandboxMode("workspace-write", value || true, {
266
+ ...options,
267
+ network: false,
268
+ });
263
269
  }
264
270
  if (!AGENT_SANDBOX_MODES.includes(mode)) {
265
271
  const error = new Error(
@@ -244,7 +244,14 @@ export function finishAgentWorktree(info, { deps = _deps } = {}) {
244
244
  let headSha = null;
245
245
  let readable = false;
246
246
  try {
247
- dirty = git(["status", "--porcelain"], info.path, deps).trim().length > 0;
247
+ // Do not inherit status.showUntrackedFiles=no from repository/user config:
248
+ // an untracked agent output is still work that finalize must preserve.
249
+ dirty =
250
+ git(
251
+ ["status", "--porcelain=v1", "--untracked-files=all"],
252
+ info.path,
253
+ deps,
254
+ ).trim().length > 0;
248
255
  headSha = git(["rev-parse", "HEAD"], info.path, deps).trim();
249
256
  readable = true;
250
257
  } catch {
@@ -20,6 +20,7 @@ import {
20
20
  isSecretEnvName,
21
21
  } from "./credential-guard.js";
22
22
  import { containsSecret } from "./secret-scan.js";
23
+ import { normalizePermissionRequest } from "./permission-request.js";
23
24
 
24
25
  const require_ = createRequire(import.meta.url);
25
26
  const shellPolicy = require_("../runtime/coding-agent-shell-policy.cjs");
@@ -459,21 +460,6 @@ function canonicalShellKeyword(token) {
459
460
  .replace(/\\(.)/g, "$1");
460
461
  }
461
462
 
462
- function inputCommand(input) {
463
- const command = input?.args?.command;
464
- if (typeof command === "string") return command;
465
- const argv = input?.args?.argv;
466
- return Array.isArray(argv)
467
- ? argv
468
- .map((value) => {
469
- const token = String(value);
470
- if (token && !/[\s|;&"'\\]/.test(token)) return token;
471
- return `"${token.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
472
- })
473
- .join(" ")
474
- : "";
475
- }
476
-
477
463
  function workspaceRoots(context = {}) {
478
464
  const roots = [];
479
465
  if (Array.isArray(context.workspaceRoots)) {
@@ -1817,7 +1803,7 @@ export function classifyAutoModeSafety(input = {}) {
1817
1803
  const args = input.args && typeof input.args === "object" ? input.args : {};
1818
1804
  const context =
1819
1805
  input.context && typeof input.context === "object" ? input.context : {};
1820
- const command = inputCommand({ args });
1806
+ const command = normalizePermissionRequest({ tool, args }).command;
1821
1807
  const segments = collectCommandSegments(command);
1822
1808
  const argsText = stableSerialize(args);
1823
1809
  const baseRiskLevel = normalizeRisk(input.baseRiskLevel, "medium");
@@ -2000,7 +1986,7 @@ export function evaluateAutoModeSafety(input = {}, opts = {}) {
2000
1986
  : classifyAutoModeSafety;
2001
1987
  const classification = classifier(input);
2002
1988
  const tool = String(input?.tool || "unknown").toLowerCase();
2003
- const command = inputCommand(input);
1989
+ const command = normalizePermissionRequest(input).command;
2004
1990
  let policy = null;
2005
1991
  if (tool === "run_shell") {
2006
1992
  const result = evaluateShellCommandPolicy(command, {
@@ -257,12 +257,16 @@ export function prepareBackgroundAgentLocalPipePath(
257
257
  { platform = process.platform } = {},
258
258
  ) {
259
259
  if (platform === "win32") return pipePath;
260
- const directory = fallbackLocalPipeDirectory(pipePath);
261
- if (!directory) return pipePath;
262
- try {
263
- mkdirSync(directory, { mode: 0o700 });
264
- } catch (error) {
265
- if (error?.code !== "EEXIST") throw error;
260
+ const normalizedPipePath = posix.resolve(
261
+ String(pipePath || "").replaceAll("\\", "/"),
262
+ );
263
+ const directory = posix.dirname(normalizedPipePath);
264
+ if (fallbackLocalPipeDirectory(pipePath)) {
265
+ try {
266
+ mkdirSync(directory, { mode: 0o700 });
267
+ } catch (error) {
268
+ if (error?.code !== "EEXIST") throw error;
269
+ }
266
270
  }
267
271
  const stat = lstatSync(directory);
268
272
  const uid = typeof process.getuid === "function" ? process.getuid() : null;
@@ -274,6 +278,22 @@ export function prepareBackgroundAgentLocalPipePath(
274
278
  ) {
275
279
  throw new Error("background agent socket directory is not private");
276
280
  }
281
+
282
+ let socketStat = null;
283
+ try {
284
+ socketStat = lstatSync(normalizedPipePath);
285
+ } catch (error) {
286
+ if (error?.code !== "ENOENT") throw error;
287
+ }
288
+ if (socketStat) {
289
+ if (
290
+ socketStat.isSymbolicLink() ||
291
+ !socketStat.isSocket() ||
292
+ (uid !== null && socketStat.uid !== uid)
293
+ ) {
294
+ throw new Error("background agent socket path is not an owned socket");
295
+ }
296
+ }
277
297
  return pipePath;
278
298
  }
279
299
 
@@ -1,6 +1,8 @@
1
1
  import {
2
+ chmodSync,
2
3
  closeSync,
3
4
  existsSync,
5
+ lstatSync,
4
6
  mkdirSync,
5
7
  openSync,
6
8
  readFileSync,
@@ -651,7 +653,21 @@ export function backgroundAgentsDir() {
651
653
  const dir =
652
654
  process.env.CC_BACKGROUND_AGENTS_DIR ||
653
655
  join(getHomeDir(), "background-agents");
654
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
656
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 });
657
+ if (process.platform !== "win32") {
658
+ const stat = lstatSync(dir);
659
+ const uid = typeof process.getuid === "function" ? process.getuid() : null;
660
+ if (
661
+ !stat.isDirectory() ||
662
+ stat.isSymbolicLink() ||
663
+ (uid !== null && stat.uid !== uid)
664
+ ) {
665
+ throw new Error(
666
+ "background agent state directory is not owner-controlled",
667
+ );
668
+ }
669
+ chmodSync(dir, 0o700);
670
+ }
655
671
  return dir;
656
672
  }
657
673