chainlesschain 0.166.48 → 0.166.58

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 (188) hide show
  1. package/README.md +22 -0
  2. package/package.json +2 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BLGEffkh.js → AIOps-DoyI29Aw.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-Cz1z2VGD.js → ActionButton-eZKcEoxc.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-C3j9cf6q.js → Analytics-B2C2e9A7.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-BR9ERuCA.js → AppLayout-DkZJiu4X.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CozJCm4y.js → Artifacts-8PD3BXVa.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DC5g9Ra2.js → Audit-Cv6sRlFu.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-B1zrQ0dW.js → BackgroundAgents-D-V84Qpm.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-ChVnfjpm.js → Backup-DYJQcxj1.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-8_vLQsLf.js → BaseInput-KL2IeywH.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-Dct9bm6L.js → Chat-Bt9wy_Yn.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BvoSsCKh.js → ChatBubbleRenderer-ChB6fH-W.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-DZQIsCIC.js → Checkbox-Dm-nfdnd.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-CdzHxmnq.js → Codegen-CYi3yDzv.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-DdAN8LeW.js → Col-C7sQywfG.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-CNgjT9MA.js → Community-DjxuqAM4.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BtQiX6G-.js → Compact-CD_4lbxr.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-OGX5ma3j.js → Compliance-BtDpNJrS.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-CgugQnGM.js → Cowork-l19ANH6Q.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-Bpg7cPFD.js → Cron-Br-rBoEK.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-D1hsuswf.js → Crosschain-60UVvKET.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-miDRsMBw.js → DID-B9dqar51.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-CGcl8htP.js → Dashboard-B39hhdHb.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BFaxTdVE.js → Dropdown-Bm5rCfvF.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-BQdGLZIO.js → EmailListRenderer-BI9HANDl.js} +1 -1
  28. package/src/assets/web-panel/assets/EvolutionSettings-Cfqn_yCq.js +1 -0
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-c1WVC_--.js → FamilyGuardDashboard-9Y4_zyhT.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-DyAcFrQY.js → Federation-vnbbmMdF.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-CfwpfD2B.js → FormItemContext-BEKNtNF9.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-DkJcbBpS.js → GenericCardRenderer-BmWr16IL.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-DgYIrPJh.js → Git-CUUwAXdn.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-BF1tYPJ6.js → Governance-Bw8XZmH9.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-BFkwRIrU.js → Inference-CNrml6dn.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-DpCoqhBa.js → KnowledgeGraph-BhxOwpW_.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-DU2qAJmD.js → Logs-BV8WViUG.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-CO1qbiOY.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-Dz9NUrfo.js → Marketplace-ztcu4mg4.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-B67I3d5v.js → McpTools-D-wzRO7z.js} +2 -2
  41. package/src/assets/web-panel/assets/{Memory-crkElJSy.js → Memory-ChdjWC1R.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-BO20VbdX.js → MobileBridge-B1QHzIjE.js} +1 -1
  43. package/src/assets/web-panel/assets/{MobileProjects-Ba-3gZZd.js → MobileProjects-DmaRtaMw.js} +1 -1
  44. package/src/assets/web-panel/assets/{Mtc-BAHZM084.js → Mtc-DRQMr4WP.js} +4 -4
  45. package/src/assets/web-panel/assets/{MtcAudit-CL3DzajL.js → MtcAudit-Cwo0on-u.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-BSWWzvWH.js → Multisig-QplgySFt.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-fnxqXM_3.js → NLProgramming-BWkMyuAy.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-qUZPIQXT.js → Notes-BI_pSEM0.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-x9Xrixqu.js → NotificationSettings-DiuFo6Xe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-BtMtQUt7.js → OrderTableRenderer-DZzQhujZ.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-C946Hzna.js → Organization-DqEdqWB0.js} +2 -2
  52. package/src/assets/web-panel/assets/{Overflow-BYf8KIts.js → Overflow-CO7_2YLN.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-Cbqf5dnv.js → P2P-BN5RiNst.js} +2 -2
  54. package/src/assets/web-panel/assets/PdhVaultBrowser-CapfG4bl.js +7 -0
  55. package/src/assets/web-panel/assets/{Permissions-CZBw45EW.js → Permissions-B24c5fWW.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-BKwUAt43.js → PersonalDataHub-D7Mb3_vh.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-DmFD2QW4.js → Pipeline-BsfxlbOQ.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-KpuwWvt5.js → Privacy-Bq7c7IYy.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-Bt8UheX6.js → ProjectInit-Clse2DPl.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-2ZeAn9CP.js → ProjectSettings-CHAEdjri.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-C1UHvBEK.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-DcEAnw6L.js → Providers-DQyH3PXU.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-qF7liYG9.js → QrScannerModal-t2Z-N49o.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-qiESlVBJ.js → QuickAsk-BacR7PlI.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-Bk-cQyi9.js → Recommend-D-NAy0CQ.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-CwrekErS.js → RemoteSession-CjI3GeVQ.js} +2 -2
  67. package/src/assets/web-panel/assets/{Reputation-Bmw_UQtW.js → Reputation-HoQ3i2oW.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-CPdqZIUX.js → Row-CY2jczWa.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-D_W-xxvS.js → RssFeed-Bd3o20IY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Search-Hu0oDFj_.js → Search-C88KjgTv.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-DeRxUwmq.js → Security-yfmfvujK.js} +3 -3
  72. package/src/assets/web-panel/assets/{Services-CsNmHFkf.js → Services-DLPBWoxT.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-gv_Vz0tN.js → Skeleton-DzDjvVQi.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-Dgg-_rCB.js → Skills-DqfrJIyP.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-Bpu-bsEJ.js → Sla-BXhsGzkm.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-CrhleHuF.js → SpeechSettings-jxSl2JDo.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-JHjUN6I9.js → SyncSettings-BX2xKtI3.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-DKRWKkl9.js → Tasks-P9MmRYt4.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-leiWntLq.js → Templates-CTpj9f62.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant--1bYulvn.js → Tenant-nnQuhdPg.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-C0y6FvSS.js → Terminal-cJ0vbuTe.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-CQK4PVv4.js → TimelineRenderer-DN08D0SD.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-DbIvF-DV.js → Tokens-C8BWWBUD.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-CkXJ2vuq.js → Trigger-DhD-LUoe.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-B02WXJPw.js → Trust-D0nFyc_Z.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-VPMkfzmw.js → UkeySign-B59G57LP.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-C5ezUnah.js → VideoEditing-BpYACxVC.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-CYfvYRrY.js → Wallet-DlZ3rKGD.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-DtKl-kpr.js → WebAuthn-De4dNyig.js} +5 -5
  90. package/src/assets/web-panel/assets/{WorkflowEditor-DACITF-u.js → WorkflowEditor-C2Tewnhp.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-qnygfnLi.js → chat-CDBn4JLE.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-D4mISLBD.js → colors-BNawl0d_.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-BBPfxYGL.js → compact-item-n65WDhze.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-Byx4ndHp.js → createContext-DAKgOdIy.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-sBSSW127.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-CGjLkkn3.js → hasIn-DhxFG46W.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CWhI8G14.js → index--76HBS1k.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Dmfe0L2Z.js → index-0Y-ncsVy.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BzeBBAl5.js → index-5oJjovnA.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CFMWjuav.js → index-BAogaHa9.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-B8UpadHC.js → index-BBFjMjmp.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BmKYaaGP.js → index-BDTrf8WH.js} +1 -1
  103. package/src/assets/web-panel/assets/index-BIJTDSLY.js +1 -0
  104. package/src/assets/web-panel/assets/{index-CD5Btq6p.js → index-BQFAuU1c.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CVUJjQAT.js → index-BRyzRluv.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-O09jXbir.js → index-BZI8xwwt.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CMj8qmpX.js → index-BfXdTvku.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-D_g9mA1N.js → index-BudfMkBy.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BN7_TSgU.js → index-By-zGgUp.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Ne8UGllV.js → index-ByDs4cW4.js} +3 -3
  111. package/src/assets/web-panel/assets/{index-CZjNamSU.js → index-BzONk4rW.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-xzRKTy0R.js → index-CE6OcLof.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-J5JkStvY.js → index-CSOgoyqx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BklGH3YI.js → index-CW_OUdP8.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CmHE-lY_.js → index-CZJrAg98.js} +1 -1
  116. package/src/assets/web-panel/assets/index-CrBauOkp.js +1 -0
  117. package/src/assets/web-panel/assets/{index-lKJWAmd4.js → index-Cv7LqHwv.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dzni_5Qw.js → index-D34AXxN9.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-c_tBkIlU.js → index-D6sWUgN6.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Y7el_3WS.js → index-DCujBaFg.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BxQF1wCU.js → index-DFkamspD.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CsVuQsY1.js → index-DLFRz0_7.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-ByA1NyFP.js → index-DV6iHrUO.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DboTeuPF.js → index-D_-6qQf0.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C9tcHs46.js → index-DeTlqus4.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DH6iC5b2.js → index-DkW0HGr-.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-B9jH-h4X.js → index-DleKcclQ.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Cpg3AWRy.js → index-Ds290C06.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B_fHPZ8E.js → index-KT94nMha.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-C3abGsSW.js → index-KZkt4e9N.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DZXhKAk9.js → index-L1QnA0gW.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DfgpKd64.js → index-PlOBwfR1.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-CoA8WsVr.js → index-gG1WJBpa.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BNe2lCk6.js → index-hA9VUXGr.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CydHMjwc.js → index-pzEYIGNA.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-XuhfEIhB.js → initDefaultProps-B3bCivrt.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-Cbxh6AxO.js → motion-CF5pGsxz.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-C7IEnFly.js → move-CaOFtFLU.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-lLADx4LL.js → mtc-parser-Z4-50Y1c.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-mIbic_k-.js → omit-AK4WqVTT.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-_xIYEqu3.js → pickAttrs-Dbye0px4.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-ClB-E0ny.js → placementArrow-DCmr-Dks.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-D36Bg2ut.js → responsiveObserve-CJ3Zm_-H.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-CUuO08Bl.js → slide-BuSk5-ue.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-BKahwLbv.js → statusUtils-8u_lKSFJ.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-2pT-T8vy.js → styleChecker-sy6_m42F.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-DyH5g7Rg.js → useFlexGapSupport-Di5EfYGo.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-CTOauB3X.js → useFs-BTfX_Ri1.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-B02JYIMe.js → usePersonalDataHub-kqurO26X.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-Do22wQrc.js → vnode-DRkH4mPV.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-BfnL7rit.js → zoom-ON_-UuD_.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/commands/agent.js +5 -0
  154. package/src/commands/config.js +19 -10
  155. package/src/commands/context.js +31 -11
  156. package/src/commands/eval.js +39 -4
  157. package/src/commands/evolution-deployment.js +70 -0
  158. package/src/data/changelog.json +91 -0
  159. package/src/gateways/ws/evolution-deployment-topic-handlers.js +20 -0
  160. package/src/harness/prompt-compressor.js +12 -4
  161. package/src/lib/diagnostic-excerpt.js +51 -0
  162. package/src/lib/diagnostic-workflow.js +10 -0
  163. package/src/lib/eval/evidence.js +19 -10
  164. package/src/lib/eval/outcomes.js +373 -0
  165. package/src/lib/eval/runner.js +6 -0
  166. package/src/lib/evolution/evolution-deployment-config.js +16 -1
  167. package/src/lib/evolution/evolution-deployment-profile.js +102 -58
  168. package/src/lib/evolution/evolution-test-deployment.js +386 -0
  169. package/src/lib/git-tool-input.js +37 -0
  170. package/src/lib/llm-config-defaults.js +32 -9
  171. package/src/lib/model-context-window.js +3 -2
  172. package/src/lib/read-file-loop-guard.js +54 -0
  173. package/src/lib/remote-read-loop-guard.js +12 -14
  174. package/src/lib/runtime-usage-ledger.js +5 -0
  175. package/src/lib/session-message-fabric.js +74 -37
  176. package/src/lib/shell-output.js +30 -0
  177. package/src/lib/task-progress-tracker.js +88 -0
  178. package/src/repl/agent-repl.js +19 -4
  179. package/src/runtime/agent-core.js +108 -22
  180. package/src/runtime/headless-runner.js +4 -0
  181. package/src/runtime/headless-stream.js +34 -1
  182. package/src/assets/web-panel/assets/EvolutionSettings-bMvgBk6r.js +0 -1
  183. package/src/assets/web-panel/assets/MarkdownRenderer-QWv7UJLq.js +0 -1
  184. package/src/assets/web-panel/assets/PdhVaultBrowser-rmxp0cuF.js +0 -7
  185. package/src/assets/web-panel/assets/Projects-zBuet8Zs.js +0 -1
  186. package/src/assets/web-panel/assets/devWarning-DBy6gsuI.js +0 -1
  187. package/src/assets/web-panel/assets/index-BfEDXk_E.js +0 -1
  188. package/src/assets/web-panel/assets/index-CrxUwNM8.js +0 -1
@@ -315,7 +315,11 @@ export class PromptCompressor {
315
315
  !options.maxMessages &&
316
316
  !options.maxTokens
317
317
  ) {
318
- const ctxWindow = getContextWindow(options.model, options.provider);
318
+ const ctxWindow = getContextWindow(
319
+ options.model,
320
+ options.provider,
321
+ options,
322
+ );
319
323
  const adaptive = adaptiveThresholds(ctxWindow);
320
324
  this.maxMessages = adaptive.maxMessages;
321
325
  this.maxTokens = adaptive.maxTokens;
@@ -337,8 +341,8 @@ export class PromptCompressor {
337
341
  );
338
342
  }
339
343
 
340
- adaptToModel(model, provider) {
341
- const ctxWindow = getContextWindow(model, provider);
344
+ adaptToModel(model, provider, options = {}) {
345
+ const ctxWindow = getContextWindow(model, provider, options);
342
346
  const adaptive = adaptiveThresholds(ctxWindow);
343
347
  this.maxMessages = adaptive.maxMessages;
344
348
  this.maxTokens = adaptive.maxTokens;
@@ -483,8 +487,12 @@ export class PromptCompressor {
483
487
  }
484
488
 
485
489
  shouldAutoCompact(messages) {
490
+ // Large adaptive windows use token pressure, not an arbitrary 50-message
491
+ // trigger. Small local models and explicit fixed limits retain their
492
+ // count-based policy; maxMessages remains a compaction target in all modes.
486
493
  return (
487
- messages.length > this.maxMessages ||
494
+ ((!this._adaptive || this._contextWindow < 128000) &&
495
+ messages.length > this.maxMessages) ||
488
496
  estimateMessagesTokens(messages) > this.maxTokens
489
497
  );
490
498
  }
@@ -0,0 +1,51 @@
1
+ /** Retain source context for several errors; an error line is not a root cause. */
2
+ export function diagnosticExcerpt(value, limit = 1600) {
3
+ const text = typeof value === "string" ? value : JSON.stringify(value ?? "");
4
+ if (text.length <= limit) return text;
5
+ const marker = "\n[... omitted ...]\n";
6
+ const lines = text.split("\n");
7
+ const errors = [];
8
+ const workers = [];
9
+ for (let i = 0; i < lines.length; i++) {
10
+ if (
11
+ /\b\w*Error:|Exception in thread|Caused by:|\bpanic:|panicked at|\bFAIL\b|error TS\d+|##\[error\]/.test(
12
+ lines[i],
13
+ )
14
+ )
15
+ errors.push(i);
16
+ if (
17
+ /\[vitest-pool\]|Worker.*(?:error|exited)|Unhandled (?:Error|Rejection)/i.test(
18
+ lines[i],
19
+ )
20
+ )
21
+ workers.push(i);
22
+ }
23
+ // Keep both an early diagnostic (possibly expected negative-test output)
24
+ // and later runner failures. Never infer causality from their ordering.
25
+ const indices = [
26
+ ...new Set(
27
+ [workers[0], errors[0], errors.at(-1)].filter((i) => i !== undefined),
28
+ ),
29
+ ].sort((a, b) => a - b);
30
+ if (!indices.length) {
31
+ const head = Math.floor((limit - marker.length) / 2);
32
+ return (
33
+ text.slice(0, head) + marker + text.slice(-(limit - marker.length - head))
34
+ );
35
+ }
36
+ const available = limit - marker.length * (indices.length + 1);
37
+ const head = Math.floor(available * 0.1);
38
+ const tail = Math.floor(available * 0.15);
39
+ const perWindow = Math.floor((available - head - tail) / indices.length);
40
+ const windows = indices.map((index) => {
41
+ const before = lines
42
+ .slice(Math.max(0, index - 2), index)
43
+ .join("\n")
44
+ .slice(-Math.floor(perWindow * 0.2));
45
+ return (before + "\n" + lines.slice(index, index + 10).join("\n")).slice(
46
+ 0,
47
+ perWindow,
48
+ );
49
+ });
50
+ return [text.slice(0, head), ...windows, text.slice(-tail)].join(marker);
51
+ }
@@ -0,0 +1,10 @@
1
+ // Shared across ordinary debugging and recovery. Tool observations establish
2
+ // process outcomes; the model still has to validate the causal hypothesis.
3
+ export const DIAGNOSTIC_WORKFLOW_GUIDANCE =
4
+ "For debugging, retain the original failure signature (error, source location, stack, command, environment and revision when verified). " +
5
+ "Label each observation by its source and reproduction scope. A passing subset is not a successful full reproduction; a different error is a separate finding until evidence connects it to the original failure. " +
6
+ "Expected negative-test output, dependency/setup failures, failed assertions and runner/infrastructure failures are different possibilities. Inspect surrounding output and process outcomes before selecting one. Timing alone does not identify the cause, and argument order is not execution order. " +
7
+ "State one hypothesis and the smallest check that can disprove it; after that check, update the hypothesis from the observed result instead of restarting discovery. " +
8
+ "Do not change dependencies while a reproduction using them is running. Poll background tasks by task_id and drain has_more_output after exit. " +
9
+ "Bind reports to verified paths, runs and attempts; do not substitute a local or stale report for the target run. A green report alone does not override a nonzero exit, unhandled errors or incomplete output. " +
10
+ "A fix requires validation against the original failure and relevant regression checks. Otherwise report what was reproduced, what differs and the specific missing evidence; do not claim the original issue is fixed.";
@@ -146,6 +146,10 @@ export function createEvalHistoryRecord(
146
146
  executionSucceeded: result.executionSucceeded,
147
147
  agentOk: result.agentOk,
148
148
  executionEvidence: result.executionEvidence,
149
+ usage: result.usage ?? null,
150
+ totalCostUsd: Number.isFinite(result.totalCostUsd)
151
+ ? result.totalCostUsd
152
+ : null,
149
153
  error:
150
154
  result.error == null
151
155
  ? null
@@ -209,7 +213,19 @@ function validateComparison(value) {
209
213
  }
210
214
  }
211
215
 
212
- function recordIssues(record, now, maxAgeMs) {
216
+ export function evalExecutionSucceeded(result) {
217
+ const execution = result?.executionEvidence;
218
+ return (
219
+ result?.executionSucceeded === true &&
220
+ result.error === null &&
221
+ execution?.protocol === EVAL_EXECUTION_PROTOCOL &&
222
+ execution.exitCode === 0 &&
223
+ execution.signal === null &&
224
+ execution.terminalVerified === true
225
+ );
226
+ }
227
+
228
+ export function evalHistoryRecordIssues(record, now, maxAgeMs) {
213
229
  if (!record || typeof record !== "object" || Array.isArray(record))
214
230
  return ["invalid_history_record"];
215
231
  const issues = [];
@@ -247,14 +263,7 @@ function recordIssues(record, now, maxAgeMs) {
247
263
  result.pass !== (result.artifactCheckPassed && result.executionSucceeded)
248
264
  )
249
265
  issues.push("inconsistent_task_verdict");
250
- if (
251
- !result.executionSucceeded ||
252
- result.error !== null ||
253
- execution?.protocol !== EVAL_EXECUTION_PROTOCOL ||
254
- execution.exitCode !== 0 ||
255
- execution.signal !== null ||
256
- execution.terminalVerified !== true
257
- )
266
+ if (!evalExecutionSucceeded(result))
258
267
  issues.push("execution_not_successful");
259
268
  if (execution?.observedFallback !== false)
260
269
  issues.push("fallback_or_missing_model_continuity");
@@ -296,7 +305,7 @@ export function evaluateStrictEvalGate(
296
305
  if (!Array.isArray(runs) || runs.length < 2) reasons.push("missing_baseline");
297
306
  const pair = Array.isArray(runs) ? runs.slice(-2) : [];
298
307
  for (const record of pair)
299
- reasons.push(...recordIssues(record, now, maxAgeMs));
308
+ reasons.push(...evalHistoryRecordIssues(record, now, maxAgeMs));
300
309
  if (pair.length === 2) {
301
310
  const [baseline, candidate] = pair;
302
311
  if (
@@ -0,0 +1,373 @@
1
+ import {
2
+ evalDigest,
3
+ evalHistoryRecordIssues,
4
+ evalExecutionSucceeded,
5
+ } from "./evidence.js";
6
+
7
+ export const OUTCOME_PLAN_SCHEMA = "chainlesschain.outcome-plan/v1";
8
+ export const OUTCOME_REPORT_SCHEMA = "chainlesschain.outcome-report/v1";
9
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
10
+ const CATEGORIES = new Set([
11
+ "repair",
12
+ "support",
13
+ "compatibility",
14
+ "release",
15
+ "test-infrastructure",
16
+ "construction",
17
+ ]);
18
+ const STAGES = ["install", "configure", "authenticate", "tool", "artifact"];
19
+ const FAILURE_CAUSES = new Set([
20
+ "install",
21
+ "configuration-identity",
22
+ "model-protocol",
23
+ "tools-permissions",
24
+ "retrieval-context",
25
+ "recovery",
26
+ "artifact",
27
+ "environment",
28
+ "budget",
29
+ "manual-repair",
30
+ ]);
31
+ const nonempty = (value) =>
32
+ typeof value === "string" && value.trim().length > 0;
33
+ const nonnegative = (value) => Number.isFinite(value) && value >= 0;
34
+ const count = (value) => Number.isSafeInteger(value) && value >= 0;
35
+ const rate = (numerator, denominator) =>
36
+ denominator ? numerator / denominator : null;
37
+ function assert(value, message) {
38
+ if (!value) throw new Error(message);
39
+ }
40
+ function canonical(value) {
41
+ if (Array.isArray(value)) return value.map(canonical);
42
+ if (!value || typeof value !== "object") return value;
43
+ return Object.fromEntries(
44
+ Object.keys(value)
45
+ .sort()
46
+ .map((key) => [key, canonical(value[key])]),
47
+ );
48
+ }
49
+ export function outcomeDigest(value) {
50
+ return evalDigest(JSON.stringify(canonical(value)));
51
+ }
52
+ function epoch(value) {
53
+ const time = Date.parse(value);
54
+ return typeof value === "string" &&
55
+ Number.isFinite(time) &&
56
+ new Date(time).toISOString() === value
57
+ ? time
58
+ : NaN;
59
+ }
60
+ function uniqueIndex(rows, key, label) {
61
+ assert(Array.isArray(rows), `${label} must be an array`);
62
+ const index = new Map();
63
+ for (const row of rows) {
64
+ assert(
65
+ row && nonempty(row[key]) && !index.has(row[key]),
66
+ `${label} contains a missing or duplicate ${key}`,
67
+ );
68
+ index.set(row[key], row);
69
+ }
70
+ return index;
71
+ }
72
+
73
+ export function validateOutcomePlan(plan) {
74
+ assert(plan?.schema === OUTCOME_PLAN_SCHEMA, "invalid outcome plan schema");
75
+ assert(
76
+ /^[a-f0-9]{40}$/u.test(plan.commitSha || ""),
77
+ "plan requires an exact commit SHA",
78
+ );
79
+ assert(/^[A-Z]{3}$/u.test(plan.currency || ""), "plan requires one currency");
80
+ assert(
81
+ epoch(plan.window?.start) < epoch(plan.window?.end),
82
+ "invalid observation window",
83
+ );
84
+ const samples = uniqueIndex(plan.samples, "id", "plan samples");
85
+ assert(
86
+ samples.size > 0 && samples.size <= 10000,
87
+ "plan requires 1–10000 samples",
88
+ );
89
+ for (const sample of samples.values()) {
90
+ assert(["task", "first-run"].includes(sample.kind), "invalid sample kind");
91
+ assert(
92
+ nonempty(sample.taskId) && nonempty(sample.stratum),
93
+ "sample requires taskId and stratum",
94
+ );
95
+ assert(
96
+ DIGEST.test(sample.comparisonDigest || ""),
97
+ "sample requires an Eval comparison digest",
98
+ );
99
+ assert(
100
+ nonnegative(sample.costBudget) &&
101
+ Number.isFinite(sample.timeBudgetMs) &&
102
+ sample.timeBudgetMs > 0,
103
+ "sample requires finite cost and time budgets",
104
+ );
105
+ }
106
+ return samples;
107
+ }
108
+
109
+ function summarize(rows) {
110
+ const succeeded = rows.filter((row) => row.succeeded).length;
111
+ const observed = rows.filter((row) => row.observed).length;
112
+ const knownCost = rows.reduce((sum, row) => sum + (row.cost ?? 0), 0);
113
+ const costsComplete = rows.every((row) => row.observed && row.cost !== null);
114
+ return {
115
+ planned: rows.length,
116
+ observed,
117
+ missing: rows.length - observed,
118
+ succeeded,
119
+ successRate: rate(succeeded, rows.length),
120
+ knownCost,
121
+ totalCost: costsComplete ? knownCost : null,
122
+ costPerSuccess: costsComplete && succeeded ? knownCost / succeeded : null,
123
+ retries: rows.every((row) => row.retries !== null)
124
+ ? rows.reduce((sum, row) => sum + row.retries, 0)
125
+ : null,
126
+ manualRepairs: rows.every((row) => row.manualRepairs !== null)
127
+ ? rows.reduce((sum, row) => sum + row.manualRepairs, 0)
128
+ : null,
129
+ };
130
+ }
131
+
132
+ /** Read-only measurement. Declarations and local Eval files are not attestations. */
133
+ export function buildOutcomeReport(
134
+ { plan, history, observations = [], maintenance = null },
135
+ { now = Date.now(), expectedPlanDigest } = {},
136
+ ) {
137
+ const samples = validateOutcomePlan(plan);
138
+ assert(Number.isFinite(now), "invalid report time");
139
+ const planDigest = outcomeDigest(plan);
140
+ assert(
141
+ !expectedPlanDigest || expectedPlanDigest === planDigest,
142
+ "frozen plan digest mismatch",
143
+ );
144
+ const observed = uniqueIndex(observations, "sampleId", "observations");
145
+ for (const id of observed.keys())
146
+ assert(samples.has(id), "observation is outside the frozen plan");
147
+ const runs = uniqueIndex(history?.runs ?? [], "runId", "Eval history");
148
+ const issues = (history?.issues ?? []).map((issue) => issue.code);
149
+ if (epoch(plan.window.end) > now)
150
+ issues.push("observation_window_not_closed");
151
+ const usedEvidence = new Set();
152
+ const rows = [];
153
+ for (const sample of samples.values()) {
154
+ const observation = observed.get(sample.id);
155
+ const reasons = [];
156
+ const row = {
157
+ sampleId: sample.id,
158
+ kind: sample.kind,
159
+ taskId: sample.taskId,
160
+ stratum: sample.stratum,
161
+ observed: Boolean(observation),
162
+ succeeded: false,
163
+ reasons,
164
+ cost: null,
165
+ elapsedMs: null,
166
+ retries: null,
167
+ manualRepairs: null,
168
+ failureCause: null,
169
+ firstRunCompletedStages: [],
170
+ };
171
+ rows.push(row);
172
+ if (!observation) {
173
+ reasons.push("missing_observation");
174
+ issues.push(`${sample.id}:missing_observation`);
175
+ continue;
176
+ }
177
+ for (const key of ["cost", "elapsedMs", "retries", "manualRepairs"]) {
178
+ const valid = ["retries", "manualRepairs"].includes(key)
179
+ ? count(observation[key])
180
+ : nonnegative(observation[key]);
181
+ if (valid) row[key] = observation[key];
182
+ else reasons.push(`missing_or_invalid_${key}`);
183
+ }
184
+ const observedAt = epoch(observation.observedAt);
185
+ if (!(
186
+ observedAt <= Math.min(now, epoch(plan.window.end)) &&
187
+ observedAt - (row.elapsedMs ?? 0) >= epoch(plan.window.start)
188
+ ))
189
+ reasons.push("observation_outside_window");
190
+ const run = runs.get(observation.runId);
191
+ const stoppedBeforeTask =
192
+ sample.kind === "first-run" &&
193
+ observation.runId === null &&
194
+ observation.firstRun?.stages?.tool?.passed === false;
195
+ const evidenceKey = JSON.stringify([observation.runId, sample.taskId]);
196
+ if (observation.runId !== null) {
197
+ assert(
198
+ !usedEvidence.has(evidenceKey),
199
+ "a task execution cannot count as multiple samples",
200
+ );
201
+ usedEvidence.add(evidenceKey);
202
+ }
203
+ if (!run && !stoppedBeforeTask) reasons.push("missing_eval_run");
204
+ if (run) {
205
+ // Failed executions are valid observations, not successful outcomes.
206
+ // All other existing Eval integrity rules remain authoritative.
207
+ const integrity = evalHistoryRecordIssues(
208
+ run,
209
+ now,
210
+ Math.max(1, now - epoch(plan.window.start)),
211
+ ).filter((reason) => reason !== "execution_not_successful");
212
+ reasons.push(...integrity);
213
+ if (run.label !== plan.commitSha) reasons.push("commit_mismatch");
214
+ if (outcomeDigest(run.comparison) !== sample.comparisonDigest)
215
+ reasons.push("comparison_mismatch");
216
+ if (!(
217
+ epoch(run.ranAt) >= epoch(plan.window.start) &&
218
+ epoch(run.ranAt) <= epoch(plan.window.end)
219
+ ))
220
+ reasons.push("run_outside_window");
221
+ }
222
+ const result = run?.results?.find((item) => item?.id === sample.taskId);
223
+ if (!result && !stoppedBeforeTask) reasons.push("missing_task_result");
224
+ if (result && (!nonnegative(result.ms) || row.elapsedMs < result.ms))
225
+ reasons.push("invalid_elapsed_time");
226
+ if (sample.kind === "first-run") {
227
+ if (typeof observation.firstRun?.cleanEnvironment !== "boolean")
228
+ reasons.push("missing_clean_environment_evidence");
229
+ for (const stage of STAGES) {
230
+ const evidence = observation.firstRun?.stages?.[stage];
231
+ if (
232
+ !evidence ||
233
+ typeof evidence.passed !== "boolean" ||
234
+ !nonempty(evidence.receipt)
235
+ )
236
+ reasons.push(`missing_stage_evidence:${stage}`);
237
+ else if (evidence.passed) row.firstRunCompletedStages.push(stage);
238
+ }
239
+ // A later completed stage without its prerequisites is not a valid funnel.
240
+ if (
241
+ row.firstRunCompletedStages.some(
242
+ (stage, index) => stage !== STAGES[index],
243
+ )
244
+ )
245
+ reasons.push("inconsistent_first_run_stages");
246
+ }
247
+ for (const reason of reasons) issues.push(`${sample.id}:${reason}`);
248
+ const successfulExecution =
249
+ result?.pass === true &&
250
+ result.artifactCheckPassed === true &&
251
+ evalExecutionSucceeded(result) &&
252
+ result.executionEvidence.observedFallback === false;
253
+ if (!successfulExecution) reasons.push("task_not_successful");
254
+ if (row.elapsedMs > sample.timeBudgetMs || row.cost > sample.costBudget)
255
+ reasons.push("budget_exceeded");
256
+ if (row.manualRepairs > 0) reasons.push("manual_repair");
257
+ if (
258
+ sample.kind === "first-run" &&
259
+ (observation.firstRun?.cleanEnvironment !== true ||
260
+ row.firstRunCompletedStages.length !== STAGES.length)
261
+ )
262
+ reasons.push("first_run_not_completed");
263
+ row.succeeded = reasons.length === 0;
264
+ if (!row.succeeded) {
265
+ if (FAILURE_CAUSES.has(observation.failureCause))
266
+ row.failureCause = observation.failureCause;
267
+ else issues.push(`${sample.id}:missing_failure_cause`);
268
+ }
269
+ }
270
+ const categories = Object.fromEntries(
271
+ [...CATEGORIES].map((category) => [category, 0]),
272
+ );
273
+ let maintenanceComplete = false;
274
+ if (maintenance) {
275
+ const entries = uniqueIndex(
276
+ maintenance.entries,
277
+ "id",
278
+ "maintenance entries",
279
+ );
280
+ maintenanceComplete =
281
+ maintenance.complete === true &&
282
+ outcomeDigest(maintenance.window) === outcomeDigest(plan.window);
283
+ for (const entry of entries.values()) {
284
+ assert(
285
+ CATEGORIES.has(entry.category) &&
286
+ nonnegative(entry.hours) &&
287
+ nonempty(entry.evidenceRef),
288
+ "invalid maintenance entry",
289
+ );
290
+ categories[entry.category] += entry.hours;
291
+ }
292
+ }
293
+ if (!maintenanceComplete) issues.push("incomplete_maintenance_records");
294
+ const maintenanceHours = [...CATEGORIES]
295
+ .filter((category) => category !== "construction")
296
+ .reduce((sum, category) => sum + categories[category], 0);
297
+ const attempts = rows.filter((row) => row.observed).length;
298
+ const allObserved = rows.every((row) => row.observed);
299
+ const firstRuns = rows.filter((row) => row.kind === "first-run");
300
+ const tasks = rows.filter((row) => row.kind === "task");
301
+ if (!firstRuns.length || !tasks.length)
302
+ issues.push("missing_metric_population");
303
+ return {
304
+ schema: OUTCOME_REPORT_SCHEMA,
305
+ generatedAt: new Date(now).toISOString(),
306
+ scope: "local-outcome-baseline",
307
+ productionAttested: false,
308
+ status: issues.length ? "INSUFFICIENT_EVIDENCE" : "BASELINE_RECORDED",
309
+ // Neither a baseline nor operator declarations constitute an improvement gate.
310
+ improvementVerdict: "NOT_EVALUATED",
311
+ planDigest,
312
+ commitSha: plan.commitSha,
313
+ currency: plan.currency,
314
+ window: plan.window,
315
+ task: summarize(tasks),
316
+ firstRun: summarize(firstRuns),
317
+ maintenance: {
318
+ complete: maintenanceComplete,
319
+ knownHours: maintenanceHours,
320
+ totalHours: maintenanceComplete ? maintenanceHours : null,
321
+ per100Attempts:
322
+ maintenanceComplete && allObserved && attempts
323
+ ? (maintenanceHours / attempts) * 100
324
+ : null,
325
+ observedAttempts: attempts,
326
+ constructionHours: maintenanceComplete ? categories.construction : null,
327
+ categories,
328
+ },
329
+ groups: [
330
+ ...new Set(
331
+ rows.map((row) => JSON.stringify([row.kind, row.stratum, row.taskId])),
332
+ ),
333
+ ].map((key) => {
334
+ const [kind, stratum, taskId] = JSON.parse(key);
335
+ return {
336
+ kind,
337
+ stratum,
338
+ taskId,
339
+ ...summarize(
340
+ rows.filter(
341
+ (row) =>
342
+ row.kind === kind &&
343
+ row.stratum === stratum &&
344
+ row.taskId === taskId,
345
+ ),
346
+ ),
347
+ };
348
+ }),
349
+ firstRunFunnel: STAGES.map((stage, index) => ({
350
+ stage,
351
+ planned: firstRuns.length,
352
+ passed: firstRuns.filter((row) =>
353
+ STAGES.slice(0, index + 1).every((required) =>
354
+ row.firstRunCompletedStages.includes(required),
355
+ ),
356
+ ).length,
357
+ })),
358
+ failureCauses: [
359
+ ...new Set(
360
+ rows
361
+ .filter((row) => !row.succeeded)
362
+ .map((row) => row.failureCause || "unknown"),
363
+ ),
364
+ ].map((cause) => ({
365
+ cause,
366
+ count: rows.filter(
367
+ (row) => !row.succeeded && (row.failureCause || "unknown") === cause,
368
+ ).length,
369
+ })),
370
+ issues: [...new Set(issues)],
371
+ rows,
372
+ };
373
+ }
@@ -109,6 +109,8 @@ export async function runEvalSuite(tasks, opts = {}) {
109
109
  executionSucceeded: false,
110
110
  agentOk: false,
111
111
  executionEvidence: null,
112
+ usage: null,
113
+ totalCostUsd: null,
112
114
  ms: 0,
113
115
  detail: "",
114
116
  error: null,
@@ -153,6 +155,10 @@ export async function runEvalSuite(tasks, opts = {}) {
153
155
  (agentResult.error == null || agentResult.error === "");
154
156
  rec.agentOk = rec.executionSucceeded;
155
157
  rec.executionEvidence = agentResult?.executionEvidence || null;
158
+ rec.usage = agentResult?.usage || null;
159
+ rec.totalCostUsd = Number.isFinite(agentResult?.totalCostUsd)
160
+ ? agentResult.totalCostUsd
161
+ : null;
156
162
  if (agentResult?.evaluationMetrics !== undefined) {
157
163
  rec.evaluationMetrics = agentResult.evaluationMetrics;
158
164
  }
@@ -80,7 +80,7 @@ export function assessEvolutionDeploymentReadiness(
80
80
  : "no enabled signed Evolution deployment",
81
81
  disabled
82
82
  ? "review the saved signed deployment, then run cc evolution deployment enable"
83
- : "configure a signed descriptor and trust root with cc evolution deployment configure --descriptor <path> --trust-root <path>",
83
+ : "before production, run cc evolution deployment init-test --module <absolute-path>; otherwise configure a signed descriptor and trust root",
84
84
  );
85
85
  }
86
86
  if (missingCommands.length > 0) {
@@ -126,6 +126,10 @@ export async function getEvolutionDeploymentStatus(options = {}) {
126
126
  fromEnvironment || (saved.profile?.enabled ? saved.profile : null);
127
127
  const base = {
128
128
  source,
129
+ deploymentMode:
130
+ source === "environment"
131
+ ? "external"
132
+ : saved.profile?.deploymentMode || "none",
129
133
  effectiveEnabled: source !== "none",
130
134
  profileEnabled: saved.profile?.enabled === true,
131
135
  profilePath: saved.filePath,
@@ -183,6 +187,8 @@ export async function configureEvolutionDeployment(
183
187
  rootRotationPath = null,
184
188
  revocationPath = null,
185
189
  enabled = true,
190
+ deploymentMode,
191
+ testPrivateKeyPath,
186
192
  },
187
193
  options = {},
188
194
  ) {
@@ -239,6 +245,11 @@ export async function configureEvolutionDeployment(
239
245
  verified.descriptor.revision,
240
246
  ),
241
247
  };
248
+ const preserveTestMode =
249
+ deploymentMode === undefined &&
250
+ current?.deploymentMode === "test" &&
251
+ current.descriptorPath === verified.descriptorPath &&
252
+ current.trustRootPath === verified.trustRootPath;
242
253
  return {
243
254
  enabled: enabled === true,
244
255
  descriptorPath: verified.descriptorPath,
@@ -246,6 +257,10 @@ export async function configureEvolutionDeployment(
246
257
  revisionFloors,
247
258
  activeTrustRootDigest: verified.descriptor.trustRootDigest,
248
259
  revokedDescriptorRevisions,
260
+ deploymentMode: preserveTestMode ? "test" : deploymentMode || "managed",
261
+ testPrivateKeyPath: preserveTestMode
262
+ ? current.testPrivateKeyPath
263
+ : testPrivateKeyPath || null,
249
264
  };
250
265
  }, options);
251
266
  return getEvolutionDeploymentStatus(options);