chainlesschain 0.162.148 → 0.162.149

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 (231) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DwpCCp64.js → AIOps-BJif14yR.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-CXek6gJY.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-BgQhdAJi.js} +2 -2
  7. package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-DTYl5NtR.js} +3 -3
  8. package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-BzATQAeR.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-BzdPEQhL.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-BM0KVh8E.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-D7fHXHkz.js} +4 -4
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-Wm34RR-b.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CAiSQ9vO.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-Df40CrEe.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-DIT2fNFU.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-CSTIbW2k.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-DtqXZZUi.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-CUtzw6o7.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-CezmlnmU.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-P4BITarg.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-BRRiYwvq.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-L5ijB9i4.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard-CFxro4ob.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BmAFCQ71.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-DJBCEuon.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-z4oLq6eT.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-DsVCpHMF.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DP3bP5th.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-BAXP2Gc6.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-I3g_bAw9.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-jHS5-ioS.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-CPL7sfx9.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-Jf236h4C.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-Cm2tcSKg.js} +2 -2
  35. package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-CZK82rhi.js} +1 -1
  36. package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-CZCeji7a.js} +4 -4
  37. package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-3l2KVS9k.js} +2 -2
  38. package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-VYdpoLh6.js} +1 -1
  39. package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-CiB9cmm1.js} +1 -1
  40. package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-wCFZbBuL.js} +2 -2
  41. package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-1a3THIyG.js} +4 -4
  42. package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-DMzLB2hG.js} +3 -3
  43. package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-D9wZbf6l.js} +1 -1
  44. package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-hrFe2ZM-.js} +3 -3
  45. package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-CHGX5Jwm.js} +1 -1
  46. package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +1 -0
  47. package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-By7FkhtY.js} +4 -4
  48. package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow--khGSzJn.js} +1 -1
  49. package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-CAG9dH35.js} +2 -2
  50. package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-B3SQZmK9.js} +3 -3
  51. package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-D35ec6JA.js} +4 -4
  52. package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CxBF7hW_.js} +2 -2
  53. package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-s6EtOO1s.js} +1 -1
  54. package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-BbJYmWmO.js} +1 -1
  55. package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-VGQq1jMT.js} +2 -2
  56. package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-B1ew3Teh.js} +2 -2
  57. package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +1 -0
  58. package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-mrO47FIK.js} +1 -1
  59. package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-IJF2mHyw.js} +1 -1
  60. package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CU0wN_Z0.js} +1 -1
  61. package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-DhN37R6G.js} +1 -1
  62. package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-D_xOX_hu.js} +2 -2
  63. package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-D_Ssv7uH.js} +1 -1
  64. package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-Kx5dKxX7.js} +1 -1
  65. package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-BlGwqZkY.js} +2 -2
  66. package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-hLFQzxpb.js} +1 -1
  67. package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DMlvsVt4.js} +3 -3
  68. package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-Bd0Qsj2m.js} +2 -2
  69. package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-DFclq9X3.js} +1 -1
  70. package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-BNtln2qY.js} +1 -1
  71. package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-Dch5H19G.js} +1 -1
  72. package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-2UfQcU1g.js} +1 -1
  73. package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-CD9YQr4i.js} +2 -2
  74. package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-BNu-7MzI.js} +1 -1
  75. package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-D1n9CaIR.js} +1 -1
  76. package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-DenL3iBW.js} +1 -1
  77. package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +3 -0
  78. package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-D87IfukO.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BkiZc8E3.js} +1 -1
  80. package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-BNRSytGN.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-Bwbd4X2m.js} +1 -1
  82. package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-B8O2bs0o.js} +1 -1
  83. package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-C2fL8zmH.js} +1 -1
  84. package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-BORYDdE1.js} +4 -4
  85. package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-C0V5S2FM.js} +4 -4
  86. package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-2dR0fcHL.js} +1 -1
  87. package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-BmuAFAn8.js} +1 -1
  88. package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-CN3smMcK.js} +1 -1
  89. package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-DCnxb4kW.js} +1 -1
  90. package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-vlR43pHn.js} +1 -1
  91. package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +1 -0
  92. package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-D04tHYFd.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-0DnaZGkC.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-308gCGh7.js → index-430S68MN.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-B78xL3s2.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BTPEZTk1.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-BXRg8GFQ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-BasvsWDM.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-BeGDEXFs.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-BqhASEL4.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-BudvKQfG.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-C-6NO5il.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-C5Sxb1sE.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-CP9m9Ggr.js} +3 -3
  105. package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-CTOCnIQ7.js} +1 -1
  106. package/src/assets/web-panel/assets/index-Cg2ldRfU.js +1 -0
  107. package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-ClhAHDK3.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-CnXebZLL.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-CngCC8hC.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-Cr-A0FYJ.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-CsAsCPJ6.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-D28DeAAB.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-D5LZVZ0L.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-D65_XseV.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-D8vwp4qp.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-DDwLgQY9.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-DIpY0qM5.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-DTWg-18U.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-DTtRscUa.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-DYAtmqiv.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-D_n8_vfI.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CahryTX0.js → index-DbADHwhr.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-DbVsQBOH.js} +1 -1
  124. package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +1 -0
  125. package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-HhNjnCfe.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-ToUh2b1-.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DISWAYce.js → index-TslMTwNy.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-_FIkN3jd.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-hpvvtAZ3.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-jzR7Ujuw.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-ljuBiQW9.js} +1 -1
  132. package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-C3wUb4je.js} +1 -1
  133. package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D-jYFUNA.js} +1 -1
  134. package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-tqb8nwJ2.js} +1 -1
  135. package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DSOjMJMz.js} +1 -1
  136. package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-CJ7VimIW.js} +1 -1
  137. package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-qXiG1iT3.js} +1 -1
  138. package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-CkGBcy1Z.js} +1 -1
  139. package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-D3WvTlLO.js} +1 -1
  140. package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BEE2ftge.js} +1 -1
  141. package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-CsfBpxiG.js} +1 -1
  142. package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-xPrIiJPI.js} +1 -1
  143. package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-C5Yd-SCR.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-D_MDS8HI.js} +1 -1
  145. package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub-BqJh-usA.js} +1 -1
  146. package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-chm_p-gz.js} +1 -1
  147. package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-3-YDNz0Z.js} +1 -1
  148. package/src/assets/web-panel/index.html +1 -1
  149. package/src/assets/web-panel/remote-session-sw.js +43 -0
  150. package/src/command-manifest.json +22 -1
  151. package/src/commands/agent.js +44 -5
  152. package/src/commands/codeintel.js +252 -0
  153. package/src/commands/eval.js +248 -0
  154. package/src/commands/plugin.js +354 -0
  155. package/src/commands/team.js +456 -0
  156. package/src/gateways/ws/message-dispatcher.js +45 -2
  157. package/src/gateways/ws/remote-session-protocol.js +37 -0
  158. package/src/gateways/ws/ws-server.js +1 -1
  159. package/src/harness/prompt-compressor.js +27 -1
  160. package/src/harness/remote-command-ledger.js +158 -0
  161. package/src/harness/remote-session-push-apns.js +246 -0
  162. package/src/harness/remote-session-push-errors.js +15 -0
  163. package/src/harness/remote-session-push-fcm.js +9 -25
  164. package/src/harness/remote-session-push-huawei.js +174 -0
  165. package/src/harness/remote-session-push-oppo.js +171 -0
  166. package/src/harness/remote-session-push-senders.js +42 -0
  167. package/src/harness/remote-session-push-vivo.js +179 -0
  168. package/src/harness/remote-session-push-web.js +299 -0
  169. package/src/harness/remote-session-push-xiaomi.js +99 -0
  170. package/src/index.js +6 -0
  171. package/src/lib/agent-core.js +2 -0
  172. package/src/lib/agent-sandbox.js +161 -5
  173. package/src/lib/agent-team/task-lease.js +434 -0
  174. package/src/lib/agent-team/team-budget.js +165 -0
  175. package/src/lib/agent-team/team-mailbox.js +106 -0
  176. package/src/lib/agent-team/team-runner.js +266 -0
  177. package/src/lib/agent-team/team-worktree.js +204 -0
  178. package/src/lib/agents.js +18 -0
  179. package/src/lib/async-hook-supervisor.cjs +305 -0
  180. package/src/lib/eval/runner.js +163 -0
  181. package/src/lib/eval/tasks.js +456 -0
  182. package/src/lib/eval/trend.js +185 -0
  183. package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
  184. package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
  185. package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
  186. package/src/lib/lsp/__tests__/lsp-client.test.js +258 -0
  187. package/src/lib/lsp/__tests__/lsp-manager.test.js +264 -0
  188. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
  189. package/src/lib/lsp/code-intelligence.js +356 -0
  190. package/src/lib/lsp/jsonrpc-stream.js +139 -0
  191. package/src/lib/lsp/lsp-client.js +318 -0
  192. package/src/lib/lsp/lsp-manager.js +323 -0
  193. package/src/lib/lsp/lsp-server-registry.js +196 -0
  194. package/src/lib/plugin-monitor-supervisor.js +238 -0
  195. package/src/lib/plugin-runtime/agents.js +51 -0
  196. package/src/lib/plugin-runtime/bin.js +100 -0
  197. package/src/lib/plugin-runtime/hooks.js +100 -0
  198. package/src/lib/plugin-runtime/install.js +388 -0
  199. package/src/lib/plugin-runtime/lsp.js +75 -0
  200. package/src/lib/plugin-runtime/manifest.js +458 -0
  201. package/src/lib/plugin-runtime/mcp.js +89 -0
  202. package/src/lib/plugin-runtime/monitors.js +100 -0
  203. package/src/lib/plugin-runtime/policy.js +144 -0
  204. package/src/lib/plugin-runtime/reload.js +79 -0
  205. package/src/lib/plugin-runtime/scopes.js +197 -0
  206. package/src/lib/plugin-runtime/settings.js +119 -0
  207. package/src/lib/plugin-runtime/signature.js +107 -0
  208. package/src/lib/plugin-runtime/skills.js +43 -0
  209. package/src/lib/plugin-runtime/trust.js +140 -0
  210. package/src/lib/sandbox-egress-proxy.js +162 -0
  211. package/src/lib/sandbox-network-policy.js +134 -0
  212. package/src/lib/sandbox-v2.js +10 -4
  213. package/src/lib/settings-hook-events.cjs +78 -6
  214. package/src/lib/settings-hooks.cjs +29 -3
  215. package/src/lib/settings-loader.cjs +35 -1
  216. package/src/lib/skill-loader.js +18 -0
  217. package/src/lib/telemetry/span-recorder.js +237 -0
  218. package/src/repl/agent-repl.js +400 -4
  219. package/src/runtime/agent-core.js +546 -52
  220. package/src/runtime/coding-agent-contract-shared.cjs +82 -8
  221. package/src/runtime/coding-agent-policy.cjs +32 -7
  222. package/src/runtime/fallback-model.js +134 -7
  223. package/src/runtime/headless-runner.js +353 -108
  224. package/src/runtime/mcp-config.js +46 -0
  225. package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +0 -1
  226. package/src/assets/web-panel/assets/OrderTableRenderer-DIp8Xcbd.js +0 -1
  227. package/src/assets/web-panel/assets/Projects-Dpid9CDg.js +0 -1
  228. package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
  229. package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
  230. package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
  231. package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
@@ -177,6 +177,19 @@ export function registerAgentCommand(program) {
177
177
  "Run shell commands in an ephemeral Docker sandbox (network disabled by default)",
178
178
  )
179
179
  .option("--sandbox-network", "Allow network access inside --sandbox")
180
+ .option(
181
+ "--otlp <file>",
182
+ "Write the agent run's OpenTelemetry spans (model/tool/retry) as OTLP/JSON to <file>",
183
+ )
184
+ .option(
185
+ "--auto-rewake",
186
+ "When an async `asyncRewake` hook (e.g. a background test) fails at turn end, re-engage the agent to fix it (bounded by --max-rewakes)",
187
+ )
188
+ .option(
189
+ "--max-rewakes <n>",
190
+ "Max auto-rewake re-drives per run (default 1); implies --auto-rewake",
191
+ (v) => parseInt(v, 10),
192
+ )
180
193
  .option(
181
194
  "--bg, --background",
182
195
  "Start as a detached background agent and return its id immediately",
@@ -252,7 +265,7 @@ export function registerAgentCommand(program) {
252
265
  )
253
266
  .option(
254
267
  "--fallback-model <model>",
255
- "Backup model(s) to try in order when the primary fails (transient error or model-not-found). Repeatable or comma-separated; up to 3. Defaults to config llm.fallbackModels. claude-code parity.",
268
+ "Backup model(s) to try in order when the primary fails (transient error or model-not-found). Repeatable or comma-separated; up to 3. A `provider:model` entry (e.g. openai:gpt-4o) falls back cross-provider, using that provider's API key from its env var (skipped if unset — never reuses the primary key). Defaults to config llm.fallbackModels.",
256
269
  (val, prev) => (prev || []).concat([val]),
257
270
  )
258
271
  .option(
@@ -509,6 +522,7 @@ export function registerAgentCommand(program) {
509
522
  // over a settings model. Applied once here so every branch (headless +
510
523
  // interactive, which all read options.model) picks it up; env vars are
511
524
  // set on the process so the agent loop + child tools inherit them.
525
+ let settingsSandbox = null;
512
526
  try {
513
527
  const { loadSettingsConfig } =
514
528
  await import("../lib/settings-loader.cjs");
@@ -520,6 +534,7 @@ export function registerAgentCommand(program) {
520
534
  process.env[k] = v;
521
535
  }
522
536
  if (!options.model && sc.model) options.model = sc.model;
537
+ settingsSandbox = sc.sandbox || null;
523
538
  } catch {
524
539
  // settings overrides are best-effort 鈥?never block the run
525
540
  }
@@ -651,10 +666,22 @@ export function registerAgentCommand(program) {
651
666
  const fallbackChatFn = fallbackModels.length
652
667
  ? makeFallbackChatFn({
653
668
  fallbackModels,
654
- onFallback: ({ from, to, error }) =>
655
- process.stderr.write(
656
- `Note: model "${from}" failed (${error}); retrying with fallback model "${to}".\n`,
657
- ),
669
+ onFallback: ({
670
+ from,
671
+ to,
672
+ error,
673
+ skipped,
674
+ reason,
675
+ crossProvider,
676
+ }) =>
677
+ skipped
678
+ ? process.stderr.write(
679
+ `Note: fallback "${to}" skipped (${reason}).\n`,
680
+ )
681
+ : process.stderr.write(
682
+ `Note: model "${from}" failed (${error}); retrying with ` +
683
+ `${crossProvider ? "cross-provider " : ""}fallback "${to}".\n`,
684
+ ),
658
685
  })
659
686
  : undefined;
660
687
 
@@ -822,6 +849,7 @@ export function registerAgentCommand(program) {
822
849
  const agentSandbox = normalizeAgentSandbox(options.sandbox, {
823
850
  cwd: process.cwd(),
824
851
  network: options.sandboxNetwork === true,
852
+ settings: settingsSandbox,
825
853
  });
826
854
  // Resume requested onto a session with no headless (JSONL) transcript?
827
855
  // Warn instead of silently starting empty 鈥?headless resume rebuilds
@@ -864,6 +892,16 @@ export function registerAgentCommand(program) {
864
892
  additionalDirectories,
865
893
  sandbox: agentSandbox,
866
894
  autoCheckpoint,
895
+ // --otlp <file>: capture + export the run's OTel spans as OTLP/JSON.
896
+ otlp: options.otlp || null,
897
+ // --auto-rewake / --max-rewakes: bounded re-drive on async-hook failure.
898
+ // --max-rewakes implies --auto-rewake (a positive budget turns it on).
899
+ autoRewake:
900
+ options.autoRewake === true ||
901
+ (Number.isFinite(options.maxRewakes) && options.maxRewakes > 0),
902
+ maxRewakes: Number.isFinite(options.maxRewakes)
903
+ ? options.maxRewakes
904
+ : undefined,
867
905
  maxTurns,
868
906
  // commander maps --no-file-refs 鈫?options.fileRefs === false
869
907
  expandFileRefs: options.fileRefs !== false,
@@ -975,6 +1013,7 @@ export function registerAgentCommand(program) {
975
1013
  sandbox: normalizeAgentSandbox(options.sandbox, {
976
1014
  cwd: process.cwd(),
977
1015
  network: options.sandboxNetwork === true,
1016
+ settings: settingsSandbox,
978
1017
  }),
979
1018
  autoCheckpoint,
980
1019
  // --vim: start the REPL in vim-mode editing (also CC_VIM=1 or /vim).
@@ -0,0 +1,252 @@
1
+ /**
2
+ * cc code-intel — semantic code navigation via the Language Server Protocol.
3
+ *
4
+ * End-to-end surface for the LSP code-intelligence layer (Phase 2 of the CLI
5
+ * optimization plan). Proves the stack works without touching the contended
6
+ * agent-core; the agent `code_intelligence` tool is wired separately.
7
+ *
8
+ * cc code-intel status # which servers are installed
9
+ * cc code-intel def <file> <line> <col> # go to definition
10
+ * cc code-intel refs <file> <line> <col> # find references
11
+ * cc code-intel hover <file> <line> <col> # type / doc info
12
+ * cc code-intel symbols <file> # document symbols
13
+ * cc code-intel wsymbols <query> # workspace symbol search
14
+ * cc code-intel diag <file> # diagnostics
15
+ * cc code-intel rename <file> <line> <col> <newName> # preview a rename
16
+ *
17
+ * Positions are 1-based (line/col), matching editor gutters.
18
+ */
19
+
20
+ import chalk from "chalk";
21
+ import { logger } from "../lib/logger.js";
22
+
23
+ function num(v, name) {
24
+ const n = Number.parseInt(v, 10);
25
+ if (!Number.isFinite(n) || n < 1) {
26
+ throw new Error(`${name} must be a positive integer (1-based), got "${v}"`);
27
+ }
28
+ return n;
29
+ }
30
+
31
+ async function withCI(fn, { json } = {}) {
32
+ const { CodeIntelligence } = await import("../lib/lsp/code-intelligence.js");
33
+ // coldStart: each CLI invocation spawns a fresh server, so wait for the
34
+ // project to load before querying (the warm agent path leaves this off).
35
+ const ci = new CodeIntelligence({
36
+ projectRoot: process.cwd(),
37
+ coldStart: true,
38
+ });
39
+ try {
40
+ const result = await fn(ci);
41
+ if (json) {
42
+ console.log(JSON.stringify(result, null, 2));
43
+ }
44
+ return result;
45
+ } finally {
46
+ await ci.dispose();
47
+ }
48
+ }
49
+
50
+ function reportUnavailable(res) {
51
+ logger.warn(
52
+ chalk.yellow(`LSP unavailable: ${res.reason}`) +
53
+ chalk.gray(
54
+ "\n → falling back to text search (`cc search` / agent search_files)",
55
+ ),
56
+ );
57
+ process.exitCode = 3;
58
+ }
59
+
60
+ function fmtLoc(l) {
61
+ const pos = `${chalk.cyan(l.file)}:${chalk.yellow(l.line)}:${l.col}`;
62
+ return l.snippet ? `${pos} ${chalk.gray(l.snippet)}` : pos;
63
+ }
64
+
65
+ export function registerCodeIntelCommand(program) {
66
+ const ci = program
67
+ .command("code-intel")
68
+ .alias("ci")
69
+ .description(
70
+ "Semantic code navigation via LSP (definition/references/symbols/diagnostics)",
71
+ );
72
+
73
+ ci.command("status")
74
+ .description("Show which language servers are installed and detectable")
75
+ .option("--json", "Output as JSON")
76
+ .action(async (options) => {
77
+ const { probeServers, supportedExtensions } =
78
+ await import("../lib/lsp/lsp-server-registry.js");
79
+ // Surface plugin-contributed servers too (Phase 3: .lsp.json).
80
+ const { ensurePluginLspServers } =
81
+ await import("../lib/plugin-runtime/lsp.js");
82
+ ensurePluginLspServers({ cwd: process.cwd() });
83
+ const servers = probeServers(process.cwd());
84
+ if (options.json) {
85
+ console.log(
86
+ JSON.stringify(
87
+ { servers, extensions: supportedExtensions() },
88
+ null,
89
+ 2,
90
+ ),
91
+ );
92
+ return;
93
+ }
94
+ logger.log(chalk.bold("LSP servers:"));
95
+ for (const s of servers) {
96
+ const mark = s.available ? chalk.green("✔") : chalk.gray("✖");
97
+ const where = s.available
98
+ ? chalk.gray(s.command)
99
+ : chalk.gray("not installed");
100
+ logger.log(` ${mark} ${s.id.padEnd(28)} ${where}`);
101
+ }
102
+ const anyAvail = servers.some((s) => s.available);
103
+ if (!anyAvail) {
104
+ logger.log(
105
+ chalk.yellow(
106
+ "\nNo language servers found. Install one to enable semantic navigation, e.g.:\n",
107
+ ) + chalk.gray(" npm i -g typescript-language-server typescript"),
108
+ );
109
+ }
110
+ });
111
+
112
+ ci.command("def <file> <line> <col>")
113
+ .description("Go to definition of the symbol at file:line:col")
114
+ .option("--json", "Output as JSON")
115
+ .action(async (file, line, col, options) => {
116
+ const res = await withCI(
117
+ (c) => c.definition(file, num(line, "line"), num(col, "col")),
118
+ options,
119
+ );
120
+ if (!res.available) return reportUnavailable(res);
121
+ if (options.json) return;
122
+ if (!res.locations.length)
123
+ return logger.log(chalk.gray("No definition found."));
124
+ for (const l of res.locations) logger.log(fmtLoc(l));
125
+ });
126
+
127
+ ci.command("refs <file> <line> <col>")
128
+ .description("Find references to the symbol at file:line:col")
129
+ .option("--no-decl", "Exclude the declaration itself")
130
+ .option("--json", "Output as JSON")
131
+ .action(async (file, line, col, options) => {
132
+ const res = await withCI(
133
+ (c) =>
134
+ c.references(file, num(line, "line"), num(col, "col"), {
135
+ includeDeclaration: options.decl !== false,
136
+ }),
137
+ options,
138
+ );
139
+ if (!res.available) return reportUnavailable(res);
140
+ if (options.json) return;
141
+ logger.log(chalk.bold(`${res.locations.length} reference(s):`));
142
+ for (const l of res.locations) logger.log(" " + fmtLoc(l));
143
+ });
144
+
145
+ ci.command("hover <file> <line> <col>")
146
+ .description("Show type/doc info for the symbol at file:line:col")
147
+ .option("--json", "Output as JSON")
148
+ .action(async (file, line, col, options) => {
149
+ const res = await withCI(
150
+ (c) => c.hover(file, num(line, "line"), num(col, "col")),
151
+ options,
152
+ );
153
+ if (!res.available) return reportUnavailable(res);
154
+ if (options.json) return;
155
+ logger.log(res.contents || chalk.gray("No hover info."));
156
+ });
157
+
158
+ ci.command("symbols <file>")
159
+ .description("List symbols declared in a document")
160
+ .option("--json", "Output as JSON")
161
+ .action(async (file, options) => {
162
+ const res = await withCI((c) => c.documentSymbols(file), options);
163
+ if (!res.available) return reportUnavailable(res);
164
+ if (options.json) return;
165
+ for (const s of res.symbols) {
166
+ const loc = chalk.gray(`${s.line}:${s.col}`);
167
+ const kind = chalk.magenta(s.kind.padEnd(10));
168
+ const container = s.container ? chalk.gray(` (${s.container})`) : "";
169
+ logger.log(` ${loc} ${kind} ${s.name}${container}`);
170
+ }
171
+ });
172
+
173
+ ci.command("wsymbols <query>")
174
+ .description("Search symbols across the workspace by name")
175
+ .option("--json", "Output as JSON")
176
+ .action(async (query, options) => {
177
+ const res = await withCI((c) => c.workspaceSymbols(query), options);
178
+ if (!res.available) return reportUnavailable(res);
179
+ if (options.json) return;
180
+ logger.log(chalk.bold(`${res.symbols.length} symbol(s):`));
181
+ for (const s of res.symbols) {
182
+ logger.log(
183
+ ` ${chalk.magenta(s.kind.padEnd(10))} ${s.name} ${chalk.gray(`${s.file}:${s.line}`)}`,
184
+ );
185
+ }
186
+ });
187
+
188
+ ci.command("diag <file>")
189
+ .description("Show diagnostics (errors/warnings) for a file")
190
+ .option(
191
+ "--timeout <ms>",
192
+ "How long to wait for the server to publish",
193
+ "5000",
194
+ )
195
+ .option("--json", "Output as JSON")
196
+ .action(async (file, options) => {
197
+ const res = await withCI(
198
+ (c) =>
199
+ c.diagnostics(file, { timeoutMs: num(options.timeout, "timeout") }),
200
+ options,
201
+ );
202
+ if (!res.available) return reportUnavailable(res);
203
+ if (options.json) return;
204
+ if (!res.diagnostics.length)
205
+ return logger.log(chalk.green("No diagnostics."));
206
+ for (const d of res.diagnostics) {
207
+ const sev =
208
+ d.severity === "error"
209
+ ? chalk.red(d.severity)
210
+ : d.severity === "warning"
211
+ ? chalk.yellow(d.severity)
212
+ : chalk.gray(d.severity);
213
+ logger.log(
214
+ ` ${chalk.gray(`${d.line}:${d.col}`)} ${sev} ${d.message}${d.code ? chalk.gray(` [${d.code}]`) : ""}`,
215
+ );
216
+ }
217
+ });
218
+
219
+ ci.command("rename <file> <line> <col> <newName>")
220
+ .description(
221
+ "Preview a symbol rename across files (does NOT apply the edit)",
222
+ )
223
+ .option("--json", "Output as JSON")
224
+ .action(async (file, line, col, newName, options) => {
225
+ const res = await withCI(
226
+ (c) =>
227
+ c.renamePreview(file, num(line, "line"), num(col, "col"), newName),
228
+ options,
229
+ );
230
+ if (!res.available) return reportUnavailable(res);
231
+ if (options.json) return;
232
+ const total = res.edits.reduce((n, f) => n + f.edits.length, 0);
233
+ logger.log(
234
+ chalk.bold(
235
+ `Rename would touch ${res.edits.length} file(s), ${total} edit(s):`,
236
+ ),
237
+ );
238
+ for (const f of res.edits) {
239
+ logger.log(` ${chalk.cyan(f.file)} — ${f.edits.length} edit(s)`);
240
+ for (const e of f.edits) {
241
+ logger.log(chalk.gray(` ${e.line}:${e.col} → "${e.newText}"`));
242
+ }
243
+ }
244
+ logger.log(
245
+ chalk.gray(
246
+ "\n(preview only — apply with your editor or agent edit tools)",
247
+ ),
248
+ );
249
+ });
250
+
251
+ return ci;
252
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * `cc eval` — reliability eval harness (Phase 7). Runs a suite of self-checking
3
+ * coding tasks against the real agent and reports the task-success rate.
4
+ *
5
+ * Each task gets a fresh temp workspace; the agent is invoked headlessly
6
+ * (`cc agent -p` in that cwd with acceptEdits so it can write files) and the
7
+ * task's objective check() decides pass/fail. `--dry-run` swaps in a no-op agent
8
+ * so the harness + report can be exercised without a model.
9
+ */
10
+
11
+ import fs from "fs";
12
+ import path from "path";
13
+ import { fileURLToPath } from "url";
14
+ import { spawn } from "child_process";
15
+ import { runEvalSuite } from "../lib/eval/runner.js";
16
+ import { getSuite } from "../lib/eval/tasks.js";
17
+ import {
18
+ TelemetryRecorder,
19
+ formatTelemetry,
20
+ } from "../lib/telemetry/span-recorder.js";
21
+ import { computeTrend, formatTrend } from "../lib/eval/trend.js";
22
+
23
+ /** Append a run summary as one JSONL line to the history file. */
24
+ function appendHistory(file, record) {
25
+ fs.appendFileSync(file, JSON.stringify(record) + "\n", "utf8");
26
+ }
27
+
28
+ /** Read a JSONL eval-history file into an array of run records (skips bad lines). */
29
+ function readHistory(file) {
30
+ if (!fs.existsSync(file)) return [];
31
+ const out = [];
32
+ for (const line of fs.readFileSync(file, "utf8").split(/\r?\n/)) {
33
+ const t = line.trim();
34
+ if (!t) continue;
35
+ try {
36
+ out.push(JSON.parse(t));
37
+ } catch {
38
+ /* skip a corrupt history line rather than abort the report */
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+
44
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
45
+ // This file is src/commands/eval.js → the CLI entry is bin/chainlesschain.js.
46
+ const BIN = path.resolve(__dirname, "..", "..", "bin", "chainlesschain.js");
47
+
48
+ /**
49
+ * Build a runAgent that shells out to a headless `cc agent -p` in the task's
50
+ * workspace. acceptEdits lets it write files without an interactive prompt.
51
+ */
52
+ function makeHeadlessRunAgent(opts = {}) {
53
+ return function runAgent({ prompt, cwd, timeoutMs }) {
54
+ return new Promise((resolve) => {
55
+ const args = [
56
+ BIN,
57
+ "agent",
58
+ "-p",
59
+ prompt,
60
+ "--permission-mode",
61
+ "acceptEdits",
62
+ "--output-format",
63
+ "text",
64
+ ];
65
+ if (opts.model) args.push("--model", opts.model);
66
+ if (opts.provider) args.push("--provider", opts.provider);
67
+ const child = spawn(process.execPath, args, {
68
+ cwd,
69
+ env: { ...process.env, CLAUDECODE: "1" },
70
+ windowsHide: true,
71
+ });
72
+ let out = "";
73
+ let err = "";
74
+ let settled = false;
75
+ const done = (result) => {
76
+ if (settled) return;
77
+ settled = true;
78
+ resolve(result);
79
+ };
80
+ const timer = setTimeout(() => {
81
+ try {
82
+ child.kill("SIGTERM");
83
+ } catch {
84
+ /* already gone */
85
+ }
86
+ done({
87
+ ok: false,
88
+ output: out,
89
+ error: `timed out after ${timeoutMs || 120000}ms`,
90
+ });
91
+ }, timeoutMs || 120000);
92
+ if (typeof timer.unref === "function") timer.unref();
93
+ child.stdout?.on("data", (d) => (out += d.toString("utf8")));
94
+ child.stderr?.on("data", (d) => (err += d.toString("utf8")));
95
+ child.on("error", (e) => {
96
+ clearTimeout(timer);
97
+ done({ ok: false, output: out, error: e.message });
98
+ });
99
+ child.on("close", (code) => {
100
+ clearTimeout(timer);
101
+ done({ ok: code === 0, output: out, error: code === 0 ? null : err });
102
+ });
103
+ });
104
+ };
105
+ }
106
+
107
+ export function registerEvalCommand(program, { logger } = {}) {
108
+ const log = logger || console;
109
+ program
110
+ .command("eval")
111
+ .description(
112
+ "Run the reliability eval suite (self-checking coding tasks) and report the task-success rate",
113
+ )
114
+ .option("--suite <name>", "Suite to run", "builtin")
115
+ .option("--model <model>", "Model for the agent runs")
116
+ .option("--provider <provider>", "Provider for the agent runs")
117
+ .option("--json", "Output the summary as JSON")
118
+ .option("--keep", "Keep the per-task temp workspaces (debug)")
119
+ .option(
120
+ "--otlp <file>",
121
+ "Write OpenTelemetry (OTLP/JSON) spans for the run to a file",
122
+ )
123
+ .option(
124
+ "--dry-run",
125
+ "Use a no-op agent (exercise the harness/report without a model)",
126
+ )
127
+ .option(
128
+ "--history <file>",
129
+ "Append this run's summary (JSONL) for trend tracking",
130
+ )
131
+ .option(
132
+ "--label <label>",
133
+ "Tag this run in the history (e.g. a version/commit)",
134
+ )
135
+ .option(
136
+ "--trend",
137
+ "Report the pass-rate trend from --history instead of running (CI gate)",
138
+ )
139
+ .option(
140
+ "--regression-threshold <pct>",
141
+ "With --trend: pass-rate drop (in points) that fails the gate on its own",
142
+ "0",
143
+ )
144
+ .action(async (options) => {
145
+ // Trend mode: don't run the suite — read the recorded history and report
146
+ // the pass-rate trend + per-task regressions. This is the release-pipeline
147
+ // consumer (the runs themselves need a real model; the report is pure).
148
+ if (options.trend) {
149
+ if (!options.history) {
150
+ (log.error || console.error)("--trend requires --history <file>");
151
+ process.exitCode = 1;
152
+ return;
153
+ }
154
+ const runs = readHistory(options.history);
155
+ const threshold =
156
+ Math.max(0, Number(options.regressionThreshold) || 0) / 100;
157
+ const trend = computeTrend(runs, { regressionThreshold: threshold });
158
+ if (options.json) console.log(JSON.stringify(trend, null, 2));
159
+ else (log.log || console.log)(formatTrend(trend));
160
+ if (trend.regressed) process.exitCode = 1;
161
+ return;
162
+ }
163
+
164
+ let tasks;
165
+ try {
166
+ tasks = getSuite(options.suite);
167
+ } catch (err) {
168
+ log.error ? log.error(err.message) : console.error(err.message);
169
+ process.exitCode = 1;
170
+ return;
171
+ }
172
+ const runAgent = options.dryRun
173
+ ? async () => ({ ok: true, output: "(dry-run: no agent)" })
174
+ : makeHeadlessRunAgent({
175
+ model: options.model,
176
+ provider: options.provider,
177
+ });
178
+
179
+ // OTel-shaped telemetry for the run (per-task span + failure class).
180
+ const recorder = new TelemetryRecorder({ serviceName: "cc-eval" });
181
+
182
+ const summary = await runEvalSuite(tasks, {
183
+ runAgent,
184
+ recorder,
185
+ keepWorkspaces: options.keep === true,
186
+ onResult: options.json
187
+ ? undefined
188
+ : (r) =>
189
+ (log.info || console.log)(
190
+ ` ${r.pass ? "✔" : "✗"} ${r.id} (${r.ms}ms)` +
191
+ (r.error
192
+ ? ` — ${r.error}`
193
+ : r.detail
194
+ ? ` — ${r.detail}`
195
+ : ""),
196
+ ),
197
+ });
198
+
199
+ if (options.otlp) {
200
+ try {
201
+ fs.writeFileSync(
202
+ options.otlp,
203
+ JSON.stringify(recorder.toOtlp(), null, 2),
204
+ "utf8",
205
+ );
206
+ } catch (e) {
207
+ (log.error || console.error)(` otlp write failed: ${e.message}`);
208
+ }
209
+ }
210
+
211
+ // Append to the trend history (a compact record — pass counts + per-task
212
+ // pass/fail + a timestamp/label — so `cc eval --trend` can chart it).
213
+ if (options.history) {
214
+ try {
215
+ appendHistory(options.history, {
216
+ ranAt: new Date().toISOString(),
217
+ label: options.label || null,
218
+ passed: summary.passed,
219
+ total: summary.total,
220
+ passRate: summary.passRate,
221
+ results: (summary.results || []).map((r) => ({
222
+ id: r.id,
223
+ pass: r.pass,
224
+ })),
225
+ });
226
+ } catch (e) {
227
+ (log.error || console.error)(` history write failed: ${e.message}`);
228
+ }
229
+ }
230
+
231
+ if (options.json) {
232
+ console.log(JSON.stringify(summary, null, 2));
233
+ } else {
234
+ // Per-task lines already streamed via onResult; print the summary +
235
+ // the telemetry metrics (durations / failure classification).
236
+ const pct = (summary.passRate * 100).toFixed(1);
237
+ (log.log || console.log)(
238
+ `\nEval: ${summary.passed}/${summary.total} passed (${pct}%) in ${summary.ms}ms`,
239
+ );
240
+ if (summary.telemetry) {
241
+ (log.log || console.log)("\n" + formatTelemetry(summary.telemetry));
242
+ }
243
+ }
244
+ // Non-zero exit when not every task passed — usable as a CI gate.
245
+ if (summary.passed < summary.total) process.exitCode = 1;
246
+ });
247
+ return program;
248
+ }