@testmuai/kane-cli 0.8.15 → 0.8.16

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 (181) hide show
  1. package/dist/{ChatSurface-2GPR4S7I.js → ChatSurface-5JEEFY34.js} +1 -1
  2. package/dist/{ChromeProfilePicker-XAZGCJKR.js → ChromeProfilePicker-6IVAYCWJ.js} +1 -1
  3. package/dist/{CliFeedbackPrompt-4SILDU7S.js → CliFeedbackPrompt-K4IN7S6J.js} +1 -1
  4. package/dist/{CliUploadProgress-OAQBY55Y.js → CliUploadProgress-MI4H4LKT.js} +1 -1
  5. package/dist/{ConfigView-FDBMJC26.js → ConfigView-CJY5MB6H.js} +1 -1
  6. package/dist/{EvidenceViewOffer-YSNRKKPC.js → EvidenceViewOffer-ABKTGD4K.js} +1 -1
  7. package/dist/FolderPicker-RQIVS7ZR.js +2 -0
  8. package/dist/{InfoBox-ZPUBB7J4.js → InfoBox-RP6RDCG7.js} +1 -1
  9. package/dist/{LinksBox-MNNNOH23.js → LinksBox-QOQJ3S2I.js} +1 -1
  10. package/dist/{ProfilesView-GY5QCIT3.js → ProfilesView-BZEBT6R5.js} +1 -1
  11. package/dist/{ProjectPicker-UCHMCNFV.js → ProjectPicker-J42MEJRQ.js} +1 -1
  12. package/dist/{SaveSessionPrompt-ATVHKAHN.js → SaveSessionPrompt-MKAIUVX7.js} +1 -1
  13. package/dist/SingleShotApp-TZZ2J7ZO.js +2 -0
  14. package/dist/{SummaryBox-2DTNE25L.js → SummaryBox-JQJKGYDM.js} +1 -1
  15. package/dist/TestMdRunView-2YVGGFLU.js +2 -0
  16. package/dist/{TestrunEvidenceTable-6UE5EMON.js → TestrunEvidenceTable-FYDS3ZVU.js} +1 -1
  17. package/dist/{WhoamiView-TFCHIOW5.js → WhoamiView-F4PPB7SN.js} +1 -1
  18. package/dist/{app-download-N7MLJQ42.js → app-download-RA4CGTC5.js} +1 -1
  19. package/dist/{auth-IQPCVCZK.js → auth-TAT427C3.js} +1 -1
  20. package/dist/{binary-VML7EGV4.js → binary-OFPMBJ34.js} +1 -1
  21. package/dist/{bind-YV6V5AI6.js → bind-LY362KX7.js} +2 -2
  22. package/dist/{bootstrap-KCPWDBLX.js → bootstrap-RCDB5OWA.js} +1 -1
  23. package/dist/bridge-E2NGMJYM.js +2 -0
  24. package/dist/{changelog-CJFWGRIL.js → changelog-ZC3LHV2Z.js} +1 -1
  25. package/dist/{chunk-MLYNVJNH.js → chunk-23MVD7GY.js} +1 -1
  26. package/dist/{chunk-5HTSKF5K.js → chunk-2GWMENG5.js} +1 -1
  27. package/dist/{chunk-ORQGQSWG.js → chunk-3AVBUEBL.js} +2 -2
  28. package/dist/chunk-3LXN6AV5.js +5 -0
  29. package/dist/{chunk-EDQZIEPJ.js → chunk-3MVEGB2I.js} +1 -1
  30. package/dist/{chunk-FXO7JKMZ.js → chunk-4LVZLLTN.js} +3 -3
  31. package/dist/{chunk-3D5MKSG3.js → chunk-4PWYSDZR.js} +1 -1
  32. package/dist/{chunk-SIYSKT6I.js → chunk-4WEVTED6.js} +1 -1
  33. package/dist/{chunk-7EGIX6Y4.js → chunk-5ACSALRU.js} +3 -3
  34. package/dist/{chunk-WNB2IYHY.js → chunk-5VZAWKDF.js} +1 -1
  35. package/dist/{chunk-3GELV4IN.js → chunk-6HCY5LJO.js} +14 -14
  36. package/dist/{chunk-JFUFWICY.js → chunk-7P6FSGRD.js} +2 -2
  37. package/dist/{chunk-QXRT6HSV.js → chunk-7QUFOWMU.js} +1 -1
  38. package/dist/{chunk-KUS324VE.js → chunk-7XMDCGIZ.js} +1 -1
  39. package/dist/{chunk-EJXBKCNF.js → chunk-AAT4O22C.js} +1 -1
  40. package/dist/{chunk-DMCEGMGB.js → chunk-AGKE5WF3.js} +1 -1
  41. package/dist/{chunk-EPE2ELDH.js → chunk-BCJNIDS3.js} +1 -1
  42. package/dist/{chunk-6L5RV62W.js → chunk-BK42G6RI.js} +1 -1
  43. package/dist/{chunk-OWGFFJKK.js → chunk-BY2MU3ZS.js} +1 -1
  44. package/dist/{chunk-IAHOLH5W.js → chunk-C6JFTSIQ.js} +1 -1
  45. package/dist/{chunk-YAAQER2L.js → chunk-CDWUZ54U.js} +1 -1
  46. package/dist/{chunk-7WDPU33M.js → chunk-CR7UWQ76.js} +1 -1
  47. package/dist/{chunk-ZCSEBT2W.js → chunk-CVNHUDT4.js} +1 -1
  48. package/dist/{chunk-6DHEOPXX.js → chunk-DSWHEEHN.js} +1 -1
  49. package/dist/{chunk-UHSNUUX3.js → chunk-E44OHYDS.js} +2 -2
  50. package/dist/{chunk-RI4ILZZC.js → chunk-ECIGXPLN.js} +1 -1
  51. package/dist/{chunk-WFBJNVMQ.js → chunk-EMAKLNDV.js} +1 -1
  52. package/dist/{chunk-HYTBEPC2.js → chunk-F2XTOZTN.js} +1 -1
  53. package/dist/{chunk-XXE7W5AV.js → chunk-FQFVAFWK.js} +1 -1
  54. package/dist/{chunk-VZDLRJ5N.js → chunk-FWPRUGJJ.js} +1 -1
  55. package/dist/{chunk-GZ65ZA4C.js → chunk-FYJ62EVY.js} +1 -1
  56. package/dist/{chunk-74FHTDEE.js → chunk-G2ZMNVYN.js} +1 -1
  57. package/dist/{chunk-DMT3W26F.js → chunk-GCMJDOAE.js} +1 -1
  58. package/dist/{chunk-6GLFQHSW.js → chunk-GGD7NKPL.js} +2 -2
  59. package/dist/{chunk-Z73ZYROU.js → chunk-H6S7L2I2.js} +1 -1
  60. package/dist/{chunk-TVELOH5A.js → chunk-HBMNUT6E.js} +1 -1
  61. package/dist/{chunk-KALEPJAV.js → chunk-HYCOX7AB.js} +2 -2
  62. package/dist/{chunk-A557OSRS.js → chunk-ICUTARPB.js} +1 -1
  63. package/dist/{chunk-BMVE73M7.js → chunk-IJTSA34Q.js} +1 -1
  64. package/dist/chunk-IQDZ6YMY.js +18 -0
  65. package/dist/{chunk-OFWJBOGT.js → chunk-IYOPWIG4.js} +2 -2
  66. package/dist/{chunk-YGMUNNKH.js → chunk-IZ5CTC6M.js} +1 -1
  67. package/dist/{chunk-N3CVR4Z2.js → chunk-J2LWXO55.js} +1 -1
  68. package/dist/{chunk-TEHZUSUY.js → chunk-KPL2XHYF.js} +1 -1
  69. package/dist/{chunk-2WRBCTNM.js → chunk-KYZKPNPQ.js} +1 -1
  70. package/dist/chunk-L45HDSJ7.js +15 -0
  71. package/dist/{chunk-SHSXOYKT.js → chunk-MD3S2RXN.js} +1 -1
  72. package/dist/{chunk-JGAMMOUC.js → chunk-MU3I453X.js} +1 -1
  73. package/dist/{chunk-YZVR7ESF.js → chunk-MZYPDLD3.js} +1 -1
  74. package/dist/{chunk-JCMHB4KH.js → chunk-NADKZKGS.js} +1 -1
  75. package/dist/{chunk-W77SZLFC.js → chunk-NMBFAIXZ.js} +1 -1
  76. package/dist/{chunk-XSUJJB7Z.js → chunk-NN6UG2BE.js} +1 -1
  77. package/dist/chunk-NPKB7EK3.js +7 -0
  78. package/dist/{chunk-OGDAWNFY.js → chunk-O3ZKP4DY.js} +1 -1
  79. package/dist/{chunk-JL3L6KOG.js → chunk-OUWOLCCS.js} +1 -1
  80. package/dist/{chunk-Z3YYMZHT.js → chunk-OYY566GN.js} +1 -1
  81. package/dist/{chunk-AYJ2YZP5.js → chunk-PDTFQGQF.js} +1 -1
  82. package/dist/{chunk-HLCETZ73.js → chunk-Q7LZ5QJV.js} +1 -1
  83. package/dist/{chunk-T4R26WER.js → chunk-QMZLIHBS.js} +2 -2
  84. package/dist/chunk-QXUPBIV3.js +93 -0
  85. package/dist/{chunk-PGXJ275T.js → chunk-RCYYE6ED.js} +1 -1
  86. package/dist/{chunk-NLEA6NPU.js → chunk-SF5QPR6T.js} +1 -1
  87. package/dist/{chunk-4TMQTSIO.js → chunk-TBYYPGHF.js} +1 -1
  88. package/dist/{chunk-NUJVYAI4.js → chunk-TGBXIV7O.js} +1 -1
  89. package/dist/{chunk-Q77QO3PC.js → chunk-TWZ6NZWE.js} +4 -4
  90. package/dist/{chunk-CNPIJFZM.js → chunk-U466V5JN.js} +1 -1
  91. package/dist/{chunk-YKYKOV6U.js → chunk-U7BVK5IX.js} +1 -1
  92. package/dist/{chunk-NWNG5UWD.js → chunk-UAFCBZ3P.js} +1 -1
  93. package/dist/{chunk-7X4R6464.js → chunk-UEG4LJD6.js} +1 -1
  94. package/dist/{chunk-XUJXGE42.js → chunk-ULGFPKC7.js} +1 -1
  95. package/dist/{chunk-ZEVU2OT3.js → chunk-V4JR5JCK.js} +1 -1
  96. package/dist/{chunk-M36MOFJW.js → chunk-VATOIZYG.js} +1 -1
  97. package/dist/{chunk-27ERHOW3.js → chunk-VWOAEF7J.js} +1 -1
  98. package/dist/{chunk-GSDXZS4U.js → chunk-W4Y3PG7F.js} +1 -1
  99. package/dist/{chunk-R7QMZBBH.js → chunk-WECVT7WE.js} +1 -1
  100. package/dist/{chunk-UZIMYV5U.js → chunk-WML5KSGQ.js} +1 -1
  101. package/dist/{chunk-RQILLYSP.js → chunk-WPNNRMTP.js} +1 -1
  102. package/dist/{chunk-ZKCCG3GK.js → chunk-XGL3RSI5.js} +1 -1
  103. package/dist/{chunk-QVLYK5JL.js → chunk-Z2GDSCPS.js} +1 -1
  104. package/dist/{chunk-JVEZBJJ7.js → chunk-Z4KRSLAM.js} +1 -1
  105. package/dist/{chunk-D6GBOFK5.js → chunk-Z5DGFN7R.js} +1 -1
  106. package/dist/{chunk-LJGAXIDU.js → chunk-ZLIYWELJ.js} +1 -1
  107. package/dist/{chunk-EFTRH35G.js → chunk-ZYEFWJNZ.js} +1 -1
  108. package/dist/{config-UGCWZGH5.js → config-WETHR632.js} +1 -1
  109. package/dist/{cover-cmd-SWJ2NZUZ.js → cover-cmd-J3CTQT3R.js} +1 -1
  110. package/dist/{credentials-GWLYYRTL.js → credentials-RQPAP5KY.js} +1 -1
  111. package/dist/{deps-bundle-VNGC2UG6.js → deps-bundle-F47ZDYIM.js} +1 -1
  112. package/dist/{deps-resolve-YLCEU6I7.js → deps-resolve-URKD4QCB.js} +1 -1
  113. package/dist/{dispatch-OMQCT7WO.js → dispatch-KOZAJQDW.js} +1 -1
  114. package/dist/{doctor-B4Z6RPKQ.js → doctor-J44UKALC.js} +1 -1
  115. package/dist/{evidence-XJGXVLO5.js → evidence-KRNDKDCT.js} +1 -1
  116. package/dist/{evolve-cmd-QQQPPGL3.js → evolve-cmd-CEYGGIWA.js} +1 -1
  117. package/dist/{explain-cmd-XVE6Z67Q.js → explain-cmd-USGRZFBY.js} +1 -1
  118. package/dist/{extract-bind-7IDQS4QP.js → extract-bind-X4QRQX53.js} +2 -2
  119. package/dist/{extract-cmd-KIEOBRIT.js → extract-cmd-RKEE32FN.js} +1 -1
  120. package/dist/{gaps-cmd-RGIPUSIR.js → gaps-cmd-WL6P6YKS.js} +1 -1
  121. package/dist/{generate-headless-XGRIDD6O.js → generate-headless-LSQHOR3G.js} +2 -2
  122. package/dist/index.js +144 -144
  123. package/dist/{ingest-cmd-R5H5SF5K.js → ingest-cmd-TQ4ARSDE.js} +1 -1
  124. package/dist/install-47CRHVU6.js +2 -0
  125. package/dist/{interactive-bind-X5DVLRRW.js → interactive-bind-FPC4RYEW.js} +3 -3
  126. package/dist/{lifecycle-cmd-6R2PR2HM.js → lifecycle-cmd-DB5EFO2O.js} +1 -1
  127. package/dist/{list-cmd-QCIYKWYQ.js → list-cmd-UWGJRGKF.js} +1 -1
  128. package/dist/{list-commands-VRRCVWKO.js → list-commands-Q77CAQJ2.js} +1 -1
  129. package/dist/login-flow-RSNR5HY2.js +2 -0
  130. package/dist/{maintenance-cmd-GZ4EMT3V.js → maintenance-cmd-EJ2RAMWB.js} +1 -1
  131. package/dist/{mobile-prompts-CMIVWDHQ.js → mobile-prompts-PPPPKRS2.js} +1 -1
  132. package/dist/{objective-variable-gate-EEYJ6B3X.js → objective-variable-gate-BCKULIFQ.js} +1 -1
  133. package/dist/{open-provider-UFSCTIQQ.js → open-provider-XIGABCD3.js} +1 -1
  134. package/dist/{persist-recorded-session-JXL5E53A.js → persist-recorded-session-MK4HCDOY.js} +1 -1
  135. package/dist/{pipeline-RSCRNNPW.js → pipeline-XDWHEZ5S.js} +1 -1
  136. package/dist/prepare-target-NR3MTLLI.js +2 -0
  137. package/dist/{reconcile-cmd-4VRTUM2D.js → reconcile-cmd-VJPEY7YD.js} +1 -1
  138. package/dist/{reconcile-deps-ZCJ2QCK5.js → reconcile-deps-T5YX6HRG.js} +2 -2
  139. package/dist/{reconcile-engine-IVLZCYZB.js → reconcile-engine-GELPXSLV.js} +1 -1
  140. package/dist/{recording-banner-SRLPSTFP.js → recording-banner-3ET3PMSV.js} +1 -1
  141. package/dist/registry-3XMA4FOC.js +2 -0
  142. package/dist/{require-project-folder-SKEZMSN7.js → require-project-folder-ZLKONKKP.js} +1 -1
  143. package/dist/{resolve-run-intent-THC3EPAX.js → resolve-run-intent-3SXUS676.js} +1 -1
  144. package/dist/{resolver-2NUNLK7N.js → resolver-G7NGWACO.js} +1 -1
  145. package/dist/{review-cmd-BMJQZ6XJ.js → review-cmd-6DNGXV5E.js} +1 -1
  146. package/dist/{run-UDP5VPYS.js → run-MUVZVTTC.js} +1 -1
  147. package/dist/{run-TURFDLC6.js → run-UJLRTKTO.js} +1 -1
  148. package/dist/{run-test-md-MRYNFNPO.js → run-test-md-RI5RXVFU.js} +2 -2
  149. package/dist/{skill-installer-CVJ5VTEJ.js → skill-installer-CAO2NJZP.js} +1 -1
  150. package/dist/{spawner-7FUA3JXA.js → spawner-H6IDWY5U.js} +1 -1
  151. package/dist/{store-guard-XQ5MSUB2.js → store-guard-PIA2DYZX.js} +1 -1
  152. package/dist/{sync-cmd-5INKTZN2.js → sync-cmd-VFVTFIIJ.js} +1 -1
  153. package/dist/{sync-setup-4R54VRAO.js → sync-setup-R7BZDE24.js} +1 -1
  154. package/dist/tcg-generate-QADJKNYZ.js +2 -0
  155. package/dist/testmd-actions-EXSVQRHQ.js +2 -0
  156. package/dist/{testmd-sync-HYZI6NRM.js → testmd-sync-2CXNIPJ7.js} +1 -1
  157. package/dist/token-refresh-5TVNSL4U.js +2 -0
  158. package/dist/{validate-basic-OKLJLDML.js → validate-basic-MN5NDCT2.js} +1 -1
  159. package/dist/{variable-receipt-CMCDUJI2.js → variable-receipt-SIABUC74.js} +1 -1
  160. package/dist/{verdicts-EMCYGQWM.js → verdicts-ZXXBKTOZ.js} +1 -1
  161. package/dist/{version-check-4DQJBSXW.js → version-check-TDGK5REB.js} +1 -1
  162. package/dist/{view-cmd-P3XRFORJ.js → view-cmd-RLO7AP4X.js} +1 -1
  163. package/dist/{walk-session-MUGS6CZY.js → walk-session-ATWNUGHX.js} +1 -1
  164. package/dist/{with-telemetry-3T53GIQC.js → with-telemetry-CLSDKQAG.js} +1 -1
  165. package/package.json +11 -11
  166. package/dist/FolderPicker-XCTJ5447.js +0 -2
  167. package/dist/SingleShotApp-IPNZBFXB.js +0 -2
  168. package/dist/TestMdRunView-2FQIEI5W.js +0 -2
  169. package/dist/bridge-5UKX7YIO.js +0 -2
  170. package/dist/chunk-6K4FDYMH.js +0 -89
  171. package/dist/chunk-JQCOKL6U.js +0 -15
  172. package/dist/chunk-JSS22MFY.js +0 -17
  173. package/dist/chunk-O66WXOOC.js +0 -5
  174. package/dist/chunk-S4JUCBCT.js +0 -7
  175. package/dist/install-W3VPVPAQ.js +0 -2
  176. package/dist/login-flow-5HL2QYEL.js +0 -2
  177. package/dist/prepare-target-XZ3FTVBW.js +0 -2
  178. package/dist/registry-CPQHW2L2.js +0 -2
  179. package/dist/tcg-generate-2BOPGRM6.js +0 -2
  180. package/dist/testmd-actions-2CPJZAC2.js +0 -2
  181. package/dist/token-refresh-NTE4LQRN.js +0 -2
package/dist/index.js CHANGED
@@ -1,137 +1,137 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
3
- import{b as es,c as ct,d as B}from"./chunk-ZUZ6QJRA.js";import{c as gn}from"./chunk-ZCSEBT2W.js";import{a as Io,b as Co,c as Mo,d as zi,e as Xi,f as Zi}from"./chunk-3GELV4IN.js";import"./chunk-3MSXQU2C.js";import"./chunk-ZEVU2OT3.js";import"./chunk-EFTRH35G.js";import"./chunk-2WRBCTNM.js";import{a as fs,b as gs}from"./chunk-ULGZPRKU.js";import{b as hs}from"./chunk-N3CVR4Z2.js";import{a as as,b as cs,c as ls,d as ds,e as us,f as ms,g as ps,h as vs}from"./chunk-RI4ILZZC.js";import{b as bs}from"./chunk-QXRT6HSV.js";import{a as ts,b as ns,c as rs,d as os,e as is,f as ss,h as hn}from"./chunk-EDQZIEPJ.js";import{f as sr,g as ar,i as ws}from"./chunk-JFUFWICY.js";import"./chunk-XUJXGE42.js";import{a as Qi,d as fn}from"./chunk-D6GBOFK5.js";import{a as ae}from"./chunk-3D5MKSG3.js";import{a as ki}from"./chunk-SIYSKT6I.js";import{A as Ni,B as tr,C as nr,D as rr,E as ji,F as Fi,G as Li,H as Vi,J as pn,K as qi,L as ir,a as it,b as Xn,c as Qn,d as No,e as jo,f as Fo,g as Ko,h as li,i as di,j as ui,k as mi,l as pi,m as fi,n as un,o as Si,p as Ii,q as Ci,r as _i,s as Ei,t as Ri,u as Ti,v as Ai,w as Di,x as $i,y as Mi,z as Oi}from"./chunk-6K4FDYMH.js";import"./chunk-S4JUCBCT.js";import{o as or,p as Gi}from"./chunk-UHSNUUX3.js";import"./chunk-YZVR7ESF.js";import{c as Hi}from"./chunk-H6TNBKGR.js";import"./chunk-66MOZKD2.js";import"./chunk-YLQHY4A7.js";import{a as gi,b as hi}from"./chunk-OFWJBOGT.js";import{b as bi}from"./chunk-KALEPJAV.js";import{a as Ot,b as Ue}from"./chunk-7X4R6464.js";import"./chunk-WD52ZNQY.js";import"./chunk-UZIMYV5U.js";import"./chunk-HLCETZ73.js";import"./chunk-4TMQTSIO.js";import"./chunk-RQILLYSP.js";import{d as xi}from"./chunk-BHSHGWBL.js";import"./chunk-S3DAAAE5.js";import{b as Pi}from"./chunk-WNB2IYHY.js";import"./chunk-O66WXOOC.js";import"./chunk-PDXZROJM.js";import{b as Nt,c as mn}from"./chunk-XSUJJB7Z.js";import{b as Ui,c as Bi,e as Ki,g as Ji,i as Wi,k as Yi}from"./chunk-JVEZBJJ7.js";import"./chunk-ZKCCG3GK.js";import{G as ai,H as ci,I as kt,O as ln,e as Ee,h as qo,l as Xo,o as Qo,p as Zo,q as ei,r as ti,s as sn,x as ni,y as ri,z as oi}from"./chunk-7EGIX6Y4.js";import"./chunk-GSDXZS4U.js";import"./chunk-7O54QURK.js";import{b as Pe,c as yt,d as zo}from"./chunk-5GUD3CIH.js";import{c as an,d as cn}from"./chunk-VOTIGXQ4.js";import"./chunk-YMLC55J4.js";import{a as bt,b as wt,d as on,e as er}from"./chunk-EHN5HTUD.js";import"./chunk-SWTJMTBY.js";import"./chunk-IE3OO5GI.js";import{a as Ye}from"./chunk-CH273NAE.js";import{a as vi}from"./chunk-JGAMMOUC.js";import"./chunk-AYJ2YZP5.js";import"./chunk-YAAQER2L.js";import{c as Mt}from"./chunk-JSS22MFY.js";import{e as _o,f as Eo,h as zn}from"./chunk-27ERHOW3.js";import{a as wi}from"./chunk-R7QMZBBH.js";import{b as Ae,r as at}from"./chunk-JQCOKL6U.js";import"./chunk-NBXYL2JT.js";import"./chunk-CAOZKSQ3.js";import{a as tn,b as vt,c as qn}from"./chunk-VZ7KXRXB.js";import{a as to,b as no,c as ro,d as Zn,e as dn,f as yi}from"./chunk-JCMHB4KH.js";import{a as Jo,b as Wo,c as Yo,d as Ho,e as Go}from"./chunk-Z3YYMZHT.js";import{a as Lo,c as Vo,d as Uo,e as Bo}from"./chunk-JL3L6KOG.js";import{a as eo}from"./chunk-5HTSKF5K.js";import"./chunk-5Y2G4NC7.js";import"./chunk-P7YZ3PU3.js";import"./chunk-TDPWFYTJ.js";import{a as Te}from"./chunk-MLYNVJNH.js";import"./chunk-KUS324VE.js";import"./chunk-4PMZ5FCD.js";import"./chunk-KBM3XHAM.js";import{a as Oo}from"./chunk-2YEHV2CX.js";import"./chunk-5LJRZI7S.js";import"./chunk-BKM2LWU2.js";import"./chunk-SHSXOYKT.js";import{C as si}from"./chunk-GP7WD4UY.js";import"./chunk-JQW2QFSX.js";import{k as ii}from"./chunk-3N6IAVD5.js";import"./chunk-FQNQVC5O.js";import"./chunk-AKX4VRRR.js";import"./chunk-UD7KKHPW.js";import{c as wo,d as yo,e as ko,i as xo,m as So}from"./chunk-NLEA6NPU.js";import"./chunk-6L5RV62W.js";import"./chunk-Z73ZYROU.js";import"./chunk-OWGFFJKK.js";import"./chunk-YCCUBQY4.js";import"./chunk-TVELOH5A.js";import{a as To,b as Po,f as Ao,g as Do,h as rn}from"./chunk-NUJVYAI4.js";import{a as en}from"./chunk-BPMSNGXQ.js";import{a as nn,b as st,c as Ro}from"./chunk-VE3SUJMA.js";import{a as $o}from"./chunk-OGDAWNFY.js";import"./chunk-RFHMDQXZ.js";import{a as ao,b as co,d as lo}from"./chunk-QVLYK5JL.js";import{e as so}from"./chunk-A557OSRS.js";import{a as io}from"./chunk-MMBBQ4OZ.js";import{j as zt}from"./chunk-6GLFQHSW.js";import"./chunk-MSGW4JDG.js";import{a as Xt,b as Qt,c as Zt}from"./chunk-TZXXJWHA.js";import{f as uo,j as mo,k as po,n as ht,o as fo,p as Hn,q as go,r as y,s as Dt,t as ho,u as Gn,v as vo}from"./chunk-RSSOJ3L2.js";import"./chunk-5EOX4MEY.js";import{b as $t}from"./chunk-IAHOLH5W.js";import{h as bo}from"./chunk-TAOHYWEO.js";import"./chunk-WFBJNVMQ.js";import"./chunk-EJXBKCNF.js";import"./chunk-YKYKOV6U.js";import{a as oo}from"./chunk-Z7S3IWUX.js";import"./chunk-4JOD47QI.js";import"./chunk-74FHTDEE.js";import"./chunk-TEHZUSUY.js";import{a as re}from"./chunk-EPE2ELDH.js";import{a as gt}from"./chunk-DHJSM5DT.js";import{a as Yn}from"./chunk-NLCCBXXV.js";import"./chunk-RZ4F3BHX.js";import"./chunk-E47GFYXA.js";import{c as Gt}from"./chunk-EYOCNMUM.js";import{a as le}from"./chunk-NWNG5UWD.js";import"./chunk-YGMUNNKH.js";import"./chunk-XXE7W5AV.js";import{a as he,b as q,i as Zr,j as Jn,p as Wn,y as G}from"./chunk-HYTBEPC2.js";import{a as ot,b as qt}from"./chunk-DFS4RMVP.js";import{a as ft}from"./chunk-HCBYKLMW.js";import{a as se,b as H,c as rt,i as Kn,j as Ht}from"./chunk-C44QQJR4.js";import{a as At}from"./chunk-6YGTRKDT.js";import{e as Ne}from"./chunk-UR6MHSHU.js";var Jt=Ne(At(),1);import de from"process";import*as Qc from"tls";function ys(){let e=Qc;if(!(typeof e.getCACertificates!="function"||typeof e.setDefaultCACertificates!="function"))try{let t=o=>typeof o=="string",r=e.getCACertificates("default").filter(t),i=e.getCACertificates("system").filter(t);e.setDefaultCACertificates([...new Set([...r,...i])])}catch{}}var ks=!1;function xs(){if(!ks)try{if(typeof process.emitWarning!="function")return;let e=process.emitWarning.bind(process),t=((r,...i)=>{let o=typeof r=="string"?r:r?.message??"";if(!((typeof i[0]=="string"?i[0]:typeof r=="object"&&r?r.name:void 0)==="ExperimentalWarning"&&o.includes("buffer.File")))return e(r,...i)});process.emitWarning=t,ks=!0}catch{}}import{basename as Lu,join as De,resolve as Vu}from"path";var $r=Ne(At(),1);var Ie=Ne(At(),1);var ze=Ne(ft(),1);function Ss({steps:e,bifurcationInfo:t,perFlowMetadata:r}){return!t||t.isSingleFlow||!r||r.length<=1?null:(0,ze.jsx)(se,{flexDirection:"column",children:r.map((i,o)=>{let n=e[o],c=n?.children??[],s=c.filter(g=>g.status==="passed").length,a=c.filter(g=>g.status==="failed").length,d=s+a,l=c.reduce((g,u)=>g+(u.duration??0),0),m=n?.status==="failed"?"failed":"passed",p=t.flows[o]??n?.objective??`Flow ${o+1}`;return(0,ze.jsxs)(se,{flexDirection:"column",marginTop:o>0?1:0,children:[(0,ze.jsxs)(se,{marginLeft:1,children:[(0,ze.jsx)(H,{color:G.purple,bold:!0,children:"Flow "+(o+1)+": "}),(0,ze.jsx)(H,{color:G.purple,children:p})]}),(0,ze.jsx)(dn,{status:m,summary:i?.summary??"",duration:l,steps:d,stepsPassed:s,stepsFailed:a,reason:i?.error_message??void 0,creditsConsumed:i?.credits_consumed??void 0})]},`flow-summary-${o}`)})})}var ce=Ne(ft(),1);function Is({config:e,spawnOpts:t,cancelRef:r,banner:i,describeContext:o,onComplete:n,onStepEnd:c,onReasoning:s,onStepComplete:a}){let{exit:d}=Ht(),{append:l}=qt(),{describe:m,onDescribe:p,creditsRef:g}=zi({resolve:()=>o??null,hostIsTTY:()=>!!process.stderr.isTTY}),u=Go(c,void 0,s,a,p),v=(0,Ie.useRef)(!1),k=(0,Ie.useRef)(!1),[R,S]=(0,Ie.useState)("");(0,Ie.useEffect)(()=>{v.current||(v.current=!0,u.startRun(e,t))},[e,t,u]),(0,Ie.useEffect)(()=>{r&&(r.current=()=>u.cancelRun())},[r,u]),(0,Ie.useEffect)(()=>{u.isRunning||m.stop()},[u.isRunning,m.stop]);let w=(0,Ie.useRef)(0);Kn((x,h)=>{h.ctrl&&x==="c"&&(u.isRunning?(w.current++,w.current>=2?d():u.cancelRun()):d())}),Kn((x,h)=>{u.askingUser&&(h.return?(u.sendAnswer(R),S("")):h.backspace||h.delete?S(P=>P.slice(0,-1)):x&&!h.ctrl&&!h.meta&&S(P=>P+x))},{isActive:!!u.askingUser}),(0,Ie.useEffect)(()=>{if(!u.isRunning&&u.lastRunEnd&&!k.current){k.current=!0;let{passed:x,failed:h,total:P}=Zn(u.steps),N=u.bifurcationInfo;n({lastRunEnd:u.lastRunEnd,stepsPassed:x,stepsFailed:h,stepsTotal:P,hadError:!1,bifurcationFlows:N&&!N.isSingleFlow?N.flows:null,describeCredits:g.current,evidence:u.getEvidenceState()}),u.shutdownRunner().finally(()=>d())}},[u.isRunning,u.lastRunEnd,u.steps,u.shutdownRunner,n,d]),(0,Ie.useEffect)(()=>{u.runError&&!u.isRunning&&!k.current&&(k.current=!0,n({lastRunEnd:null,stepsPassed:0,stepsFailed:0,stepsTotal:0,hadError:!0,bifurcationFlows:null,describeCredits:g.current,evidence:u.getEvidenceState()}),u.shutdownRunner().finally(()=>d()))},[u.runError,u.isRunning,u.shutdownRunner,n,d]);let I=u.lastRunEnd?(()=>{let{passed:x,failed:h,total:P}=Zn(u.steps);return{status:u.lastRunEnd.status,duration:u.lastRunEnd.duration??0,summary:u.lastRunEnd.summary??"",stepsPassed:x,stepsFailed:h,stepsTotal:P,reason:u.lastRunEnd.reason,finalState:u.lastRunEnd.final_state,creditsConsumed:(u.lastRunEnd.credits_consumed??0)+g.current}})():null,f=(0,Ie.useRef)(!1);return(0,Ie.useEffect)(()=>{f.current||!i||(f.current=!0,l((0,ce.jsxs)(se,{flexDirection:"column",marginBottom:1,children:[(0,ce.jsxs)(se,{borderStyle:"round",borderColor:"#dc4e08",paddingX:2,children:[(0,ce.jsx)(H,{color:"#ff9500",bold:!0,children:"KaneAI CLI"}),(0,ce.jsx)(H,{color:G.dim,children:" \u2502 "}),(0,ce.jsx)(H,{color:G.orange,children:i.model}),(0,ce.jsx)(H,{color:G.dim,children:" \u2502 "}),(0,ce.jsx)(H,{color:G.dim,children:i.auth})]}),i.status?.map((x,h)=>(0,ce.jsx)(H,{color:G.dim,children:x},h))]})))},[]),(0,ce.jsxs)(se,{flexDirection:"column",children:[(()=>{let x=ro({isRunning:u.isRunning,bifurcationInfo:u.bifurcationInfo,steps:u.steps,cmInitCounts:u.cmInitCounts,replayInfo:u.replayInfo});return x?(0,ce.jsx)(no,{label:x.label,hasBifurcation:x.hasBifurcation}):null})(),u.steps.length>0&&(0,ce.jsx)(to,{steps:u.steps,bifurcated:!!u.bifurcationInfo&&!u.bifurcationInfo.isSingleFlow,flows:u.bifurcationInfo?.flows,cmInitCounts:u.cmInitCounts,staticSteps:!0,onStepCommit:l,describe:m.text,describeVisible:m.visible,describeRevealing:m.revealing}),u.askingUser&&(0,ce.jsxs)(se,{flexDirection:"column",marginTop:1,children:[(0,ce.jsxs)(H,{color:G.orange,children:['Agent is asking: "',u.askingUser,'"']}),(0,ce.jsxs)(H,{children:["> ",R,"\u2588"]})]}),u.runError&&(0,ce.jsx)(yi,{message:u.runError,code:"RUNNER_ERROR"}),I&&u.lastRunEnd&&(0,ce.jsx)(Ss,{steps:u.steps,bifurcationInfo:u.bifurcationInfo,perFlowMetadata:u.lastRunEnd.per_flow_metadata??[]}),I&&(0,ce.jsx)(dn,{status:I.status==="passed"?"passed":"failed",summary:I.summary??"",duration:I.duration,steps:I.stepsTotal,stepsPassed:I.stepsPassed,stepsFailed:I.stepsFailed,reason:I.reason,creditsConsumed:I.creditsConsumed})]})}import{createInterface as Zc}from"readline";function lt(e){process.stdout.write(JSON.stringify(e)+`
4
- `)}async function Cs(e,t,r){let i=Lo();if(!i)throw new Error("v16-runner not found. Build the binary with `cd v16-runner && python build.py` or ensure Python is available.");let o=Uo({environment:t?.environment,mode:t?.mode,assertionMode:t?.assertionMode,finalValidation:t?.finalValidation,username:e.username,accessKey:e.access_key,sessionId:e.session_id});e.device?.platform&&await Vo(o,e.device);let n=new Jo({env:o,runner:i,log:t?.log,sessionId:e.session_id}),c={...Wo(e),headless:e.headless??!1},s={...e};delete s.run_id;let a=r?.kind??"author";a==="evaluate"&&delete s.objective,Bo(s,{environment:t?.environment});let d=`run-${e.run_index}`;fn().then(I=>{I&&lt({type:"update_available",current:I.current,latest:I.latest,severity:I.severity})}).catch(()=>{}),gn().then(I=>{I&&lt({type:"skill_update_available",current:I.current,latest:I.latestCompatible,install_cmd:"kane-cli install skill"})}).catch(()=>{});let l=Zc({input:process.stdin});l.on("line",I=>{try{let f=JSON.parse(I);f.type==="user_response"?n.sendUserResponse(f.answer??""):f.type==="cancel"&&n.cancel(d)}catch{}}),await n.start(c);let m=null,p=!1,g=0,u=null,v=0,k=!1,R=Yo(),S=!1,w;r?.timeoutSeconds&&r.timeoutSeconds>0&&(w=setTimeout(()=>{S=!0,r.onTimeout?.(),n.kill()},r.timeoutSeconds*1e3));try{for await(let I of n.run(d,a,s))switch(R=Ho(R,I),I.type){case"run_start":k&&v++;break;case"step_start":{let f=I;r?.onStepLog?.("STEP_START",`Step ${f.index} started`,{index:f.index,objective:f.objective,child_id:f.child_id});let x={step:f.index+1,status:"running",remark:f.objective??`Step ${f.index+1}`};f.child_id&&(x.child_id=f.child_id),lt(x);break}case"step_event":I.event==="reasoning"&&I.detail&&I.detail!=="reasoning"&&r?.onReasoning?.(I.detail),r?.onStepLog?.("STEP_EVENT",`Step ${I.index} ${I.event}`,{index:I.index,phase:I.event,action_type:I.action_type,detail:I.detail,child_id:I.child_id});break;case"step_end":{let f=I;r?.onStepLog?.("STEP_END",`Step ${f.index} ${f.status}`,{index:f.index,status:f.status,duration:f.duration,summary:f.summary,child_id:f.child_id}),r?.onStepComplete?.(),g++;let x={step:f.index+1,status:f.status==="passed"?"done":"failed",remark:f.summary??""};f.child_id&&(x.child_id=f.child_id),lt(x);let h=k?Math.max(0,v-1):0,P=typeof f.ordinal=="number"&&f.id?{ordinal:f.ordinal,id:f.id}:void 0;r?.onStepEnd?.(f.index,h,f.child_id,P);break}case"bifurcation":{let f=I,x=f.flows??[],h=f.count??x.length;(f.is_single_flow??h<=1)||(u=x,k=!0,v=0),lt({type:"bifurcation",flows:x,count:h});break}case"ask_user":{let f=I;lt({type:"ask_user",question:f.question,step_index:f.step_index,...f.options?{options:f.options}:{}});break}case"run_end":{m=I;break}case"error":{p=!0,lt({type:"error",message:I.message});break}default:break}}catch(I){if(!S)throw I}finally{w&&clearTimeout(w)}return l.close(),await n.shutdown(),{lastRunEnd:m,stepsTotal:g,hadError:p,timedOut:S,bifurcationFlows:u,evidence:R}}function el(e){if(e.conditions.length===0)return xt("--analyzer-only needs at least one --condition");if(e.objective!==void 0&&e.objective!=="")return xt("a positional objective is not accepted with --analyzer-only; pass each condition via --condition");if(!e.agent&&e.isTTY)return xt("--analyzer-only requires --agent or a non-TTY stdin (it emits NDJSON, never a UI)");let t=e.conditions.findIndex(o=>o.trim()==="");if(t!==-1)return xt(`--condition #${t+1} is blank`);let r=e.conditions.findIndex(o=>/[\r\n]/.test(o));if(r!==-1)return xt(`--condition #${r+1} spans more than one line`);let i=[];return e.codeExport&&i.push("--code-export"),e.name&&i.push("--name"),e.target&&e.target!=="desktop"&&i.push(`--target ${e.target}`),e.app&&i.push("--app"),e.deviceName&&i.push("--device-name"),e.osVersion&&i.push("--os-version"),i.length?xt(`--analyzer-only does not accept ${i.join(", ")}: it judges the current web page and saves nothing`):{ok:!0}}function _s(e){if(!e.analyzerOnly)return e.conditions.length>0?"--condition requires --analyzer-only":e.objective?null:"missing required argument 'objective'";let t=el(e);return t.ok?null:t.message}function Es(){return{agent:!0,local:!0,allowMissingUrl:!0,target:"desktop"}}function Rs(e){let t=[];return e.url&&t.push("--url"),e.maxSteps!==void 0&&e.maxSteps!=="50"&&t.push("--max-steps"),e.mode&&t.push("--mode"),e.finalValidation&&t.push("--final-validation"),e.taskSkills&&t.push("--task-skills"),e.bugDetection&&t.push("--bug-detection"),t}var Ts=`
5
- `;function Ps(e){return e.join(Ts)}function As(e,t){let r=e.split(Ts);if(r.length!==t)throw new Error(`expected ${t} condition(s) after variable transform, got ${r.length}`);return r}function Ds(e,t){let r=e.reason??"";if(r.includes("Cancel")||r.includes("Timeout"))return 3;let i=e.condition_results??[];return i.length===t&&i.every(n=>typeof n=="boolean")?0:1}function xt(e){return{ok:!1,message:e}}function $s(e){return!!(e.target||e.deviceName||e.osVersion||e.app||e.cdpEndpoint||e.wsEndpoint||e.cft||e.url)}function Ms(e){return e.kind!=="mismatch"?null:e.suggested==="mobile"?"classification: objective looks mobile; run stays on web \u2014 pass --target emulator|simulator to run on a device":"classification: objective looks web; run stays on the device \u2014 pass --target desktop to run on web"}var Os=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function vn(e=process.stderr){if(!e.isTTY)return{onProgress:i=>e.write(`${i}
6
- `),done:()=>{}};let t=0,r=!1;return{onProgress:i=>{r=!0,t=(t+1)%Os.length,e.write(`\r\x1B[2K${Os[t]} ${i}`)},done:()=>{r&&e.write(`
7
- `),r=!1}}}var Ns=["emulator","simulator"];function js(e){e.command("doctor").description("Check the mobile tooling this machine needs for one target: emulator or simulator").option("--target <target>","Which toolchain to check: emulator | simulator (required)").option("--install","Download or repair the managed deps bundle for that target").action(async t=>{if(!t.target){process.stderr.write(["error: --target is required \u2014 say which toolchain to check."," kane-cli doctor --target emulator"," kane-cli doctor --target simulator"].join(`
3
+ import{b as oi,c as ct,d as J}from"./chunk-ZUZ6QJRA.js";import{c as bn}from"./chunk-CVNHUDT4.js";import{a as Eo,b as Ro,c as jo,d as ei,e as ti,f as ri}from"./chunk-6HCY5LJO.js";import"./chunk-3MSXQU2C.js";import"./chunk-V4JR5JCK.js";import"./chunk-ZYEFWJNZ.js";import"./chunk-KYZKPNPQ.js";import{a as bi,b as wi}from"./chunk-ULGZPRKU.js";import{b as yi}from"./chunk-J2LWXO55.js";import{a as ui,b as mi,c as pi,d as fi,e as gi,f as hi,g as vi,h as ki}from"./chunk-ECIGXPLN.js";import{b as xi}from"./chunk-7QUFOWMU.js";import{a as si,b as ii,c as ai,d as ci,e as li,f as di,h as wn}from"./chunk-3MVEGB2I.js";import{f as dr,g as ur,i as Si}from"./chunk-7P6FSGRD.js";import"./chunk-ULGFPKC7.js";import{a as ni,d as vn}from"./chunk-Z5DGFN7R.js";import{a as le}from"./chunk-4PWYSDZR.js";import{a as Is}from"./chunk-4WEVTED6.js";import{A as Vs,B as sr,C as ir,D as ar,E as Us,F as Bs,G as Ks,H as Js,J as hn,K as Zs,L as lr,a as st,b as tr,c as nr,d as Lo,e as Vo,f as Uo,g as Yo,h as ms,i as ps,j as fs,k as gs,l as hs,m as vs,n as fn,o as Es,p as Rs,q as Ts,r as Ps,s as As,t as Ds,u as $s,v as Os,w as Ns,x as js,y as Fs,z as Ls}from"./chunk-QXUPBIV3.js";import"./chunk-NPKB7EK3.js";import{o as cr,p as Qs}from"./chunk-E44OHYDS.js";import"./chunk-MZYPDLD3.js";import{c as Xs}from"./chunk-H6TNBKGR.js";import"./chunk-66MOZKD2.js";import"./chunk-YLQHY4A7.js";import{a as bs,b as ws}from"./chunk-IYOPWIG4.js";import{b as ks}from"./chunk-HYCOX7AB.js";import{a as Ot,b as Be}from"./chunk-UEG4LJD6.js";import"./chunk-WD52ZNQY.js";import"./chunk-WML5KSGQ.js";import"./chunk-Q7LZ5QJV.js";import"./chunk-TBYYPGHF.js";import"./chunk-WPNNRMTP.js";import{d as _s}from"./chunk-BHSHGWBL.js";import"./chunk-S3DAAAE5.js";import{b as Ms}from"./chunk-5VZAWKDF.js";import"./chunk-3LXN6AV5.js";import"./chunk-PDXZROJM.js";import{b as Nt,c as gn}from"./chunk-NN6UG2BE.js";import{b as Ws,c as Ys,e as Hs,g as Gs,i as qs,k as zs}from"./chunk-Z4KRSLAM.js";import"./chunk-XGL3RSI5.js";import{G as ds,H as us,I as kt,O as mn,e as Re,h as Qo,l as es,o as ts,p as ns,q as rs,r as os,s as ln,x as ss,y as is,z as as}from"./chunk-5ACSALRU.js";import"./chunk-W4Y3PG7F.js";import"./chunk-7O54QURK.js";import{b as De,c as yt,d as Zo}from"./chunk-5GUD3CIH.js";import{c as dn,d as un}from"./chunk-VOTIGXQ4.js";import"./chunk-YMLC55J4.js";import{a as bt,b as wt,d as cn,e as or}from"./chunk-EHN5HTUD.js";import"./chunk-SWTJMTBY.js";import"./chunk-IE3OO5GI.js";import{a as He}from"./chunk-CH273NAE.js";import{a as ys}from"./chunk-MU3I453X.js";import"./chunk-PDTFQGQF.js";import"./chunk-CDWUZ54U.js";import{c as rn,d as on,e as Mt}from"./chunk-IQDZ6YMY.js";import{e as To,f as Po,h as er}from"./chunk-VWOAEF7J.js";import{a as Ss}from"./chunk-WECVT7WE.js";import{b as $e,n as xs,t as at}from"./chunk-L45HDSJ7.js";import"./chunk-NBXYL2JT.js";import"./chunk-CAOZKSQ3.js";import{a as nn,b as vt,c as Zn}from"./chunk-VZ7KXRXB.js";import{a as oo,b as so,c as io,d as rr,e as pn,f as Cs}from"./chunk-NADKZKGS.js";import{a as Ho,b as Go,c as qo,d as zo,e as Xo}from"./chunk-OYY566GN.js";import{a as Bo,c as Ko,d as Jo,e as Wo}from"./chunk-OUWOLCCS.js";import{a as ro}from"./chunk-2GWMENG5.js";import"./chunk-5Y2G4NC7.js";import"./chunk-P7YZ3PU3.js";import"./chunk-TDPWFYTJ.js";import{a as Ae}from"./chunk-23MVD7GY.js";import"./chunk-7XMDCGIZ.js";import"./chunk-4PMZ5FCD.js";import"./chunk-KBM3XHAM.js";import{a as Fo}from"./chunk-2YEHV2CX.js";import"./chunk-5LJRZI7S.js";import"./chunk-BKM2LWU2.js";import"./chunk-MD3S2RXN.js";import{C as ls}from"./chunk-GP7WD4UY.js";import"./chunk-JQW2QFSX.js";import{k as cs}from"./chunk-3N6IAVD5.js";import"./chunk-FQNQVC5O.js";import"./chunk-AKX4VRRR.js";import"./chunk-UD7KKHPW.js";import{c as xo,d as So,e as Co,i as Io,m as _o}from"./chunk-SF5QPR6T.js";import"./chunk-BK42G6RI.js";import"./chunk-H6S7L2I2.js";import"./chunk-BY2MU3ZS.js";import"./chunk-YCCUBQY4.js";import"./chunk-HBMNUT6E.js";import{a as Do,b as $o,f as Mo,g as Oo,h as an}from"./chunk-TGBXIV7O.js";import{a as tn}from"./chunk-BPMSNGXQ.js";import{a as sn,b as it,c as Ao}from"./chunk-VE3SUJMA.js";import{a as No}from"./chunk-O3ZKP4DY.js";import"./chunk-RFHMDQXZ.js";import{a as uo,b as mo,d as po}from"./chunk-Z2GDSCPS.js";import{e as lo}from"./chunk-ICUTARPB.js";import{a as co}from"./chunk-MMBBQ4OZ.js";import{j as Xt}from"./chunk-GGD7NKPL.js";import"./chunk-MSGW4JDG.js";import{a as Qt,b as Zt,c as en}from"./chunk-TZXXJWHA.js";import{f as fo,j as go,k as ho,n as ht,o as vo,p as Xn,q as bo,r as y,s as Dt,t as wo,u as Qn,v as yo}from"./chunk-RSSOJ3L2.js";import"./chunk-5EOX4MEY.js";import{b as $t}from"./chunk-C6JFTSIQ.js";import{h as ko}from"./chunk-TAOHYWEO.js";import"./chunk-EMAKLNDV.js";import"./chunk-AAT4O22C.js";import"./chunk-U7BVK5IX.js";import{a as ao}from"./chunk-Z7S3IWUX.js";import"./chunk-4JOD47QI.js";import"./chunk-G2ZMNVYN.js";import"./chunk-KPL2XHYF.js";import{a as oe}from"./chunk-BCJNIDS3.js";import{a as gt}from"./chunk-DHJSM5DT.js";import{a as zn}from"./chunk-NLCCBXXV.js";import"./chunk-RZ4F3BHX.js";import"./chunk-E47GFYXA.js";import{c as qt}from"./chunk-EYOCNMUM.js";import{a as me}from"./chunk-UAFCBZ3P.js";import"./chunk-IZ5CTC6M.js";import"./chunk-FQFVAFWK.js";import{a as be,b as z,i as no,j as Gn,p as qn,y as q}from"./chunk-F2XTOZTN.js";import{a as ot,b as zt}from"./chunk-DFS4RMVP.js";import{a as ft}from"./chunk-HCBYKLMW.js";import{a as ce,b as G,c as rt,i as Hn,j as Gt}from"./chunk-C44QQJR4.js";import{a as At}from"./chunk-6YGTRKDT.js";import{e as je}from"./chunk-UR6MHSHU.js";var Jt=je(At(),1);import pe from"process";import*as tl from"tls";function Ci(){let e=tl;if(!(typeof e.getCACertificates!="function"||typeof e.setDefaultCACertificates!="function"))try{let t=o=>typeof o=="string",r=e.getCACertificates("default").filter(t),s=e.getCACertificates("system").filter(t);e.setDefaultCACertificates([...new Set([...r,...s])])}catch{}}var Ii=!1;function _i(){if(!Ii)try{if(typeof process.emitWarning!="function")return;let e=process.emitWarning.bind(process),t=((r,...s)=>{let o=typeof r=="string"?r:r?.message??"";if(!((typeof s[0]=="string"?s[0]:typeof r=="object"&&r?r.name:void 0)==="ExperimentalWarning"&&o.includes("buffer.File")))return e(r,...s)});process.emitWarning=t,Ii=!0}catch{}}import{basename as Bu,join as Me,resolve as Ku}from"path";var jr=je(At(),1);var Ie=je(At(),1);var Qe=je(ft(),1);function Ei({steps:e,bifurcationInfo:t,perFlowMetadata:r}){return!t||t.isSingleFlow||!r||r.length<=1?null:(0,Qe.jsx)(ce,{flexDirection:"column",children:r.map((s,o)=>{let n=e[o],c=n?.children??[],i=c.filter(g=>g.status==="passed").length,a=c.filter(g=>g.status==="failed").length,d=i+a,l=c.reduce((g,u)=>g+(u.duration??0),0),m=n?.status==="failed"?"failed":"passed",p=t.flows[o]??n?.objective??`Flow ${o+1}`;return(0,Qe.jsxs)(ce,{flexDirection:"column",marginTop:o>0?1:0,children:[(0,Qe.jsxs)(ce,{marginLeft:1,children:[(0,Qe.jsx)(G,{color:q.purple,bold:!0,children:"Flow "+(o+1)+": "}),(0,Qe.jsx)(G,{color:q.purple,children:p})]}),(0,Qe.jsx)(pn,{status:m,summary:s?.summary??"",duration:l,steps:d,stepsPassed:i,stepsFailed:a,reason:s?.error_message??void 0,creditsConsumed:s?.credits_consumed??void 0})]},`flow-summary-${o}`)})})}var de=je(ft(),1);function Ri({config:e,spawnOpts:t,cancelRef:r,banner:s,describeContext:o,onComplete:n,onStepEnd:c,onReasoning:i,onStepComplete:a}){let{exit:d}=Gt(),{append:l}=zt(),{describe:m,onDescribe:p,creditsRef:g}=ei({resolve:()=>o??null,hostIsTTY:()=>!!process.stderr.isTTY}),u=Xo(c,void 0,i,a,p),v=(0,Ie.useRef)(!1),x=(0,Ie.useRef)(!1),[T,S]=(0,Ie.useState)("");(0,Ie.useEffect)(()=>{v.current||(v.current=!0,u.startRun(e,t))},[e,t,u]),(0,Ie.useEffect)(()=>{r&&(r.current=()=>u.cancelRun())},[r,u]),(0,Ie.useEffect)(()=>{u.isRunning||m.stop()},[u.isRunning,m.stop]);let w=(0,Ie.useRef)(0);Hn((k,h)=>{h.ctrl&&k==="c"&&(u.isRunning?(w.current++,w.current>=2?d():u.cancelRun()):d())}),Hn((k,h)=>{u.askingUser&&(h.return?(u.sendAnswer(T),S("")):h.backspace||h.delete?S(R=>R.slice(0,-1)):k&&!h.ctrl&&!h.meta&&S(R=>R+k))},{isActive:!!u.askingUser}),(0,Ie.useEffect)(()=>{if(!u.isRunning&&u.lastRunEnd&&!x.current){x.current=!0;let{passed:k,failed:h,total:R}=rr(u.steps),O=u.bifurcationInfo;n({lastRunEnd:u.lastRunEnd,stepsPassed:k,stepsFailed:h,stepsTotal:R,hadError:!1,bifurcationFlows:O&&!O.isSingleFlow?O.flows:null,describeCredits:g.current,evidence:u.getEvidenceState()}),u.shutdownRunner().finally(()=>d())}},[u.isRunning,u.lastRunEnd,u.steps,u.shutdownRunner,n,d]),(0,Ie.useEffect)(()=>{u.runError&&!u.isRunning&&!x.current&&(x.current=!0,n({lastRunEnd:null,stepsPassed:0,stepsFailed:0,stepsTotal:0,hadError:!0,bifurcationFlows:null,describeCredits:g.current,evidence:u.getEvidenceState()}),u.shutdownRunner().finally(()=>d()))},[u.runError,u.isRunning,u.shutdownRunner,n,d]);let C=u.lastRunEnd?(()=>{let{passed:k,failed:h,total:R}=rr(u.steps);return{status:u.lastRunEnd.status,duration:u.lastRunEnd.duration??0,summary:u.lastRunEnd.summary??"",stepsPassed:k,stepsFailed:h,stepsTotal:R,reason:u.lastRunEnd.reason,finalState:u.lastRunEnd.final_state,creditsConsumed:(u.lastRunEnd.credits_consumed??0)+g.current}})():null,f=(0,Ie.useRef)(!1);return(0,Ie.useEffect)(()=>{f.current||!s||(f.current=!0,l((0,de.jsxs)(ce,{flexDirection:"column",marginBottom:1,children:[(0,de.jsxs)(ce,{borderStyle:"round",borderColor:"#dc4e08",paddingX:2,children:[(0,de.jsx)(G,{color:"#ff9500",bold:!0,children:"KaneAI CLI"}),(0,de.jsx)(G,{color:q.dim,children:" \u2502 "}),(0,de.jsx)(G,{color:q.orange,children:s.model}),(0,de.jsx)(G,{color:q.dim,children:" \u2502 "}),(0,de.jsx)(G,{color:q.dim,children:s.auth})]}),s.status?.map((k,h)=>(0,de.jsx)(G,{color:q.dim,children:k},h))]})))},[]),(0,de.jsxs)(ce,{flexDirection:"column",children:[(()=>{let k=io({isRunning:u.isRunning,bifurcationInfo:u.bifurcationInfo,steps:u.steps,cmInitCounts:u.cmInitCounts,replayInfo:u.replayInfo});return k?(0,de.jsx)(so,{label:k.label,hasBifurcation:k.hasBifurcation}):null})(),u.steps.length>0&&(0,de.jsx)(oo,{steps:u.steps,bifurcated:!!u.bifurcationInfo&&!u.bifurcationInfo.isSingleFlow,flows:u.bifurcationInfo?.flows,cmInitCounts:u.cmInitCounts,staticSteps:!0,onStepCommit:l,describe:m.text,describeVisible:m.visible,describeRevealing:m.revealing}),u.askingUser&&(0,de.jsxs)(ce,{flexDirection:"column",marginTop:1,children:[(0,de.jsxs)(G,{color:q.orange,children:['Agent is asking: "',u.askingUser,'"']}),(0,de.jsxs)(G,{children:["> ",T,"\u2588"]})]}),u.runError&&(0,de.jsx)(Cs,{message:u.runError,code:"RUNNER_ERROR"}),C&&u.lastRunEnd&&(0,de.jsx)(Ei,{steps:u.steps,bifurcationInfo:u.bifurcationInfo,perFlowMetadata:u.lastRunEnd.per_flow_metadata??[]}),C&&(0,de.jsx)(pn,{status:C.status==="passed"?"passed":"failed",summary:C.summary??"",duration:C.duration,steps:C.stepsTotal,stepsPassed:C.stepsPassed,stepsFailed:C.stepsFailed,reason:C.reason,creditsConsumed:C.creditsConsumed})]})}import{createInterface as nl}from"readline";function lt(e){process.stdout.write(JSON.stringify(e)+`
4
+ `)}async function Ti(e,t,r){let s=Bo();if(!s)throw new Error("v16-runner not found. Build the binary with `cd v16-runner && python build.py` or ensure Python is available.");let o=Jo({environment:t?.environment,mode:t?.mode,assertionMode:t?.assertionMode,finalValidation:t?.finalValidation,username:e.username,accessKey:e.access_key,sessionId:e.session_id});e.device?.platform&&await Ko(o,e.device);let n=new Ho({env:o,runner:s,log:t?.log,sessionId:e.session_id}),c={...Go(e),headless:e.headless??!1},i={...e};delete i.run_id;let a=r?.kind??"author";a==="evaluate"&&delete i.objective,Wo(i,{environment:t?.environment});let d=`run-${e.run_index}`;vn().then(C=>{C&&lt({type:"update_available",current:C.current,latest:C.latest,severity:C.severity})}).catch(()=>{}),bn().then(C=>{C&&lt({type:"skill_update_available",current:C.current,latest:C.latestCompatible,install_cmd:"kane-cli install skill"})}).catch(()=>{});let l=nl({input:process.stdin});l.on("line",C=>{try{let f=JSON.parse(C);f.type==="user_response"?n.sendUserResponse(f.answer??""):f.type==="cancel"&&n.cancel(d)}catch{}}),await n.start(c);let m=null,p=!1,g=0,u=null,v=0,x=!1,T=qo(),S=!1,w;r?.timeoutSeconds&&r.timeoutSeconds>0&&(w=setTimeout(()=>{S=!0,r.onTimeout?.(),n.kill()},r.timeoutSeconds*1e3));try{for await(let C of n.run(d,a,i))switch(T=zo(T,C),C.type){case"run_start":x&&v++;break;case"step_start":{let f=C;r?.onStepLog?.("STEP_START",`Step ${f.index} started`,{index:f.index,objective:f.objective,child_id:f.child_id});let k={step:f.index+1,status:"running",remark:f.objective??`Step ${f.index+1}`};f.child_id&&(k.child_id=f.child_id),lt(k);break}case"step_event":C.event==="reasoning"&&C.detail&&C.detail!=="reasoning"&&r?.onReasoning?.(C.detail),r?.onStepLog?.("STEP_EVENT",`Step ${C.index} ${C.event}`,{index:C.index,phase:C.event,action_type:C.action_type,detail:C.detail,child_id:C.child_id});break;case"step_end":{let f=C;r?.onStepLog?.("STEP_END",`Step ${f.index} ${f.status}`,{index:f.index,status:f.status,duration:f.duration,summary:f.summary,child_id:f.child_id}),r?.onStepComplete?.(),g++;let k={step:f.index+1,status:f.status==="passed"?"done":"failed",remark:f.summary??""};f.child_id&&(k.child_id=f.child_id),lt(k);let h=x?Math.max(0,v-1):0,R=typeof f.ordinal=="number"&&f.id?{ordinal:f.ordinal,id:f.id}:void 0;r?.onStepEnd?.(f.index,h,f.child_id,R);break}case"bifurcation":{let f=C,k=f.flows??[],h=f.count??k.length;(f.is_single_flow??h<=1)||(u=k,x=!0,v=0),lt({type:"bifurcation",flows:k,count:h});break}case"ask_user":{let f=C;lt({type:"ask_user",question:f.question,step_index:f.step_index,...f.options?{options:f.options}:{}});break}case"run_end":{m=C;break}case"error":{p=!0,lt({type:"error",message:C.message});break}default:break}}catch(C){if(!S)throw C}finally{w&&clearTimeout(w)}return l.close(),await n.shutdown(),{lastRunEnd:m,stepsTotal:g,hadError:p,timedOut:S,bifurcationFlows:u,evidence:T}}function rl(e){if(e.conditions.length===0)return xt("--analyzer-only needs at least one --condition");if(e.objective!==void 0&&e.objective!=="")return xt("a positional objective is not accepted with --analyzer-only; pass each condition via --condition");if(!e.agent&&e.isTTY)return xt("--analyzer-only requires --agent or a non-TTY stdin (it emits NDJSON, never a UI)");let t=e.conditions.findIndex(o=>o.trim()==="");if(t!==-1)return xt(`--condition #${t+1} is blank`);let r=e.conditions.findIndex(o=>/[\r\n]/.test(o));if(r!==-1)return xt(`--condition #${r+1} spans more than one line`);let s=[];return e.codeExport&&s.push("--code-export"),e.name&&s.push("--name"),e.target&&e.target!=="desktop"&&s.push(`--target ${e.target}`),e.app&&s.push("--app"),e.deviceName&&s.push("--device-name"),e.osVersion&&s.push("--os-version"),s.length?xt(`--analyzer-only does not accept ${s.join(", ")}: it judges the current web page and saves nothing`):{ok:!0}}function Pi(e){if(!e.analyzerOnly)return e.conditions.length>0?"--condition requires --analyzer-only":e.objective?null:"missing required argument 'objective'";let t=rl(e);return t.ok?null:t.message}function Ai(){return{agent:!0,local:!0,allowMissingUrl:!0,target:"desktop"}}function Di(e){let t=[];return e.url&&t.push("--url"),e.maxSteps!==void 0&&e.maxSteps!=="50"&&t.push("--max-steps"),e.mode&&t.push("--mode"),e.finalValidation&&t.push("--final-validation"),e.taskSkills&&t.push("--task-skills"),e.bugDetection&&t.push("--bug-detection"),t}var $i=`
5
+ `;function Mi(e){return e.join($i)}function Oi(e,t){let r=e.split($i);if(r.length!==t)throw new Error(`expected ${t} condition(s) after variable transform, got ${r.length}`);return r}function Ni(e,t){let r=e.reason??"";if(r.includes("Cancel")||r.includes("Timeout"))return 3;let s=e.condition_results??[];return s.length===t&&s.every(n=>typeof n=="boolean")?0:1}function xt(e){return{ok:!1,message:e}}function ji(e){return!!(e.target||e.deviceName||e.osVersion||e.app||e.cdpEndpoint||e.wsEndpoint||e.cft||e.url)}function Fi(e){return e.kind!=="mismatch"?null:e.suggested==="mobile"?"classification: objective looks mobile; run stays on web \u2014 pass --target emulator|simulator to run on a device":"classification: objective looks web; run stays on the device \u2014 pass --target desktop to run on web"}var Li=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function yn(e=process.stderr){if(!e.isTTY)return{onProgress:s=>e.write(`${s}
6
+ `),done:()=>{}};let t=0,r=!1;return{onProgress:s=>{r=!0,t=(t+1)%Li.length,e.write(`\r\x1B[2K${Li[t]} ${s}`)},done:()=>{r&&e.write(`
7
+ `),r=!1}}}var Vi=["emulator","simulator"];function Ui(e){e.command("doctor").description("Check the mobile tooling this machine needs for one target: emulator or simulator").option("--target <target>","Which toolchain to check: emulator | simulator (required)").option("--install","Download or repair the managed deps bundle for that target").action(async t=>{if(!t.target){process.stderr.write(["error: --target is required \u2014 say which toolchain to check."," kane-cli doctor --target emulator"," kane-cli doctor --target simulator"].join(`
8
8
  `)+`
9
- `),process.exitCode=2;return}let r=t.target.toLowerCase();if(!Ns.includes(r)){process.stderr.write(`error: unknown target '${t.target}' \u2014 supported values: ${Ns.join(", ")}
10
- `),process.exitCode=2;return}if(t.install){let o=vn();try{await zt().ensure(r,{automatic:!(process.stdin.isTTY&&process.stdout.isTTY),approved:!0,onProgress:o.onProgress})}catch(n){o.done(),process.stderr.write(`error: ${n instanceof Error?n.message:String(n)}
11
- `),process.exitCode=2;return}o.done()}let i=await ao(Gt(r));process.stdout.write(`${co(i)}
12
- `),process.exitCode=lo(i)})}function jt(e,t){if(e===t)return 0;if(e.length===0)return t.length;if(t.length===0)return e.length;let r=new Array(t.length+1),i=new Array(t.length+1);for(let o=0;o<=t.length;o++)r[o]=o;for(let o=1;o<=e.length;o++){i[0]=o;for(let n=1;n<=t.length;n++){let c=e[o-1]===t[n-1]?0:1;i[n]=Math.min(r[n]+1,i[n-1]+1,r[n-1]+c)}[r,i]=[i,r]}return r[t.length]}var tl=2,nl=3,Fs=new Set(["apps","balance","changelog","config","context","cover","design","devices","doctor","evidence","feedback","folders","generate","help","install","login","logout","maintain","plugin","profiles","projects","run","testmd","testrun","whoami"]),Ls=new Set(["doctor"]);function cr(e){return e?Fs:new Set([...Fs].filter(t=>!Ls.has(t)))}function rl(e,t){let r=e.toLowerCase(),i=[...t],o=[];for(let n of i){let c=n.toLowerCase();c!==r&&c.startsWith(r)&&o.push({name:n,distance:0})}if(o.length===0)for(let n of i){let c=n.toLowerCase();if(c===r)continue;let s=jt(r,c);s<=tl&&o.push({name:n,distance:s})}return o.sort((n,c)=>n.distance-c.distance||n.name.localeCompare(c.name)),o.slice(0,nl).map(n=>n.name)}function Vs(e,t){if(!t.hostSupportsMobile&&Ls.has(e))return{message:`error: ${t.mobileMessage}
13
- `,exitCode:2};let r=cr(t.hostSupportsMobile);return{message:ol(e,rl(e,r)),exitCode:2}}var lr=new Set(["set-device-name","set-os-version","set-app","set-auto-grant-permissions","set-auto-accept-alerts"]);function Us(e,t){return!t.hostSupportsMobile&&lr.has(e)?{message:`error: ${t.mobileMessage}
14
- `,exitCode:2}:null}function ol(e,t){let r=t.length>0?` \u2014 did you mean ${t.map(i=>`'${i}'`).join(" or ")}?`:"";return`error: unknown command '${e}'${r}
9
+ `),process.exitCode=2;return}let r=t.target.toLowerCase();if(!Vi.includes(r)){process.stderr.write(`error: unknown target '${t.target}' \u2014 supported values: ${Vi.join(", ")}
10
+ `),process.exitCode=2;return}if(t.install){let o=yn();try{await Xt().ensure(r,{automatic:!(process.stdin.isTTY&&process.stdout.isTTY),approved:!0,onProgress:o.onProgress})}catch(n){o.done(),process.stderr.write(`error: ${n instanceof Error?n.message:String(n)}
11
+ `),process.exitCode=2;return}o.done()}let s=await uo(qt(r));process.stdout.write(`${mo(s)}
12
+ `),process.exitCode=po(s)})}function jt(e,t){if(e===t)return 0;if(e.length===0)return t.length;if(t.length===0)return e.length;let r=new Array(t.length+1),s=new Array(t.length+1);for(let o=0;o<=t.length;o++)r[o]=o;for(let o=1;o<=e.length;o++){s[0]=o;for(let n=1;n<=t.length;n++){let c=e[o-1]===t[n-1]?0:1;s[n]=Math.min(r[n]+1,s[n-1]+1,r[n-1]+c)}[r,s]=[s,r]}return r[t.length]}var ol=2,sl=3,Bi=new Set(["apps","balance","changelog","config","context","cover","design","devices","doctor","evidence","feedback","folders","generate","help","install","login","logout","maintain","plugin","profiles","projects","run","testmd","testrun","whoami"]),Ki=new Set(["doctor"]);function mr(e){return e?Bi:new Set([...Bi].filter(t=>!Ki.has(t)))}function il(e,t){let r=e.toLowerCase(),s=[...t],o=[];for(let n of s){let c=n.toLowerCase();c!==r&&c.startsWith(r)&&o.push({name:n,distance:0})}if(o.length===0)for(let n of s){let c=n.toLowerCase();if(c===r)continue;let i=jt(r,c);i<=ol&&o.push({name:n,distance:i})}return o.sort((n,c)=>n.distance-c.distance||n.name.localeCompare(c.name)),o.slice(0,sl).map(n=>n.name)}function Ji(e,t){if(!t.hostSupportsMobile&&Ki.has(e))return{message:`error: ${t.mobileMessage}
13
+ `,exitCode:2};let r=mr(t.hostSupportsMobile);return{message:al(e,il(e,r)),exitCode:2}}var pr=new Set(["set-device-name","set-os-version","set-app","set-auto-grant-permissions","set-auto-accept-alerts"]);function Wi(e,t){return!t.hostSupportsMobile&&pr.has(e)?{message:`error: ${t.mobileMessage}
14
+ `,exitCode:2}:null}function al(e,t){let r=t.length>0?` \u2014 did you mean ${t.map(s=>`'${s}'`).join(" or ")}?`:"";return`error: unknown command '${e}'${r}
15
15
 
16
16
  Run an objective with: kane-cli run "<objective>"
17
17
  List all commands: kane-cli --help
18
- `}function bn(e){let t=e.indexOf("--"),r=t===-1?e:e.slice(0,t),i;for(let o=0;o<r.length;o++)r[o]==="--mode"?i=r[++o]:r[o].startsWith("--mode=")&&(i=r[o].slice(7));return i==="agent"}function Bs(e,t,r=50){let i=!1,o=(n,c)=>{if(!c)return;let s=n.line(c);s!=null&&t(s)};return{eager(){for(let n of e)n.promise.then(c=>{i||o(n,c)}).catch(()=>{})},async bounded(){if(i)return;let n=new Promise(s=>{setTimeout(()=>s(null),r).unref?.()}),c=await Promise.all(e.map(s=>Promise.race([s.promise.catch(()=>null),n])));i=!0,c.forEach((s,a)=>o(e[a],s))},silence(){i=!0}}}function Ks(e,t){return t||e==="context"?"silence":e==="design"?"bounded":"eager"}import{join as il}from"path";function Js(e){let t=e.command("testmd").description("Manage test.md files (run, list, status, delete, export, sync)").action(async()=>{process.stdin.isTTY||(process.stderr.write(`error: testmd requires a sub-action in non-TTY mode (run | list | status | delete | export | sync)
19
- `),process.exit(2));let{runListTui:r,resolveCurrentOrgId:i}=await import("./testmd-actions-2CPJZAC2.js"),o=await i({});o.ok||process.exit(o.code),process.exit(await r(o.orgId))});al(t),cl(t),ll(t),dl(t),ul(t),ml(t)}function sl(e,t){return t.concat(e)}function al(e){e.command("run <path>").description("Run a test from a *_test.md file").option("--url <url>","Start URL for the first step (overrides frontmatter url: and config default_url)").option("--headless","Run Chrome in headless mode").option("--max-steps <n>","Max agent steps","50").option("--timeout <seconds>","Kill after N seconds").option("--cdp-endpoint <url>","Connect to existing Chrome via CDP").option("--ws-endpoint <url>","Playwright WebSocket endpoint").option("--global-context <file>",`Override global context (default: ${il(q,"global-memory.md")})`).option("--local-context <file>","Override local context (default: .testmuai/context.md in cwd)").addOption(new B("--model <name>","Model override").hideHelp()).option("--variables <json>","Inline variables JSON").option("--variables-file <path>","Load variables from file").option("--dataset-id <id>","Test Manager dataset whose row supplies the ${column} parameters (overrides the file's dataset:)").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (overrides the file's dataset.row; a missing or unknown id lists the rows)").option("--session-context <json>","Session context JSON (prior runs)").addOption(new B("--cft","Use Playwright Chromium instead of managed Chrome").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").option("--mode <name>","Run mode: action | testing").option("--assertion-mode <mode>","Assertion mode: dom (default \u2014 DOM extraction & assertions, vision fallback) | visual (vision only)").option("--final-validation <on|off>","Final validation: append the system cp_final checkpoint. Overrides config (default: off)").option("--agent","Agent mode: plain NDJSON output, no colors/UI").option("--task-skills","Enable domain-specific task skills (experimental)").addOption(new B("--local","Skip TMS integration (no uploads, no variables/secrets push)").hideHelp()).option("--allow-missing-url","Non-TTY only: proceed from the browser's current page instead of failing when the first step has no start URL (frontmatter url:/--url still used)").option("--code-export","Generate code export after upload").option("--code-language <lang>","Code-export language (python|javascript)").option("--name <name>","Persist session under this name").option("--target <name>","Where to run: desktop | emulator | simulator (default: the file's `target:`, else desktop)").option("--device-name <name>","Which device, when the target is mobile: the name as `kane-cli devices list` shows it. The OS version comes from --os-version or the file's os_version:").option("--os-version <version>","The device's OS version (e.g. 17.5, 14). Alone = re-version the file's device (or any device on that version)").option("--app <path|AppId>","App under test, when the target is mobile: a build (.apk / .zip of the .app) or an APP\u2026 id from your uploads. Overrides the file's `app:`").option("--skip-code-validation","Skip post-codegen validation").option("--no-skip-code-validation","Force post-codegen validation").option("--on-lock-conflict <mode>","lock conflict policy: readonly|fail|wait",t=>{if(t!=="readonly"&&t!=="fail"&&t!=="wait")throw new Error(`--on-lock-conflict must be readonly|fail|wait, got: ${t}`);return t}).option("--push","always commit at end-of-run (no retry semantics)").option("--no-adaptive-heal","disable adaptive heal \u2014 a replay miss becomes terminal instead of re-authoring the failing tail (default: heal on, 3 attempts then a full re-author)").addOption(new B("--retry","(retired) adaptive heal is on by default").hideHelp()).addOption(new B("--retry-count <n>","(retired) heal budget is fixed at 3").argParser(t=>{let r=parseInt(t,10);if(Number.isNaN(r)||r<0)throw new Error(`--retry-count must be a non-negative integer, got: ${t}`);return t}).hideHelp()).option("--author","re-author every step in place on the test's existing identity and commit a new version (a never-authored test takes the first-run path)").addOption(new B("--no-evidence-publish","skip the replay evidence publish (blob upload + TMS /evidence/ingest) \u2014 the run leaves no execution record in TMS").hideHelp()).addOption(new B("--no-testmd-sync","skip the testmd bundle push before the commit \u2014 the caller owns the bundle for that commit").hideHelp()).option("--bug-detection <mode>","detect product bugs while authoring: off|stop|continue (stop halts the run on a confirmed bug; continue records it and keeps going). Overrides `config set-bug-detection`. Authoring steps only \u2014 replay failures always investigate.",t=>{if(t!=="off"&&t!=="stop"&&t!=="continue")throw new Error(`--bug-detection must be off, stop or continue, got: ${t}`);return t}).action(async(t,r)=>{let{retiredRetryFlagsNotice:i}=await import("./replay-policy-A62KXE6Y.js"),o=i(r);o&&process.stderr.write(o+`
20
- `);let{runTestMdFile:n}=await import("./run-test-md-MRYNFNPO.js"),c=await n(t,r);process.exit(c)})}function cl(e){e.command("list").description("List *_test.md files in the working directory (recursive)").option("--root <dir>","Root directory to scan (default: cwd)").option("--ignore <name>","Skip a directory by name (repeatable)",sl,[]).option("--json","Force NDJSON output even on TTY").action(async t=>{let{runListAction:r,resolveCurrentOrgId:i}=await import("./testmd-actions-2CPJZAC2.js"),o=await i({json:!!t.json});o.ok||process.exit(o.code),process.exit(await r(t,o.orgId))})}function ll(e){e.command("status <path>").description("Print local meta.json for a *_test.md (no live TMS check in v1)").action(async t=>{let{runStatusAction:r,resolveCurrentOrgId:i}=await import("./testmd-actions-2CPJZAC2.js"),o=await i({});o.ok||process.exit(o.code),process.exit(await r(t,o.orgId))})}function dl(e){e.command("delete <path>").description("Remove output-<stem>/ and the *_test.md source file (TMS untouched)").option("--yes","Skip confirmation prompt (required in non-TTY)").action(async(t,r)=>{let{runDeleteAction:i,resolveCurrentOrgId:o}=await import("./testmd-actions-2CPJZAC2.js"),n=await o({});n.ok||process.exit(n.code),process.exit(await i(t,!!r.yes,n.orgId))})}function ul(e){e.command("export <path>").description("Generate standalone test code (Playwright)").option("--language <lang>","python|javascript (falls back to tui-config)").option("--output <dir>","Override output dir (default: output-<stem>/playwright-<lang>-code/)").option("--force","Overwrite an existing local export").action(async(t,r)=>{let{runExportAction:i,resolveCurrentOrgId:o}=await import("./testmd-actions-2CPJZAC2.js"),n=await o({});n.ok||process.exit(n.code),process.exit(await i(t,r,n.orgId))})}function ml(e){e.command("sync <path>").description("Zip the testmd + imports + replay outputs and push {commit_id}-testmd.zip to cloud").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").action(async(t,r)=>{let{runSyncAction:i,resolveSyncAuth:o}=await import("./testmd-actions-2CPJZAC2.js"),n=await o(r);n.ok||process.exit(n.code),process.exit(await i(t,n))})}async function dr(e){if(e==="agent")return;let{warnIfBehind:t}=await import("./store-guard-XQ5MSUB2.js"),{contextDir:r}=await import("./paths-JCYX6UWL.js");await t(r(process.cwd()),i=>process.stderr.write(i+`
21
- `))}function Ws(e){let t=e.command("context").description("Assurance context graph (.context/): ingest sources, extract use-cases, list nodes").action((a,d)=>{d.args.length>0&&d.error(`error: unknown command '${d.args[0]}'`,{exitCode:2,code:"commander.unknownCommand"}),d.help()});t.command("ingest <src...>").description("Land source files into .context/ and extract them \u2014 the one-flow entry. On a TTY this continues into the interactive extract chat; --mode ci or piped stdin lands only").option("--as <id>","Ingest AS this existing source id \u2014 a new VERSION: moves its head, dependents go stale (single file only)").option("--mode <mode>","interactive | agent | ci | override \u2014 how the extraction runs. ci (and headless without --mode) lands only").option("--plan","Extraction stops after the proposal \u2014 print it, commit nothing").option("--force","Extract even if the landed snapshot was already extracted").option("--trust <dial>","Extraction trust dial: auto (default) | hold (headless only)").action(async(a,d)=>{let{ingestCommand:l}=await import("./ingest-cmd-R5H5SF5K.js");process.exit(await l(a,d))}),t.command("extract").description("Interactively extract use-cases from ingested sources via the context agent").option("--plan","Stop after the proposal \u2014 print it, commit nothing").option("--apply <path>","NOT IMPLEMENTED YET \u2014 will commit a saved --plan proposal (refuses loudly today)").option("--mode <mode>","Ask policy: interactive | agent | ci | override. TTY defaults to interactive chat; REQUIRED when headless").option("--force","Re-extract sources even if their current snapshot was already extracted").option("--resume <sid>","Resume a paused session (state under .context/sessions/)").option("--message <text>","With --resume: answer the pending questions (or steer) in plain words \u2014 the agent maps your statement itself").option("--source <id>","Extract exactly this ingested source \u2014 the explicit path for su-conv-* conversation sources, which the default sweep skips").option("--queued","(removed) the queue is gone \u2014 extract sweeps every pending source by default; this flag refuses with guidance for one release").option("--trust <dial>","Per-run trust dial: auto (new items commit derived into review \u2014 the default everywhere) | hold (everything new HELD; headless only \u2014 refused under interactive). ci refuses the flag entirely").option("--answer <pairs...>","With --resume --mode agent: answer a pending question/panel BY ID \u2014 <qid-or-panelId>=<option number (1-based) or free text>, repeatable").option("--with-source <ref>","With --resume: land this file/URL FIRST and set the pending questions aside \u2014 the agent reads the source, narrates what it settled, and re-asks what's still open").action(async a=>{let{extractCommand:d}=await import("./extract-cmd-KIEOBRIT.js");process.exit(await d(a))}),t.command("sessions [action] [sid]").description("List resumable sessions; `sessions show <sid>` prints pending questions + assumed defaults; `sessions clean [sid]` GCs expired/named ones").option("--all","clean: remove ALL sessions (incl. corrupt), not just expired").option("--json","JSON output").action(async(a,d,l)=>{let{sessionsCommand:m}=await import("./sessions-cmd-DV442ZCY.js");process.exit(await ae("sessions",()=>m(a,l,d)))});let r="interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)",i=(a,d)=>[...d,a],o=async(a,d,l,m="sync")=>{let{syncCommand:p}=await import("./sync-cmd-5INKTZN2.js");process.exit(await ae(m,()=>p(a,d,l),{mode:l.mode}))},n=a=>{s.opts().answer.length>0&&a.error("error: unknown option '--answer' (it belongs to kane-cli context sync [name] and kane-cli context pull)",{exitCode:2,code:"kane.answerOnSubcommand"})},c=a=>({...s.opts().mode!==void 0?{mode:s.opts().mode}:{},...a}),s=t.command("sync [name]").description("Get level with a location: finish an open rebase, take the location's new records, publish yours. Subcommands: setup, add, list, remove, status, doctor").option("--answer <id=choice>","Answer a rebase decision headless: <decision id>=<keep-theirs | apply-mine | apply-mine-as-new>, repeatable; only when a rebase is open",i,[]).option("--mode <mode>",r).action(async(a,d)=>o(a,[],{...d,answer:d.answer.length>0?d.answer:void 0}));s.command("setup").description("Guided setup: share context through GitHub, S3 or a folder, or join your team").option("--mode <mode>",r).action(async(a,d)=>{n(d);let{setupCommand:l}=await import("./sync-setup-4R54VRAO.js");process.exit(await l(c(a)))}),s.command("add <name> <descriptor>").description("Check a location (GitHub repository, S3 bucket or folder) and bind this store to it under <name>").option("--credential-env <VAR>","s3: read the access key from $VAR_ID and the secret from $VAR_SECRET, stored under the user config dir with mode 0600").option("--credential-file <path>","s3: read a JSON file {accessKeyId, secretAccessKey}, stored under the user config dir with mode 0600").option("--mode <mode>",r).action(async(a,d,l,m)=>{n(m),await o("add",[a,d],c(l))}),s.command("list").description("The locations this store is bound to").option("--json","JSON output").option("--mode <mode>",r).action(async(a,d)=>{n(d),await o("list",[],c(a))}),s.command("remove <name>").description("Forget a location (its witness is kept)").option("--mode <mode>",r).action(async(a,d,l)=>{n(l),await o("remove",[a],c(d))}),s.command("status [name]").description("Compare this store with a location and list the open rebase decisions; never writes").option("--show <n>","One moved record in full, by its position").option("--json","JSON output: the relation, rebase_id, decisions").option("--mode <mode>",r).action(async(a,d,l)=>{n(l),await o("status",a===void 0?[]:[a],c(d))}),s.command("doctor").description("What the store looks like: an interrupted reset, the chain, every rebase with its id; never writes unless asked").option("--abort","Undo an interrupted reset (before its import); else close the open rebase, keeping what was reapplied").option("--export <dir>","Build the pre-rebase store in <dir> as its own store (chain, envelopes, proposals, sessions, side files, test files)").option("--from <rebase-id>","With --export: which rebase (default: the open one, else the only one)").option("--json","JSON output").option("--mode <mode>",r).action(async(a,d)=>{n(d),await o("doctor",[],c(a))}),t.command("pull [name]").description("Take a location's new records: verified in full, then imported. Finishes an open rebase first").option("--rebase","You and the location both added work after the shared position: your records after it are saved, the location's are taken, yours are reapplied; nothing on the location is rewritten").option("--yes","Confirms replacing this store's records after the shared position (they are saved first); it does not answer rebase decisions").option("--answer <id=choice>","Answer a rebase decision headless: <decision id>=<keep-theirs | apply-mine | apply-mine-as-new>, repeatable; only when a rebase is open",i,[]).option("--mode <mode>",r).action(async(a,d)=>{let{pullCommand:l}=await import("./sync-cmd-5INKTZN2.js");process.exit(await ae("pull",()=>l(a,{...d,answer:d.answer.length>0?d.answer:void 0}),{mode:d.mode}))}),t.command("push [name]").description("Push this store's new records, their blobs and proposals to a location; refuses when the location has records this store has not pulled").option("--mode <mode>","interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)").action(async(a,d)=>{let{pushCommand:l}=await import("./sync-cmd-5INKTZN2.js");process.exit(await ae("push",()=>l(a,d),{mode:d.mode}))}),t.command("clone [descriptor] [dir]").description("Create a store in [dir] (default: the location's last name part) from a location <descriptor>, bound to it as `origin`").option("--credential-env <VAR>","s3: read the access key from $VAR_ID and the secret from $VAR_SECRET, stored under `origin` for the clone").option("--credential-file <path>","s3: read a JSON file {accessKeyId, secretAccessKey}, stored under `origin` for the clone").option("--mode <mode>","interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)").action(async(a,d,l)=>{let{cloneCommand:m}=await import("./sync-cmd-5INKTZN2.js");process.exit(await ae("clone",()=>m(a,d,l),{mode:l.mode}))}),t.command("fsck").description("Verify the full commit chain and check the derived projection for drift").option("--json","Print the full structured report as one JSON object (issues carry code + detail + ecids)").action(async a=>{let{fsckCommand:d}=await import("./maintenance-cmd-GZ4EMT3V.js");process.exit(await ae("fsck",l=>d(l,a)))}),t.command("locks",{hidden:!0}).description("Show held context/UC locks and waiters (read-only)").option("--json","Machine output (plain array, no NDJSON envelope \u2014 not a room verb)").action(async a=>{let{runLocksCommand:d}=await import("./locks-cmd-67OHQZNV.js"),{contextDir:l}=await import("./paths-JCYX6UWL.js");process.exit(d(l(process.cwd()),a,m=>process.stdout.write(m+`
22
- `)))}),t.command("rebuild").description("Wipe .context/derived and rebuild it from the verified commit chain").option("--yes","Skip the confirmation prompt (required when headless)").action(async a=>{let{rebuildCommand:d}=await import("./maintenance-cmd-GZ4EMT3V.js");process.exit(await ae("rebuild",()=>d(a),{write:!0}))}),t.command("list").description("List context graph nodes").option("--type <t>","Filter by node label (source | usecase)").option("--inferred","Only derived (unreviewed) nodes").option("--stale","Only stale/orphaned nodes").option("--all","Include superseded node versions").option("--json","JSON output").action(async a=>{let{listCommand:d}=await import("./list-cmd-QCIYKWYQ.js");process.exit(await ae("list",()=>d(a)))}),t.command("view").description("Render the context graph as an interactive HTML page and open it in the browser (snapshot)").option("--out <path>","Write the HTML to <path> instead of a temp file").option("--open","Force-open the browser even when non-TTY (piped)").option("--no-open","Write the file but do not open the browser").option("--json","Print the computed view payload as JSON and exit (no HTML)").action(async a=>{let{viewCommand:d}=await import("./view-cmd-P3XRFORJ.js");process.exit(await ae("view",()=>d(a)))}),t.command("retire <source_id>").description("Retire a source (head \u2192 null + tombstone record); reversible via revert").option("--reason <text>","Why this source is being retired").option("--yes","Skip the confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d)=>{let{retireCommand:l}=await import("./lifecycle-cmd-6R2PR2HM.js");process.exit(await ae("retire",async()=>(await dr(d.mode),l(a,d)),{write:!0,mode:d.mode}))}),t.command("name [ref] [slug]").description("Assign a stable kebab-case name to a node (ref = cid or existing slug); --backfill assigns logical ids to all unnamed live nodes").option("--backfill","assign label-prefixed logical ids (uc-/sc-/ac-/t-\u2026) to every live unnamed node").option("--yes","Skip the --backfill confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d,l)=>{let{nameCommand:m,nameBackfillCommand:p}=await import("./lifecycle-cmd-6R2PR2HM.js");l.backfill&&process.exit(await ae("namebackfill",()=>p(l),{mode:l.mode,streamVerb:"name"})),process.exit(await ae("name",async()=>(await dr(l.mode),m(a,d,l)),{write:!0,mode:l.mode}))}),t.command("revert <seq>").description("Invert a record's effects via a compensation record \u2014 history is never rewritten").option("--reason <text>","Why this record is being reverted").option("--yes","Skip the confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d)=>{let{revertCommand:l}=await import("./lifecycle-cmd-6R2PR2HM.js");process.exit(await ae("revert",async()=>(await dr(d.mode),l(a,d)),{write:!0,mode:d.mode}))}),t.command("review").description("Walk a review queue; verdicts land as ONE batched record").option("--queue <q>","derived (default) | skipped | archived | drift").option("--json","NDJSON output (drift listing + --verdicts outcomes)").option("--verdicts <file>",'headless verdict input: JSON array of {"ref", "resolution", ...} \u2014 atomic, works with or without a TTY').option("--allow-archive","Apply archives headlessly (requires --because; refused under --mode ci)").option("--because <reason>","audit reason stamped on headless archives (required with --allow-archive)").option("--mode <m>","agent | ci \u2014 ci refuses archives under ANY flag").option("--approve <refs...>","structured verdict: approve these refs (temp_ref/cid/logical id)").option("--skip <refs...>","structured verdict: skip these refs (no fact \u2014 stays queued)").option("--defer <refs...>","structured verdict: defer these refs (no fact \u2014 stays queued)").action(async a=>{let{reviewCommand:d}=await import("./review-cmd-BMJQZ6XJ.js");process.exit(await ae("review",()=>d(a)))}),t.command("explain <ref>").description("Replay the recorded reasoning + lineage for a node (no model call)").option("--json","JSON output").action(async(a,d)=>{let{explainCommand:l}=await import("./explain-cmd-XVE6Z67Q.js");process.exit(await ae("explain",()=>l(a,d)))})}function Ys(e){let t=e.command("design").description("Test design engine: turn a committed use-case into ACs, scenarios, and 1:1 tests").action((r,i)=>{i.args.length>0&&i.error(`error: unknown command '${i.args[0]}'`,{exitCode:2}),i.help()});t.command("tests").description("Design the assurance for ONE committed use-case (conversational; chat is the default)").option("--use-case <ref>","The use-case to design \u2014 logical id (uc-\u2026) or cid (optional with --resume: the session remembers it)").option("--max <n>","Budget ceiling: max scenario+test pairs (NO ceiling when omitted \u2014 the agent estimates and asks)",r=>Number(r)).option("--strength <s>","Manual covering-array strength override: pairwise | 3-wise").option("--mode <mode>","Ask policy: interactive | agent | ci | override. TTY defaults to interactive chat; REQUIRED when headless").option("--force","Redesign a use-case that already has a live design (supersedes its scenario+test pairs)").option("--resume <sid>","Resume a paused design session (state under .context/sessions/)").option("--message <text>","With --resume: answer the pending questions (or steer) in plain words \u2014 the agent maps your statement itself").option("--plan","Transcription only \u2014 print each finalize payload, commit nothing").option("--allow-unreviewed","Design against an unreviewed use-case without approving it first").option("--phase <name>","Enter the design at this phase (grounding | acs | scenarios | wiring | tests), re-seeded from committed prior phases").option("--answer <pairs...>","With --resume --mode agent: answer a pending question/panel BY ID \u2014 <qid-or-panelId>=<option number (1-based) or free text>, repeatable").action(async r=>{let{designTestsCommand:i}=await import("./bind-YV6V5AI6.js");process.exit(await i(r))}),t.command("explain <ref>").description("Replay WHY a designed item looks the way it does \u2014 sidecar + recorded judgements, zero fresh AI").action(async r=>{let{designExplainCommand:i}=await import("./explain-cmd-R45I5MT7.js");process.exit(await i(r))})}function Hs(e){let t=e.command("maintain").description("Keep the assurance suite true as sources change: reconcile").action((r,i)=>{i.args.length>0&&i.error(`error: unknown command '${i.args[0]}'`,{exitCode:2}),i.help()});t.command("evolve [ref]").description("Re-design the parent use-case of a test/scenario/AC/use-case \u2014 unaffected items are preserved verbatim; reports the pair diff").option("--from-stale","Evolve every use-case with stale designed entities (deduped, per-UC confirm)").option("--because <reason>","Re-design a FRESH target anyway \u2014 the reason becomes the change delta and lands in provenance").action(async(r,i)=>{let{evolveCommand:o}=await import("./evolve-cmd-QQQPPGL3.js");process.exit(await o(r,i))}),t.command("reconcile").description("Reconcile a changed source: the head lands, extraction runs over the change, and every proposed change HOLDS as a review card \u2014 approve / reject / defer, nothing commits without your verdict (the in-chat review is the TTY default)").option("--from <file>","The NEW version of the source document (a file path)").option("--source-id <id>","The EXISTING source this file succeeds \u2014 its head moves; see `kane-cli context list --type source`").option("--plan","Preview: the head-move lands (the change fact), everything else is STAGED into the stored plan \u2014 nothing suite-side commits").option("--apply [path]","Walk a STORED plan (REMOVE stays plan-only). Bare = the latest plan behind an approval prompt; a path picks one; with --from it recomputes live").option("--mode <mode>","interactive | agent | ci | override \u2014 TTY defaults to the in-chat card review; headless requires one").action(async r=>{let{reconcileCommand:i}=await import("./reconcile-cmd-4VRTUM2D.js");process.exit(await i(r))})}function Gs(e){e.command("cover").description("Two-axis coverage: depth proven by an evidence pack + completeness owed by the live graph").enablePositionalOptions().option("--from <pack>","Evidence pack to read (dir, sealed file, or execution id; default: newest in .testmuai/evidence)").option("--json","Machine-readable output").option("--mode <mode>","interactive | agent | ci \u2014 agent/ci ride the NDJSON envelope (done-last + next)").action(async(r,i)=>{i.args.length>0&&i.error(`error: unknown command '${i.args[0]}'`,{exitCode:2});let{coverCommand:o}=await import("./cover-cmd-SWJ2NZUZ.js");process.exit(await ae("cover",()=>o(r)))}).command("gaps [uc]").description("Dual-axis coverage ribbon \u2014 designed \xD7 proven from the live graph; pass a use-case id for its full dossier").option("--stage <stage>","design | cover | all (default all)").option("--top <n>","Bound pending rows per use-case in the --json document (table output is never truncated)",r=>Number(r)).option("--rollup <rollup>","Proven-axis formula: lenient | strict (default lenient)").option("--json","Machine-readable nested document").option("--mode <mode>","interactive | agent | ci \u2014 agent/ci ride the NDJSON envelope (done-last + next)").action(async(r,i)=>{let{gapsCommand:o}=await import("./gaps-cmd-RGIPUSIR.js");process.exit(await ae("gaps",()=>o(r,i)))})}var Tr=Ne(At(),1);var je=Ne(At(),1);function zs(e){return{members:e.map(t=>({...t,status:"pending"})),summary:null,done:null}}function qs(e,t){return typeof t!="string"||t.length===0?!1:t===e.relPath||t.endsWith("/"+e.relPath)}function pl(e){return e==="passed"?"passed":"failed"}function Xs(e,t){switch(t.type){case"testrun_member_start":case"testrun_authored_member_start":return{...e,members:e.members.map(r=>qs(r,t.path)?{...r,status:"running"}:r)};case"testrun_member_end":case"testrun_authored_member_end":return{...e,members:e.members.map(r=>qs(r,t.path)?{...r,status:pl(t.status),durationS:t.duration_s}:r)};case"testrun_summary":return{...e,summary:{execution:t.execution??null,authored:t.authored??[],totals:t.totals,durationS:t.duration_s,upload:t.upload,cancelled:!!t.cancelled}};case"testrun_done":return{...e,done:{executionId:t.execution_id,overallStatus:t.overall_status}};default:return e}}var J=Ne(ft(),1);function Zs(e){return e<60?`${e.toFixed(1)}s`:`${Math.floor(e/60)}m ${Math.round(e%60)}s`}function Qs({member:e}){let t=e.status==="running",r=e.status==="passed",i=e.status==="failed",o=e.durationS!=null?Zs(e.durationS):"";return(0,J.jsxs)(se,{children:[(0,J.jsx)(se,{width:3,children:t?(0,J.jsx)(eo,{}):r?(0,J.jsx)(H,{color:G.green,bold:!0,children:"\u2713"}):i?(0,J.jsx)(H,{color:G.red,bold:!0,children:"\u2717"}):(0,J.jsx)(H,{color:G.muted,children:"\u25CB"})}),(0,J.jsxs)(se,{flexGrow:1,children:[(0,J.jsx)(H,{color:i?G.red:G.dim,children:e.relPath}),e.memberClass==="author"&&(0,J.jsx)(H,{color:G.purple,children:" authoring"})]}),(0,J.jsx)(se,{width:8,justifyContent:"flex-end",children:(0,J.jsx)(H,{color:G.dim,children:o})})]})}function fl({summary:e}){let t=e.totals,r=e.cancelled?"cancelled":t.failed>0||t.broken>0?"failed":"passed",i=r==="cancelled"?G.orange:r==="passed"?G.green:G.red,o=r==="cancelled"?"!":r==="passed"?"\u2713":"\u2717",n=r.toUpperCase(),c=`${t.passed} passed \xB7 ${t.failed} failed \xB7 ${t.broken} broken \xB7 ${t.skipped} skipped \xB7 ${t.authored} authored`;return(0,J.jsx)(se,{flexDirection:"column",marginTop:1,children:(0,J.jsxs)(se,{borderStyle:"round",borderColor:i,flexDirection:"column",paddingX:2,paddingY:1,children:[(0,J.jsxs)(H,{bold:!0,color:i,children:[o," ",n]}),(0,J.jsx)(H,{color:G.dim,children:c}),e.execution&&(0,J.jsxs)(H,{color:G.dim,children:["execution ",e.execution.id,": ",e.execution.status]}),e.authored.length>0&&(0,J.jsxs)(H,{color:G.dim,children:["authored: ",e.authored.length," test(s)"]}),(0,J.jsxs)(H,{color:G.dim,children:[Zs(e.durationS)," \xB7 upload: ",e.upload]})]})})}function ea({members:e,title:t,env:r,dispatchRef:i,onDone:o}){let{exit:n}=Ht(),{append:c}=qt(),[s,a]=(0,je.useState)(()=>zs(e)),[d,l]=(0,je.useState)(()=>new Set),m=(0,je.useRef)(!1),p=(0,je.useRef)(!1);(0,je.useEffect)(()=>(i.current=u=>a(v=>Xs(v,u)),()=>{i.current=null}),[]),(0,je.useEffect)(()=>{p.current||(p.current=!0,c((0,J.jsxs)(se,{borderStyle:"round",borderColor:"#dc4e08",paddingX:2,children:[(0,J.jsx)(H,{color:"#ff9500",bold:!0,children:"KaneAI CLI"}),(0,J.jsx)(H,{color:G.dim,children:" \u2502 "}),(0,J.jsx)(H,{color:G.dim,children:`testrun \xB7 ${t} \xB7 ${r}`})]})))},[]),(0,je.useEffect)(()=>{let u=s.members.filter(v=>(v.status==="passed"||v.status==="failed")&&!d.has(v.relPath));if(u.length!==0){for(let v of u)c((0,J.jsx)(Qs,{member:v},v.relPath));l(v=>{let k=new Set(v);for(let R of u)k.add(R.relPath);return k})}},[s.members,d,c]),(0,je.useEffect)(()=>{s.done&&!m.current&&(m.current=!0,o?.(),n())},[s.done,n,o]);let g=s.members.filter(u=>!d.has(u.relPath));return(0,J.jsxs)(se,{flexDirection:"column",children:[g.length>0&&(0,J.jsx)(se,{flexDirection:"column",children:g.map(u=>(0,J.jsx)(Qs,{member:u},u.relPath))}),s.summary&&(0,J.jsx)(fl,{summary:s.summary})]})}import{existsSync as hl}from"fs";import{resolve as vl,relative as bl}from"path";import{existsSync as gl}from"fs";import{relative as ta}from"path";var pe=class extends Error{};function na(e,t){let r=Ye(e);if(!gl(r))throw new pe(`--from-context needs an assurance store at ${r} \u2014 run the design flow there first, or run from the project root that holds .context`);let i=si(r),o=Gi(or(e)),n=[];for(let c of t){let s=c.trim();if(!s)continue;let a=i.resolve(s);if(!a)throw new pe(`--from-context: unknown id '${s}' \u2014 it does not resolve in the assurance graph`);if(i.superseded.has(a.tip))throw new pe(`--from-context: '${s}' is tombstoned (retired with no live successor) \u2014 redesign the suite or select a live test id`);let d=i.getNode(a.tip);if(d?.label!=="test")throw new pe(`--from-context: '${s}' is a ${d?.label??"unknown"} node, not a test \u2014 only test ids select members`);let l=s.toLowerCase(),m=o.get(l)??o.get(s)??[];if(m.length===0)throw new pe(`--from-context: '${s}' has no minted test file under ${or(e)} \u2014 re-run the design for this suite, or restore the deleted file`);if(m.length>1)throw new pe(`--from-context: '${s}' is claimed by ${m.length} files (${m.map(p=>ta(e,p)).join(", ")}) \u2014 remove the duplicates`);n.push({path:m[0],relPath:ta(e,m[0]),contextId:l})}return n}async function ra(e){let t=e.cwd??process.cwd(),r=e.fromContext?.length?na(t,e.fromContext):[],i;if(e.paths&&e.paths.length>0||r.length>0){let c=(e.paths??[]).map(s=>{let a=vl(t,s);if(!hl(a)||!a.endsWith("_test.md"))throw new pe(`not a *_test.md file: ${s}`);return{path:a,relPath:bl(t,a)}});i=[...r,...c]}else i=(await gi({root:t})).results.map(s=>({path:s.path,relPath:s.relPath}));if(e.match){let c;try{c=new RegExp(e.match)}catch(s){throw new pe(`invalid --match regex: ${s instanceof Error?s.message:s}`)}i=i.filter(s=>c.test(s.relPath))}let o=new Set,n=[];for(let c of i){if(o.has(c.path))continue;o.add(c.path);let s=hi(c.path);n.push({...c,tags:s.tags,...s.mobileTarget?{mobile:!0,platform:s.mobileTarget.platform,...s.mobileTarget.os_version?{osVersion:s.mobileTarget.os_version}:{},...s.mobileTarget.device_name?{deviceName:s.mobileTarget.device_name}:{},...s.mobileTarget.app?{app:s.mobileTarget.app}:{}}:{}})}if(e.tags&&e.tags.length>0){let c=new Set(e.tags.map(s=>s.toLowerCase()));return n.filter(s=>s.tags.some(a=>c.has(a))).sort((s,a)=>s.relPath.localeCompare(a.relPath))}return n.sort((c,s)=>c.relPath.localeCompare(s.relPath))}import{readFileSync as wl}from"fs";import{join as yl}from"path";function oa(e){try{return JSON.parse(wl(yl(Ae(e),".internal","meta.json"),"utf8"))}catch{return null}}var St=e=>typeof e=="string"&&e?e:void 0;function kl(e,t){if(!t)return[];try{return Wi(at(e.path),t.index)}catch{return[]}}function ia(e,t){let r=kl(e,t);return r.length===0?e:{...e,unresolved:r}}function sa(e,t={}){let r=[],i,o,n;for(let a of e){if(a.mobile&&!t.remote&&(n??=(t.host??Xt)().supported,!n)){r.push({...a,memberClass:St(oa(a.path)?.test_id)?"replay":"author",failure:"mobile_host_unsupported"});continue}let d=oa(a.path);if(!d){r.push(ia({...a,memberClass:"author"},t.variables));continue}let l={testcaseId:St(d.testcase_id),folderId:St(d.folder_id),commitId:St(d.commit_id),sessionName:St(d.session_name)},m=St(d.test_id),p=typeof d.org_id=="string"?d.org_id:void 0,g=typeof d.project_id=="string"?d.project_id:void 0,u=m?"replay":"author";if(i===void 0&&p&&(i=p),o===void 0&&g&&(o=g),p&&i&&p!==i){r.push({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u,failure:"org_mismatch"});continue}if(g&&o&&g!==o){r.push({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u,failure:"project_mismatch"});continue}r.push(ia({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u},t.variables))}let c=r.length>0&&r.every(a=>!a.failure),s=Yi(r.map(a=>a.unresolved??[]));return{checks:r,valid:c,orgId:i,projectId:o,...s.length?{unresolved:s}:{}}}function xl(e){return e.tags?.length?`testrun --tags ${e.tags.join(",")}`:e.match?`testrun --match ${e.match}`:e.paths?.length?`testrun ${e.paths.length} paths`:"testrun"}async function aa(e,t={}){let r=await ra(e),i=e.cwd??process.cwd(),o=sa(r,{...t,variables:{index:Bi(Ui(i))},...e.remote?{remote:!0}:{}}),n=Number(e.parallel??1),c=Number.isFinite(n)&&n>=1?Math.floor(n):1;if(c>1&&!e.remote&&r.some(s=>s.mobile))throw new pe("Mobile tests can only run one at a time on your local device. Please remove --parallel and try again.");if(e.deviceOverride&&new Set(r.filter(a=>a.mobile&&a.platform).map(a=>a.platform)).size>1)throw new pe("--device-name/--os-version name ONE device, but this selection has both emulator and simulator members \u2014 no device can serve both. Select one platform (--match/--tags) or drop the override.");return{...o,parallel:c,parallelClamped:!1,onFailure:e.onFailure??"continue",title:e.name??xl(e)}}import{basename as Sl,join as wa}from"path";import{readFileSync as ka,existsSync as Il}from"fs";import{promises as Ft}from"fs";import{existsSync as Lt}from"fs";import{join as Xe}from"path";async function ur(e){let t=e.status??"skipped",r=Xe(e.packDir,"tests",e.testId),i=Xe(r,"steps"),o=Xe(r,"logs");await Ft.mkdir(i,{recursive:!0});let n=Xe(i,".keep");Lt(n)||await Ft.writeFile(n,""),await Ft.mkdir(o,{recursive:!0});let c=Xe(o,"testrun.log");Lt(c)||await Ft.writeFile(c,e.reason+`
23
- `);let s=Xe(r,e.definition.path);Lt(s)||await Ft.writeFile(s,e.definition.content);let a=Xe(o,"meta.yaml");if(!Lt(a)){let l=await ni(o);await ti(e.packDir,e.testId,Zo(l))}let d=Xe(r,"result.yaml");Lt(d)||await ei(e.packDir,e.testId,Qo({testId:e.testId,status:t,definitionPath:e.definition.path,externalId:qo(e.externalIdInput),tags:e.tags,environment:{},steps:[]}))}async function wn(e,t,r){let i=[],o=new Array(e.length).fill(!1),n=0,c=!1,s,a=!1,d=()=>{i.length<e.length&&(a=!0)};r.signal&&(r.signal.aborted?d():r.signal.addEventListener("abort",d,{once:!0}));async function l(){for(;;){if(c||r.signal?.aborted||n>=e.length)return;let p=n++,g=e[p];o[p]=!0;try{r.onStart?.(g);let u=await t(g);i.push({item:g,result:u}),r.onEnd?.(g,u),r.failFast&&r.isFailure(u)&&(c=!0)}catch(u){s=s??u,c=!0}}}let m=Math.max(1,Math.min(r.parallel,e.length));try{await Promise.all(Array.from({length:m},()=>l()))}finally{r.signal?.removeEventListener("abort",d)}if(s)throw s;return{done:i,skipped:e.filter((p,g)=>!o[g]),cancelled:a}}function ca(e){return{type:"testrun_plan",members:e.checks.map(t=>({path:t.path,test_id:t.testId,tags:t.tags,...t.mobile?{mobile:!0}:{},...t.contextId?{context_id:t.contextId}:{},...t.failure?{failure:t.failure}:{},...t.unresolved?.length?{unresolved:t.unresolved}:{}})),valid:e.valid,parallel:e.parallel,...e.parallelClamped?{parallel_clamped:!0}:{}}}function la(e,t){return{type:"testrun_start",execution_id:e,members:t.checks.map(r=>r.relPath),parallel:t.parallel}}function da(e){return{type:"testrun_member_start",path:e.path,test_id:e.testId,...e.contextId?{context_id:e.contextId}:{}}}function ua(e,t){return{type:"testrun_member_end",path:e.path,test_id:e.testId,status:t.overallStatus,duration_s:t.durationS,...e.contextId?{context_id:e.contextId}:{}}}function ma(e){return{type:"testrun_authored_member_start",path:e.path}}function pa(e){return{type:"testrun_authored_member_end",path:e.relPath,...e.testId?{test_id:e.testId}:{},status:e.overallStatus,duration_s:e.durationS}}function It(e,t){return{type:"testrun_evidence_ingest",status:e.ok?"ok":"failed",evidence_id:t,...e.stage?{stage:e.stage}:{}}}function yn(e){return{type:"testrun_summary",execution:e.execution,authored:e.authored,totals:e.totals,duration_s:e.durationS,upload:e.upload,cancelled:e.cancelled,...e.remote?{remote:e.remote}:{}}}function Ct(e,t){return{type:"testrun_done",execution_id:e,overall_status:t}}function fa(e){return{type:"remote_start",backend:e.backend,env:e.env}}function ga(e){return{type:"remote_device",platform:e.platform,slug:e.slug,name:e.name,os_version:e.osVersion,...e.avdId?{avd_id:e.avdId}:{},...e.pool?{pool:e.pool}:{}}}function ha(e){return{type:"remote_app",path:e.path,app_id:e.appId,source:e.source}}function mr(e){return{type:"remote_device_hint",reason:e.reason,detail:e.detail}}function va(e){return{type:"remote_dispatched",job_id:e.jobId,job_url:e.jobUrl}}function Qe(e){return{type:"reconcile_merge_degraded",code:"RECONCILE_MERGE_DEGRADED",reason:e.reason,...e.detail?{detail:e.detail}:{},...e.excludedPack?{excluded_pack:e.excludedPack}:{},...e.standaloneIds?{standalone_execution_ids:e.standaloneIds}:{}}}function Vt(e){return{type:"remote_import_tape",path:e.path,status:e.status,...e.reason?{reason:e.reason}:{},...e.dispatchCommit?{dispatch_commit:e.dispatchCommit}:{},...e.gridCommit?{grid_commit:e.gridCommit}:{},...e.localCommit?{local_commit:e.localCommit}:{}}}function He(e){return{type:"remote_exec_sync",code:{skipped:"REMOTE_EXEC_SYNC_SKIPPED",warning:"REMOTE_EXEC_SYNC_WARNING",failed:"REMOTE_EXEC_SYNC_FAILED"}[e.status],status:e.status,reason:e.reason,...e.detail?{detail:e.detail}:{},...e.executionId?{execution_id:e.executionId}:{}}}function pr(e){return{type:"remote_coverage",code:{skipped:"REMOTE_COVERAGE_SKIPPED",failed:"REMOTE_COVERAGE_FAILED"}[e.status],status:e.status,reason:e.reason,...e.detail?{detail:e.detail}:{}}}function kn(e){return{type:"remote_error",code:e.code,detail:e.detail}}function Ut(e){return{type:"remote_done",status:e.status,exit:e.exit,job_id:e.jobId,sessions_path:e.sessionsPath}}function ba(e,t){let r=e.unresolved??[];return r.length>0?mn(r,{cwd:t}):null}var _t=e=>e.overallStatus==="failed"||e.overallStatus==="broken"||e.overallStatus==="interrupted";function ya(e){try{return ka(e,"utf8")}catch{return""}}async function xa(e,t){let r=t.cwd??process.cwd(),i=Date.now(),o=yt();t.onExecutionId?.(o);let n=f=>({execution_id:o,test_id:f.testId,testcase_id:f.testcaseId,project_id:f.projectId,folder_id:f.folderId,org_id:f.orgId,commit_id:f.commitId,session_name:f.sessionName,user_name:t.operator?.userName,user_email:t.operator?.userEmail}),c=await Xo({execution_id:o,title:e.title,started:new Date().toISOString(),producerVersion:he,run_kind:"author",origin:"testrun",pid:process.pid},r);t.emit(la(o,e));let s=[...new Set(e.checks.flatMap(f=>f.tags))];t.log?.("info","TESTRUN_START","Testrun started",{execution_id:o,member_count:e.checks.length,parallel:e.parallel,on_failure:e.onFailure,tags:s});let a=0,d=e.checks.map(f=>({key:f.path,value:f})),l=await wn(d,f=>t.executeMember(f.value,a++),{parallel:e.parallel,failFast:e.onFailure==="fail-fast",isFailure:_t,signal:t.signal,onStart:f=>t.emit(da(f.value)),onEnd:(f,x)=>{t.emit(ua(f.value,x)),t.log?.("info","TESTRUN_MEMBER_END","Testrun member ended",{execution_id:o,member_test_id:f.value.testId??Ee(f.value.relPath),status:x.overallStatus,result_code:x.resultCode??null,duration_s:x.durationS,run_kind:x.runKind})}}),m=l.done.find(f=>_t(f.result));for(let f of l.skipped)await ur({packDir:c,testId:Ee(f.value.relPath),definition:{path:"test.md",content:ya(f.value.path)},externalIdInput:n(f.value),tags:f.value.tags,reason:l.cancelled?"skipped: testrun cancelled":`skipped: fail-fast after ${m?Sl(m.item.value.path):"failure"}`});let p=new Map(l.done.map(f=>[f.item.value.relPath,f.result]));for(let f of e.checks){let x=Ee(f.relPath);if(Il(wa(c,"tests",x,"result.yaml")))continue;let h=p.get(f.relPath);await ur({packDir:c,testId:x,definition:{path:"test.md",content:ya(f.path)},externalIdInput:n(f),tags:f.tags,reason:`member ended '${h?.overallStatus??"broken"}' before writing its result (chrome-slot failure or pre-run crash \u2014 see member session logs)`,status:"broken"}),h&&!_t(h)&&(h.overallStatus="broken",h.exitCode=2)}let g=l.done.flatMap(f=>f.result.pendingInvestigations??[]);if(g.length>0){t.emit({type:"testrun_investigations_wait",count:g.length});let f=g.map(P=>P.exited),x,h=!1;try{await Promise.race([Promise.allSettled(f),new Promise(P=>{x=setTimeout(()=>{h=!0,P()},t.investigationTimeoutMs??12e4)})])}finally{clearTimeout(x)}if(h){for(let N of g)try{N.cancel()}catch{}let P;try{await Promise.race([Promise.allSettled(f),new Promise(N=>{P=setTimeout(N,15e3)})])}finally{clearTimeout(P)}}}try{let f=P=>P==="passed"||P==="failed"||P==="skipped"?P:"broken",x=P=>{try{let N=vt(ka(wa(c,"tests",P,"result.yaml"),"utf8"));return an(N.steps??[])}catch{return[]}},h=cn({cwd:r,members:l.done.map(P=>({path:P.item.value.path,verdict:f(P.result.overallStatus),acs:x(P.result.testId),executionId:o,startedAt:new Date().toISOString(),durationMs:Math.round(P.result.durationS*1e3),mode:"testrun",local:!t.shouldPublish}))});for(let P of h.warnings)t.log?.("warn","TESTRUN_EXEC_SYNC_WARNING",P,{execution_id:o})}catch(f){t.log?.("warn","TESTRUN_EXEC_SYNC_FAILED","Testrun exec-sync failed",{execution_id:o,error:String(f)})}try{let f=(t.coverageWriter??kt)(c,Ye(r));f.status==="skipped"&&t.log?.("warn","TESTRUN_COVERAGE_SKIPPED",`Testrun coverage/usecases.yaml not written: ${f.reason}`,{execution_id:o,reason:f.reason})}catch(f){t.log?.("warn","TESTRUN_COVERAGE_WRITER_THREW","Testrun coverage writer threw",{execution_id:o,error:String(f)})}let u=await wt(c,new Date().toISOString()),v;try{let f=await bt(Pe(o,r),"L1");v=f.valid,f.valid||t.log?.("warn","EVIDENCE_INVALID","Sealed testrun pack failed L1 validation",{execution_id:o,first_code:String(f.diagnostics?.[0]?.code??""),surface:"testrun"})}catch(f){t.log?.("warn","TESTRUN_VALIDATION_ERROR","Testrun pack validation threw",{execution_id:o,error:String(f)})}let k="skipped";if(t.shouldPublish&&!l.cancelled&&t.publish){let f=e.checks[0],x=await t.publish({testId:f.testId,sessionId:o,executionId:o,sealedPackPath:Pe(o,r),projectId:e.projectId});k=x.ok?"ok":"failed",t.emit(It(x,o))}else t.shouldPublish&&l.cancelled&&t.log?.("info","PUBLISH_SKIPPED","Testrun evidence publish skipped",{surface:"testrun",reason:"cancel"});let R=new Map(l.done.map(f=>[f.item.value.path,f.result]));for(let f of e.checks){let x=R.get(f.path);await sn(Ae(f.path),{execution_id:o,run_kind:x?.runKind??"author",status:x?_t(x)?x.overallStatus==="failed"?"failed":"broken":"passed":"skipped",valid:v,uploaded:k==="ok",at:new Date().toISOString()})}let S={tests:e.checks.length,passed:l.done.filter(f=>!_t(f.result)).length,failed:l.done.filter(f=>f.result.overallStatus==="failed").length,broken:l.done.filter(f=>["broken","interrupted"].includes(f.result.overallStatus)).length,skipped:l.skipped.length};t.log?.("info","TESTRUN_SUMMARY","Testrun summary",{execution_id:o,totals:{passed:S.passed,failed:S.failed,broken:S.broken,skipped:S.skipped},upload:k});let w=l.done.some(f=>_t(f.result)),I=l.cancelled?3:w?1:0;return t.log?.("info","TESTRUN_DONE","Testrun done",{execution_id:o,exit_code:I}),{exitCode:I,executionId:o,totals:S,upload:k}}import{readFileSync as Cl}from"fs";function Sa(e,t){if(e.mobile)return t;let{deviceName:r,osVersion:i,...o}=t;return o}function _l(e,t){return{testId:e,overallStatus:t.overallStatus,exitCode:t.exitCode,durationS:t.durationS??0,runKind:qi(!!t.anyAuthorStepRan),resultCode:t.resultCode??null,...t.pendingInvestigations?.length?{pendingInvestigations:t.pendingInvestigations}:{}}}function Ia(e){let t=e.cdpEndpoint!==void 0?{...e.passThroughOpts,cdpEndpoint:e.cdpEndpoint}:{...e.passThroughOpts};return{path:e.abs,cwd:e.cwd,opts:t,isAgent:!0,disableAskUser:!0,resolved:e.cdpEndpoint!==void 0?{...e.resolved,chrome:{...e.resolved.chrome,cdp_endpoint:e.cdpEndpoint}}:e.resolved,resolvedAuth:e.resolvedAuth,cliOverrides:{},environment:e.environment,envConfig:e.envConfig,profile:e.profile,model:e.model,creds:e.creds,configStore:e.configStore,session:e.session,skipGlobalRemoteLogger:!0,evidenceAttach:e.attach,suppressEvidenceOffer:!0,onFatalExit:r=>{throw new Error(`project/folder gate failed: ${r.split(`
24
- `)[0]}`)},signal:e.signal}}async function fr(e,t,r,i,o=ir){let n=Ee(e.relPath),c=Date.now();try{let s=await ai.attach({packDir:r.packDir,testId:n,definition:{path:"test.md",content:Cl(e.path,"utf8")},cwd:r.cwd}),a=Sa(e,r.passThroughOpts),d=Ia({abs:e.path,cwd:r.cwd,resolved:at(e.path),resolvedAuth:r.resolvedAuth,environment:r.environment,envConfig:r.envConfig,profile:r.profile,model:r.model,creds:r.creds,configStore:r.configStore,session:new Mt,passThroughOpts:a,...t?{cdpEndpoint:t.cdpEndpoint}:{},attach:s,signal:r.signal}),{host:l,lifecycle:m}=i(e),p=()=>{try{m.cleanup("runner","testrun cancelled")}catch{}};r.signal?.addEventListener("abort",p);try{let g=await o(d,l,m);return _l(n,g)}finally{r.signal?.removeEventListener("abort",p)}}catch(s){return process.stderr.write(`member ${e.relPath} broken: ${s.message}
25
- `),{testId:n,overallStatus:"broken",exitCode:2,durationS:(Date.now()-c)/1e3,runKind:"replay"}}finally{t?.release()}}async function gr(e,t,r,i,o=ir){let n=Date.now();try{let c=Sa(e,r.passThroughOpts),s=Ia({abs:e.path,cwd:r.cwd,resolved:at(e.path),resolvedAuth:r.resolvedAuth,environment:r.environment,envConfig:r.envConfig,profile:r.profile,model:r.model,creds:r.creds,configStore:r.configStore,session:new Mt,passThroughOpts:c,...t?{cdpEndpoint:t.cdpEndpoint}:{},attach:void 0,signal:r.signal}),{host:a,lifecycle:d}=i(e),l=()=>{try{d.cleanup("runner","testrun cancelled")}catch{}};r.signal?.addEventListener("abort",l);try{let m=await o(s,a,d);return{relPath:e.relPath,testId:m.ownPack?.testId,testcaseId:m.ownPack?.testcaseId,commitId:m.ownPack?.commitId,executionId:m.ownPack?.executionId,overallStatus:m.overallStatus,exitCode:m.exitCode,durationS:m.durationS??0,published:m.ownPack?m.ownPack.published?"yes":"no":"unknown"}}finally{r.signal?.removeEventListener("abort",l)}}catch(c){return process.stderr.write(`author member ${e.relPath} broken: ${c.message}
26
- `),{relPath:e.relPath,overallStatus:"broken",exitCode:2,durationS:(Date.now()-n)/1e3,published:"no"}}finally{t?.release()}}var El=e=>e.overallStatus==="failed"||e.overallStatus==="broken"||e.overallStatus==="interrupted";async function Ca(e,t){if(e.length===0)return{results:[],cancelled:!1,skipped:[]};let r=0,i=e.map(n=>({key:n.path,value:n})),o=await wn(i,n=>t.executeAuthorMember(n.value,r++),{parallel:t.parallel,failFast:!1,isFailure:El,signal:t.signal,onStart:n=>t.emit(ma(n.value)),onEnd:(n,c)=>t.emit(pa(c))});return{results:o.done.map(n=>n.result),cancelled:o.cancelled,skipped:o.skipped.map(n=>n.value)}}import{mkdtempSync as Rl,rmSync as Tl}from"fs";import{tmpdir as Pl}from"os";import{join as Al}from"path";function _a(e){let t=Promise.resolve(),r=new Map,i=n=>{try{Tl(n,{recursive:!0,force:!0})}catch{}};function o(n){let c=t.then(async()=>{if(r.has(n))throw new Error(`chrome slot ${n} already acquired (one acquire per worker index)`);let s=Rl(Al(Pl(),"kane-testrun-chrome-")),a;try{a=await e.launch({userDataDir:s,width:e.width,height:e.height,headless:e.headless})}catch(d){throw i(s),d}return r.set(n,{chrome:a,dataDir:s}),{cdpEndpoint:a.cdpEndpoint,release(){let d=r.get(n);if(d){r.delete(n);try{d.chrome.kill()}catch{}i(d.dataDir)}}}});return t=c.catch(()=>{}),c}return{acquire:o,killAll(){for(let[,n]of r){try{n.chrome.kill()}catch{}i(n.dataDir)}r.clear()}}}function Ea(){let e=new Map;return{register(t,r){e.set(t,r)},deregister(t){e.delete(t)},cleanup(t,r){let i=e.get(t);if(i){e.delete(t);try{i()}catch{}}},remoteLogger:null}}import{EventEmitter as Dl}from"events";import{Writable as $l}from"stream";function Ml(){return new $l({write(e,t,r){r()}})}function Ol(){let e=new Dl;return Object.assign(e,{isTTY:!0,setEncoding(){},setRawMode(t){return e},ref(){return e},unref(){return e},read(){return null}}),e}function Ra(){let e=process.env.KANE_TESTRUN_MEMBER_DEBUG;return e==="1"||e==="true"}function Ta(){return{...ki({isAgent:!0,log:()=>{},stdout:Ra()?process.stderr:Ml(),stdin:Ol()}),onAgentEvent:Ra()?t=>{process.stderr.write(`[member] ${JSON.stringify(t)}
27
- `)}:()=>{},onLockState:()=>{},onAdaptiveHeal:()=>{}}}import{randomUUID as Zd}from"crypto";import{appendFileSync as eu}from"fs";import{join as tu,relative as _r}from"path";import{execFileSync as Fl}from"child_process";import{existsSync as Aa}from"fs";import{isAbsolute as Da,resolve as $a,relative as Ma,sep as Oa}from"path";import{basename as Nl}from"path";function xn(e){return e==="ios"?"simulator":"emulator"}function jl(e){return e.filter(t=>t.app&&!$t(t.app.trim()))}async function Pa(e,t,r={}){let i=e.checks.filter(m=>m.mobile),o=jl(i);if(o.length===0)return{ok:!0,app:{byMember:{},uploads:[]}};let n=[...new Set(o.map(m=>m.app.trim()))];if(t.dryRun)return{ok:!0,app:{byMember:{},uploads:n.map(m=>({path:m,appId:"",source:"dry-run"}))}};let c=r.upload??ko,s=new Map,a=[],d=[];for(let m of n){let p=o.find(u=>u.app.trim()===m).platform,g=await c({path:m,type:xn(p),env:t.env,orgId:t.orgId,userId:t.userId,auth:{username:t.auth.username,accessKey:t.auth.accessKey,orgId:t.orgId},baseUrl:it(t.env),...t.onProgress?{onProgress:t.onProgress}:{}});if(wo(g)){d.push({code:"mobile_app_upload_failed",detail:`${Nl(m)} could not be uploaded, and the grid has no other way to get it: ${g.reason}
28
- Fix the upload, or set the file's \`app:\` to an APP\u2026 id from \`kane-cli apps list --target ${xn(p)}\`.`});continue}s.set(m,g.appId),a.push({path:m,appId:g.appId,source:g.fromCache?"cache":"uploaded"})}if(d.length)return{ok:!1,errors:d};let l={};for(let m of o)l[m.relPath]=s.get(m.app.trim());return{ok:!0,app:{byMember:l,uploads:a}}}function hr(e,t){return`project conflict: this profile is configured for project ${e}, but the selected members were authored in project ${t}.
18
+ `}function kn(e){let t=e.indexOf("--"),r=t===-1?e:e.slice(0,t),s;for(let o=0;o<r.length;o++)r[o]==="--mode"?s=r[++o]:r[o].startsWith("--mode=")&&(s=r[o].slice(7));return s==="agent"}function Yi(e,t,r=50){let s=!1,o=(n,c)=>{if(!c)return;let i=n.line(c);i!=null&&t(i)};return{eager(){for(let n of e)n.promise.then(c=>{s||o(n,c)}).catch(()=>{})},async bounded(){if(s)return;let n=new Promise(i=>{setTimeout(()=>i(null),r).unref?.()}),c=await Promise.all(e.map(i=>Promise.race([i.promise.catch(()=>null),n])));s=!0,c.forEach((i,a)=>o(e[a],i))},silence(){s=!0}}}function Hi(e,t){return t||e==="context"?"silence":e==="design"?"bounded":"eager"}import{join as cl}from"path";function Gi(e){let t=e.command("testmd").description("Manage test.md files (run, list, status, delete, export, sync)").action(async()=>{process.stdin.isTTY||(process.stderr.write(`error: testmd requires a sub-action in non-TTY mode (run | list | status | delete | export | sync)
19
+ `),process.exit(2));let{runListTui:r,resolveCurrentOrgId:s}=await import("./testmd-actions-EXSVQRHQ.js"),o=await s({});o.ok||process.exit(o.code),process.exit(await r(o.orgId))});dl(t),ul(t),ml(t),pl(t),fl(t),gl(t)}function ll(e,t){return t.concat(e)}function dl(e){e.command("run <path>").description("Run a test from a *_test.md file").option("--url <url>","Start URL for the first step (overrides frontmatter url: and config default_url)").option("--headless","Run Chrome in headless mode").option("--max-steps <n>","Max agent steps","50").option("--timeout <seconds>","Kill after N seconds").option("--cdp-endpoint <url>","Connect to existing Chrome via CDP").option("--ws-endpoint <url>","Playwright WebSocket endpoint").option("--global-context <file>",`Override global context (default: ${cl(z,"global-memory.md")})`).option("--local-context <file>","Override local context (default: .testmuai/context.md in cwd)").addOption(new J("--model <name>","Model override").hideHelp()).option("--variables <json>","Inline variables JSON").option("--variables-file <path>","Load variables from file").option("--dataset-id <id>","Test Manager dataset whose row supplies the ${column} parameters (overrides the file's dataset:)").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (overrides the file's dataset.row; a missing or unknown id lists the rows)").option("--session-context <json>","Session context JSON (prior runs)").addOption(new J("--cft","Use Playwright Chromium instead of managed Chrome").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").option("--mode <name>","Run mode: action | testing").option("--assertion-mode <mode>","Assertion mode: dom (default \u2014 DOM extraction & assertions, vision fallback) | visual (vision only)").option("--final-validation <on|off>","Final validation: append the system cp_final checkpoint. Overrides config (default: off)").option("--agent","Agent mode: plain NDJSON output, no colors/UI").option("--task-skills","Enable domain-specific task skills (experimental)").addOption(new J("--local","Skip TMS integration (no uploads, no variables/secrets push)").hideHelp()).option("--allow-missing-url","Non-TTY only: proceed from the browser's current page instead of failing when the first step has no start URL (frontmatter url:/--url still used)").option("--code-export","Generate code export after upload").option("--code-language <lang>","Code-export language (python|javascript)").option("--name <name>","Persist session under this name").option("--target <name>","Where to run: desktop | emulator | simulator (default: the file's `target:`, else desktop)").option("--device-name <name>","Which device, when the target is mobile: the name as `kane-cli devices list` shows it. The OS version comes from --os-version or the file's os_version:").option("--os-version <version>","The device's OS version (e.g. 17.5, 14). Alone = re-version the file's device (or any device on that version)").option("--app <path|AppId>","App under test, when the target is mobile: a build (.apk / .zip of the .app) or an APP\u2026 id from your uploads. Overrides the file's `app:`").option("--skip-code-validation","Skip post-codegen validation").option("--no-skip-code-validation","Force post-codegen validation").option("--on-lock-conflict <mode>","lock conflict policy: readonly|fail|wait",t=>{if(t!=="readonly"&&t!=="fail"&&t!=="wait")throw new Error(`--on-lock-conflict must be readonly|fail|wait, got: ${t}`);return t}).option("--push","always commit at end-of-run (no retry semantics)").option("--no-adaptive-heal","disable adaptive heal \u2014 a replay miss becomes terminal instead of re-authoring the failing tail (default: heal on, 3 attempts then a full re-author)").addOption(new J("--retry","(retired) adaptive heal is on by default").hideHelp()).addOption(new J("--retry-count <n>","(retired) heal budget is fixed at 3").argParser(t=>{let r=parseInt(t,10);if(Number.isNaN(r)||r<0)throw new Error(`--retry-count must be a non-negative integer, got: ${t}`);return t}).hideHelp()).option("--author","re-author every step in place on the test's existing identity and commit a new version (a never-authored test takes the first-run path)").addOption(new J("--no-evidence-publish","skip the replay evidence publish (blob upload + TMS /evidence/ingest) \u2014 the run leaves no execution record in TMS").hideHelp()).addOption(new J("--no-testmd-sync","skip the testmd bundle push before the commit \u2014 the caller owns the bundle for that commit").hideHelp()).option("--bug-detection <mode>","detect product bugs while authoring: off|stop|continue (stop halts the run on a confirmed bug; continue records it and keeps going). Overrides `config set-bug-detection`. Authoring steps only \u2014 replay failures always investigate.",t=>{if(t!=="off"&&t!=="stop"&&t!=="continue")throw new Error(`--bug-detection must be off, stop or continue, got: ${t}`);return t}).action(async(t,r)=>{let{retiredRetryFlagsNotice:s}=await import("./replay-policy-A62KXE6Y.js"),o=s(r);o&&process.stderr.write(o+`
20
+ `);let{runTestMdFile:n}=await import("./run-test-md-RI5RXVFU.js"),c=await n(t,r);process.exit(c)})}function ul(e){e.command("list").description("List *_test.md files in the working directory (recursive)").option("--root <dir>","Root directory to scan (default: cwd)").option("--ignore <name>","Skip a directory by name (repeatable)",ll,[]).option("--json","Force NDJSON output even on TTY").action(async t=>{let{runListAction:r,resolveCurrentOrgId:s}=await import("./testmd-actions-EXSVQRHQ.js"),o=await s({json:!!t.json});o.ok||process.exit(o.code),process.exit(await r(t,o.orgId))})}function ml(e){e.command("status <path>").description("Print local meta.json for a *_test.md (no live TMS check in v1)").action(async t=>{let{runStatusAction:r,resolveCurrentOrgId:s}=await import("./testmd-actions-EXSVQRHQ.js"),o=await s({});o.ok||process.exit(o.code),process.exit(await r(t,o.orgId))})}function pl(e){e.command("delete <path>").description("Remove output-<stem>/ and the *_test.md source file (TMS untouched)").option("--yes","Skip confirmation prompt (required in non-TTY)").action(async(t,r)=>{let{runDeleteAction:s,resolveCurrentOrgId:o}=await import("./testmd-actions-EXSVQRHQ.js"),n=await o({});n.ok||process.exit(n.code),process.exit(await s(t,!!r.yes,n.orgId))})}function fl(e){e.command("export <path>").description("Generate standalone test code (Playwright)").option("--language <lang>","python|javascript (falls back to tui-config)").option("--output <dir>","Override output dir (default: output-<stem>/playwright-<lang>-code/)").option("--force","Overwrite an existing local export").action(async(t,r)=>{let{runExportAction:s,resolveCurrentOrgId:o}=await import("./testmd-actions-EXSVQRHQ.js"),n=await o({});n.ok||process.exit(n.code),process.exit(await s(t,r,n.orgId))})}function gl(e){e.command("sync <path>").description("Zip the testmd + imports + replay outputs and push {commit_id}-testmd.zip to cloud").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").action(async(t,r)=>{let{runSyncAction:s,resolveSyncAuth:o}=await import("./testmd-actions-EXSVQRHQ.js"),n=await o(r);n.ok||process.exit(n.code),process.exit(await s(t,n))})}async function fr(e){if(e==="agent")return;let{warnIfBehind:t}=await import("./store-guard-PIA2DYZX.js"),{contextDir:r}=await import("./paths-JCYX6UWL.js");await t(r(process.cwd()),s=>process.stderr.write(s+`
21
+ `))}function qi(e){let t=e.command("context").description("Assurance context graph (.context/): ingest sources, extract use-cases, list nodes").action((a,d)=>{d.args.length>0&&d.error(`error: unknown command '${d.args[0]}'`,{exitCode:2,code:"commander.unknownCommand"}),d.help()});t.command("ingest <src...>").description("Land source files into .context/ and extract them \u2014 the one-flow entry. On a TTY this continues into the interactive extract chat; --mode ci or piped stdin lands only").option("--as <id>","Ingest AS this existing source id \u2014 a new VERSION: moves its head, dependents go stale (single file only)").option("--mode <mode>","interactive | agent | ci | override \u2014 how the extraction runs. ci (and headless without --mode) lands only").option("--plan","Extraction stops after the proposal \u2014 print it, commit nothing").option("--force","Extract even if the landed snapshot was already extracted").option("--trust <dial>","Extraction trust dial: auto (default) | hold (headless only)").action(async(a,d)=>{let{ingestCommand:l}=await import("./ingest-cmd-TQ4ARSDE.js");process.exit(await l(a,d))}),t.command("extract").description("Interactively extract use-cases from ingested sources via the context agent").option("--plan","Stop after the proposal \u2014 print it, commit nothing").option("--apply <path>","NOT IMPLEMENTED YET \u2014 will commit a saved --plan proposal (refuses loudly today)").option("--mode <mode>","Ask policy: interactive | agent | ci | override. TTY defaults to interactive chat; REQUIRED when headless").option("--force","Re-extract sources even if their current snapshot was already extracted").option("--resume <sid>","Resume a paused session (state under .context/sessions/)").option("--message <text>","With --resume: answer the pending questions (or steer) in plain words \u2014 the agent maps your statement itself").option("--source <id>","Extract exactly this ingested source \u2014 the explicit path for su-conv-* conversation sources, which the default sweep skips").option("--queued","(removed) the queue is gone \u2014 extract sweeps every pending source by default; this flag refuses with guidance for one release").option("--trust <dial>","Per-run trust dial: auto (new items commit derived into review \u2014 the default everywhere) | hold (everything new HELD; headless only \u2014 refused under interactive). ci refuses the flag entirely").option("--answer <pairs...>","With --resume --mode agent: answer a pending question/panel BY ID \u2014 <qid-or-panelId>=<option number (1-based) or free text>, repeatable").option("--with-source <ref>","With --resume: land this file/URL FIRST and set the pending questions aside \u2014 the agent reads the source, narrates what it settled, and re-asks what's still open").action(async a=>{let{extractCommand:d}=await import("./extract-cmd-RKEE32FN.js");process.exit(await d(a))}),t.command("sessions [action] [sid]").description("List resumable sessions; `sessions show <sid>` prints pending questions + assumed defaults; `sessions clean [sid]` GCs expired/named ones").option("--all","clean: remove ALL sessions (incl. corrupt), not just expired").option("--json","JSON output").action(async(a,d,l)=>{let{sessionsCommand:m}=await import("./sessions-cmd-DV442ZCY.js");process.exit(await le("sessions",()=>m(a,l,d)))});let r="interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)",s=(a,d)=>[...d,a],o=async(a,d,l,m="sync")=>{let{syncCommand:p}=await import("./sync-cmd-VFVTFIIJ.js");process.exit(await le(m,()=>p(a,d,l),{mode:l.mode}))},n=a=>{i.opts().answer.length>0&&a.error("error: unknown option '--answer' (it belongs to kane-cli context sync [name] and kane-cli context pull)",{exitCode:2,code:"kane.answerOnSubcommand"})},c=a=>({...i.opts().mode!==void 0?{mode:i.opts().mode}:{},...a}),i=t.command("sync [name]").description("Get level with a location: finish an open rebase, take the location's new records, publish yours. Subcommands: setup, add, list, remove, status, doctor").option("--answer <id=choice>","Answer a rebase decision headless: <decision id>=<keep-theirs | apply-mine | apply-mine-as-new>, repeatable; only when a rebase is open",s,[]).option("--mode <mode>",r).action(async(a,d)=>o(a,[],{...d,answer:d.answer.length>0?d.answer:void 0}));i.command("setup").description("Guided setup: share context through GitHub, S3 or a folder, or join your team").option("--mode <mode>",r).action(async(a,d)=>{n(d);let{setupCommand:l}=await import("./sync-setup-R7BZDE24.js");process.exit(await l(c(a)))}),i.command("add <name> <descriptor>").description("Check a location (GitHub repository, S3 bucket or folder) and bind this store to it under <name>").option("--credential-env <VAR>","s3: read the access key from $VAR_ID and the secret from $VAR_SECRET, stored under the user config dir with mode 0600").option("--credential-file <path>","s3: read a JSON file {accessKeyId, secretAccessKey}, stored under the user config dir with mode 0600").option("--mode <mode>",r).action(async(a,d,l,m)=>{n(m),await o("add",[a,d],c(l))}),i.command("list").description("The locations this store is bound to").option("--json","JSON output").option("--mode <mode>",r).action(async(a,d)=>{n(d),await o("list",[],c(a))}),i.command("remove <name>").description("Forget a location (its witness is kept)").option("--mode <mode>",r).action(async(a,d,l)=>{n(l),await o("remove",[a],c(d))}),i.command("status [name]").description("Compare this store with a location and list the open rebase decisions; never writes").option("--show <n>","One moved record in full, by its position").option("--json","JSON output: the relation, rebase_id, decisions").option("--mode <mode>",r).action(async(a,d,l)=>{n(l),await o("status",a===void 0?[]:[a],c(d))}),i.command("doctor").description("What the store looks like: an interrupted reset, the chain, every rebase with its id; never writes unless asked").option("--abort","Undo an interrupted reset (before its import); else close the open rebase, keeping what was reapplied").option("--export <dir>","Build the pre-rebase store in <dir> as its own store (chain, envelopes, proposals, sessions, side files, test files)").option("--from <rebase-id>","With --export: which rebase (default: the open one, else the only one)").option("--json","JSON output").option("--mode <mode>",r).action(async(a,d)=>{n(d),await o("doctor",[],c(a))}),t.command("pull [name]").description("Take a location's new records: verified in full, then imported. Finishes an open rebase first").option("--rebase","You and the location both added work after the shared position: your records after it are saved, the location's are taken, yours are reapplied; nothing on the location is rewritten").option("--yes","Confirms replacing this store's records after the shared position (they are saved first); it does not answer rebase decisions").option("--answer <id=choice>","Answer a rebase decision headless: <decision id>=<keep-theirs | apply-mine | apply-mine-as-new>, repeatable; only when a rebase is open",s,[]).option("--mode <mode>",r).action(async(a,d)=>{let{pullCommand:l}=await import("./sync-cmd-VFVTFIIJ.js");process.exit(await le("pull",()=>l(a,{...d,answer:d.answer.length>0?d.answer:void 0}),{mode:d.mode}))}),t.command("push [name]").description("Push this store's new records, their blobs and proposals to a location; refuses when the location has records this store has not pulled").option("--mode <mode>","interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)").action(async(a,d)=>{let{pushCommand:l}=await import("./sync-cmd-VFVTFIIJ.js");process.exit(await le("push",()=>l(a,d),{mode:d.mode}))}),t.command("clone [descriptor] [dir]").description("Create a store in [dir] (default: the location's last name part) from a location <descriptor>, bound to it as `origin`").option("--credential-env <VAR>","s3: read the access key from $VAR_ID and the secret from $VAR_SECRET, stored under `origin` for the clone").option("--credential-file <path>","s3: read a JSON file {accessKeyId, secretAccessKey}, stored under `origin` for the clone").option("--mode <mode>","interactive | agent | ci | override \u2014 agent rides the NDJSON envelope (done-last)").action(async(a,d,l)=>{let{cloneCommand:m}=await import("./sync-cmd-VFVTFIIJ.js");process.exit(await le("clone",()=>m(a,d,l),{mode:l.mode}))}),t.command("fsck").description("Verify the full commit chain and check the derived projection for drift").option("--json","Print the full structured report as one JSON object (issues carry code + detail + ecids)").action(async a=>{let{fsckCommand:d}=await import("./maintenance-cmd-EJ2RAMWB.js");process.exit(await le("fsck",l=>d(l,a)))}),t.command("locks",{hidden:!0}).description("Show held context/UC locks and waiters (read-only)").option("--json","Machine output (plain array, no NDJSON envelope \u2014 not a room verb)").action(async a=>{let{runLocksCommand:d}=await import("./locks-cmd-67OHQZNV.js"),{contextDir:l}=await import("./paths-JCYX6UWL.js");process.exit(d(l(process.cwd()),a,m=>process.stdout.write(m+`
22
+ `)))}),t.command("rebuild").description("Wipe .context/derived and rebuild it from the verified commit chain").option("--yes","Skip the confirmation prompt (required when headless)").action(async a=>{let{rebuildCommand:d}=await import("./maintenance-cmd-EJ2RAMWB.js");process.exit(await le("rebuild",()=>d(a),{write:!0}))}),t.command("list").description("List context graph nodes").option("--type <t>","Filter by node label (source | usecase)").option("--inferred","Only derived (unreviewed) nodes").option("--stale","Only stale/orphaned nodes").option("--all","Include superseded node versions").option("--json","JSON output").action(async a=>{let{listCommand:d}=await import("./list-cmd-UWGJRGKF.js");process.exit(await le("list",()=>d(a)))}),t.command("view").description("Render the context graph as an interactive HTML page and open it in the browser (snapshot)").option("--out <path>","Write the HTML to <path> instead of a temp file").option("--open","Force-open the browser even when non-TTY (piped)").option("--no-open","Write the file but do not open the browser").option("--json","Print the computed view payload as JSON and exit (no HTML)").action(async a=>{let{viewCommand:d}=await import("./view-cmd-RLO7AP4X.js");process.exit(await le("view",()=>d(a)))}),t.command("retire <source_id>").description("Retire a source (head \u2192 null + tombstone record); reversible via revert").option("--reason <text>","Why this source is being retired").option("--yes","Skip the confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d)=>{let{retireCommand:l}=await import("./lifecycle-cmd-DB5EFO2O.js");process.exit(await le("retire",async()=>(await fr(d.mode),l(a,d)),{write:!0,mode:d.mode}))}),t.command("name [ref] [slug]").description("Assign a stable kebab-case name to a node (ref = cid or existing slug); --backfill assigns logical ids to all unnamed live nodes").option("--backfill","assign label-prefixed logical ids (uc-/sc-/ac-/t-\u2026) to every live unnamed node").option("--yes","Skip the --backfill confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d,l)=>{let{nameCommand:m,nameBackfillCommand:p}=await import("./lifecycle-cmd-DB5EFO2O.js");l.backfill&&process.exit(await le("namebackfill",()=>p(l),{mode:l.mode,streamVerb:"name"})),process.exit(await le("name",async()=>(await fr(l.mode),m(a,d,l)),{write:!0,mode:l.mode}))}),t.command("revert <seq>").description("Invert a record's effects via a compensation record \u2014 history is never rewritten").option("--reason <text>","Why this record is being reverted").option("--yes","Skip the confirmation prompt (required when headless)").option("--mode <mode>",r).action(async(a,d)=>{let{revertCommand:l}=await import("./lifecycle-cmd-DB5EFO2O.js");process.exit(await le("revert",async()=>(await fr(d.mode),l(a,d)),{write:!0,mode:d.mode}))}),t.command("review").description("Walk a review queue; verdicts land as ONE batched record").option("--queue <q>","derived (default) | skipped | archived | drift").option("--json","NDJSON output (drift listing + --verdicts outcomes)").option("--verdicts <file>",'headless verdict input: JSON array of {"ref", "resolution", ...} \u2014 atomic, works with or without a TTY').option("--allow-archive","Apply archives headlessly (requires --because; refused under --mode ci)").option("--because <reason>","audit reason stamped on headless archives (required with --allow-archive)").option("--mode <m>","agent | ci \u2014 ci refuses archives under ANY flag").option("--approve <refs...>","structured verdict: approve these refs (temp_ref/cid/logical id)").option("--skip <refs...>","structured verdict: skip these refs (no fact \u2014 stays queued)").option("--defer <refs...>","structured verdict: defer these refs (no fact \u2014 stays queued)").action(async a=>{let{reviewCommand:d}=await import("./review-cmd-6DNGXV5E.js");process.exit(await le("review",()=>d(a)))}),t.command("explain <ref>").description("Replay the recorded reasoning + lineage for a node (no model call)").option("--json","JSON output").action(async(a,d)=>{let{explainCommand:l}=await import("./explain-cmd-USGRZFBY.js");process.exit(await le("explain",()=>l(a,d)))})}function zi(e){let t=e.command("design").description("Test design engine: turn a committed use-case into ACs, scenarios, and 1:1 tests").action((r,s)=>{s.args.length>0&&s.error(`error: unknown command '${s.args[0]}'`,{exitCode:2}),s.help()});t.command("tests").description("Design the assurance for ONE committed use-case (conversational; chat is the default)").option("--use-case <ref>","The use-case to design \u2014 logical id (uc-\u2026) or cid (optional with --resume: the session remembers it)").option("--max <n>","Budget ceiling: max scenario+test pairs (NO ceiling when omitted \u2014 the agent estimates and asks)",r=>Number(r)).option("--strength <s>","Manual covering-array strength override: pairwise | 3-wise").option("--mode <mode>","Ask policy: interactive | agent | ci | override. TTY defaults to interactive chat; REQUIRED when headless").option("--force","Redesign a use-case that already has a live design (supersedes its scenario+test pairs)").option("--resume <sid>","Resume a paused design session (state under .context/sessions/)").option("--message <text>","With --resume: answer the pending questions (or steer) in plain words \u2014 the agent maps your statement itself").option("--plan","Transcription only \u2014 print each finalize payload, commit nothing").option("--allow-unreviewed","Design against an unreviewed use-case without approving it first").option("--phase <name>","Enter the design at this phase (grounding | acs | scenarios | wiring | tests), re-seeded from committed prior phases").option("--answer <pairs...>","With --resume --mode agent: answer a pending question/panel BY ID \u2014 <qid-or-panelId>=<option number (1-based) or free text>, repeatable").action(async r=>{let{designTestsCommand:s}=await import("./bind-LY362KX7.js");process.exit(await s(r))}),t.command("explain <ref>").description("Replay WHY a designed item looks the way it does \u2014 sidecar + recorded judgements, zero fresh AI").action(async r=>{let{designExplainCommand:s}=await import("./explain-cmd-R45I5MT7.js");process.exit(await s(r))})}function Xi(e){let t=e.command("maintain").description("Keep the assurance suite true as sources change: reconcile").action((r,s)=>{s.args.length>0&&s.error(`error: unknown command '${s.args[0]}'`,{exitCode:2}),s.help()});t.command("evolve [ref]").description("Re-design the parent use-case of a test/scenario/AC/use-case \u2014 unaffected items are preserved verbatim; reports the pair diff").option("--from-stale","Evolve every use-case with stale designed entities (deduped, per-UC confirm)").option("--because <reason>","Re-design a FRESH target anyway \u2014 the reason becomes the change delta and lands in provenance").action(async(r,s)=>{let{evolveCommand:o}=await import("./evolve-cmd-CEYGGIWA.js");process.exit(await o(r,s))}),t.command("reconcile").description("Reconcile a changed source: the head lands, extraction runs over the change, and every proposed change HOLDS as a review card \u2014 approve / reject / defer, nothing commits without your verdict (the in-chat review is the TTY default)").option("--from <file>","The NEW version of the source document (a file path)").option("--source-id <id>","The EXISTING source this file succeeds \u2014 its head moves; see `kane-cli context list --type source`").option("--plan","Preview: the head-move lands (the change fact), everything else is STAGED into the stored plan \u2014 nothing suite-side commits").option("--apply [path]","Walk a STORED plan (REMOVE stays plan-only). Bare = the latest plan behind an approval prompt; a path picks one; with --from it recomputes live").option("--mode <mode>","interactive | agent | ci | override \u2014 TTY defaults to the in-chat card review; headless requires one").action(async r=>{let{reconcileCommand:s}=await import("./reconcile-cmd-VJPEY7YD.js");process.exit(await s(r))})}function Qi(e){e.command("cover").description("Two-axis coverage: depth proven by an evidence pack + completeness owed by the live graph").enablePositionalOptions().option("--from <pack>","Evidence pack to read (dir, sealed file, or execution id; default: newest in .testmuai/evidence)").option("--json","Machine-readable output").option("--mode <mode>","interactive | agent | ci \u2014 agent/ci ride the NDJSON envelope (done-last + next)").action(async(r,s)=>{s.args.length>0&&s.error(`error: unknown command '${s.args[0]}'`,{exitCode:2});let{coverCommand:o}=await import("./cover-cmd-J3CTQT3R.js");process.exit(await le("cover",()=>o(r)))}).command("gaps [uc]").description("Dual-axis coverage ribbon \u2014 designed \xD7 proven from the live graph; pass a use-case id for its full dossier").option("--stage <stage>","design | cover | all (default all)").option("--top <n>","Bound pending rows per use-case in the --json document (table output is never truncated)",r=>Number(r)).option("--rollup <rollup>","Proven-axis formula: lenient | strict (default lenient)").option("--json","Machine-readable nested document").option("--mode <mode>","interactive | agent | ci \u2014 agent/ci ride the NDJSON envelope (done-last + next)").action(async(r,s)=>{let{gapsCommand:o}=await import("./gaps-cmd-WL6P6YKS.js");process.exit(await le("gaps",()=>o(r,s)))})}var $r=je(At(),1);var Fe=je(At(),1);function ea(e){return{members:e.map(t=>({...t,status:"pending"})),summary:null,done:null}}function Zi(e,t){return typeof t!="string"||t.length===0?!1:t===e.relPath||t.endsWith("/"+e.relPath)}function hl(e){return e==="passed"?"passed":"failed"}function ta(e,t){switch(t.type){case"testrun_member_start":case"testrun_authored_member_start":return{...e,members:e.members.map(r=>Zi(r,t.path)?{...r,status:"running"}:r)};case"testrun_member_end":case"testrun_authored_member_end":return{...e,members:e.members.map(r=>Zi(r,t.path)?{...r,status:hl(t.status),durationS:t.duration_s}:r)};case"testrun_summary":return{...e,summary:{execution:t.execution??null,authored:t.authored??[],totals:t.totals,durationS:t.duration_s,upload:t.upload,cancelled:!!t.cancelled}};case"testrun_done":return{...e,done:{executionId:t.execution_id,overallStatus:t.overall_status}};default:return e}}var Y=je(ft(),1);function ra(e){return e<60?`${e.toFixed(1)}s`:`${Math.floor(e/60)}m ${Math.round(e%60)}s`}function na({member:e}){let t=e.status==="running",r=e.status==="passed",s=e.status==="failed",o=e.durationS!=null?ra(e.durationS):"";return(0,Y.jsxs)(ce,{children:[(0,Y.jsx)(ce,{width:3,children:t?(0,Y.jsx)(ro,{}):r?(0,Y.jsx)(G,{color:q.green,bold:!0,children:"\u2713"}):s?(0,Y.jsx)(G,{color:q.red,bold:!0,children:"\u2717"}):(0,Y.jsx)(G,{color:q.muted,children:"\u25CB"})}),(0,Y.jsxs)(ce,{flexGrow:1,children:[(0,Y.jsx)(G,{color:s?q.red:q.dim,children:e.relPath}),e.memberClass==="author"&&(0,Y.jsx)(G,{color:q.purple,children:" authoring"})]}),(0,Y.jsx)(ce,{width:8,justifyContent:"flex-end",children:(0,Y.jsx)(G,{color:q.dim,children:o})})]})}function vl({summary:e}){let t=e.totals,r=e.cancelled?"cancelled":t.failed>0||t.broken>0?"failed":"passed",s=r==="cancelled"?q.orange:r==="passed"?q.green:q.red,o=r==="cancelled"?"!":r==="passed"?"\u2713":"\u2717",n=r.toUpperCase(),c=`${t.passed} passed \xB7 ${t.failed} failed \xB7 ${t.broken} broken \xB7 ${t.skipped} skipped \xB7 ${t.authored} authored`;return(0,Y.jsx)(ce,{flexDirection:"column",marginTop:1,children:(0,Y.jsxs)(ce,{borderStyle:"round",borderColor:s,flexDirection:"column",paddingX:2,paddingY:1,children:[(0,Y.jsxs)(G,{bold:!0,color:s,children:[o," ",n]}),(0,Y.jsx)(G,{color:q.dim,children:c}),e.execution&&(0,Y.jsxs)(G,{color:q.dim,children:["execution ",e.execution.id,": ",e.execution.status]}),e.authored.length>0&&(0,Y.jsxs)(G,{color:q.dim,children:["authored: ",e.authored.length," test(s)"]}),(0,Y.jsxs)(G,{color:q.dim,children:[ra(e.durationS)," \xB7 upload: ",e.upload]})]})})}function oa({members:e,title:t,env:r,dispatchRef:s,onDone:o}){let{exit:n}=Gt(),{append:c}=zt(),[i,a]=(0,Fe.useState)(()=>ea(e)),[d,l]=(0,Fe.useState)(()=>new Set),m=(0,Fe.useRef)(!1),p=(0,Fe.useRef)(!1);(0,Fe.useEffect)(()=>(s.current=u=>a(v=>ta(v,u)),()=>{s.current=null}),[]),(0,Fe.useEffect)(()=>{p.current||(p.current=!0,c((0,Y.jsxs)(ce,{borderStyle:"round",borderColor:"#dc4e08",paddingX:2,children:[(0,Y.jsx)(G,{color:"#ff9500",bold:!0,children:"KaneAI CLI"}),(0,Y.jsx)(G,{color:q.dim,children:" \u2502 "}),(0,Y.jsx)(G,{color:q.dim,children:`testrun \xB7 ${t} \xB7 ${r}`})]})))},[]),(0,Fe.useEffect)(()=>{let u=i.members.filter(v=>(v.status==="passed"||v.status==="failed")&&!d.has(v.relPath));if(u.length!==0){for(let v of u)c((0,Y.jsx)(na,{member:v},v.relPath));l(v=>{let x=new Set(v);for(let T of u)x.add(T.relPath);return x})}},[i.members,d,c]),(0,Fe.useEffect)(()=>{i.done&&!m.current&&(m.current=!0,o?.(),n())},[i.done,n,o]);let g=i.members.filter(u=>!d.has(u.relPath));return(0,Y.jsxs)(ce,{flexDirection:"column",children:[g.length>0&&(0,Y.jsx)(ce,{flexDirection:"column",children:g.map(u=>(0,Y.jsx)(na,{member:u},u.relPath))}),i.summary&&(0,Y.jsx)(vl,{summary:i.summary})]})}import{existsSync as wl}from"fs";import{resolve as yl,relative as kl}from"path";import{existsSync as bl}from"fs";import{relative as sa}from"path";var ve=class extends Error{};function ia(e,t){let r=He(e);if(!bl(r))throw new ve(`--from-context needs an assurance store at ${r} \u2014 run the design flow there first, or run from the project root that holds .context`);let s=ls(r),o=Qs(cr(e)),n=[];for(let c of t){let i=c.trim();if(!i)continue;let a=s.resolve(i);if(!a)throw new ve(`--from-context: unknown id '${i}' \u2014 it does not resolve in the assurance graph`);if(s.superseded.has(a.tip))throw new ve(`--from-context: '${i}' is tombstoned (retired with no live successor) \u2014 redesign the suite or select a live test id`);let d=s.getNode(a.tip);if(d?.label!=="test")throw new ve(`--from-context: '${i}' is a ${d?.label??"unknown"} node, not a test \u2014 only test ids select members`);let l=i.toLowerCase(),m=o.get(l)??o.get(i)??[];if(m.length===0)throw new ve(`--from-context: '${i}' has no minted test file under ${cr(e)} \u2014 re-run the design for this suite, or restore the deleted file`);if(m.length>1)throw new ve(`--from-context: '${i}' is claimed by ${m.length} files (${m.map(p=>sa(e,p)).join(", ")}) \u2014 remove the duplicates`);n.push({path:m[0],relPath:sa(e,m[0]),contextId:l})}return n}async function aa(e){let t=e.cwd??process.cwd(),r=e.fromContext?.length?ia(t,e.fromContext):[],s;if(e.paths&&e.paths.length>0||r.length>0){let c=(e.paths??[]).map(i=>{let a=yl(t,i);if(!wl(a)||!a.endsWith("_test.md"))throw new ve(`not a *_test.md file: ${i}`);return{path:a,relPath:kl(t,a)}});s=[...r,...c]}else s=(await bs({root:t})).results.map(i=>({path:i.path,relPath:i.relPath}));if(e.match){let c;try{c=new RegExp(e.match)}catch(i){throw new ve(`invalid --match regex: ${i instanceof Error?i.message:i}`)}s=s.filter(i=>c.test(i.relPath))}let o=new Set,n=[];for(let c of s){if(o.has(c.path))continue;o.add(c.path);let i=ws(c.path);n.push({...c,tags:i.tags,...i.mobileTarget?{mobile:!0,platform:i.mobileTarget.platform,...i.mobileTarget.os_version?{osVersion:i.mobileTarget.os_version}:{},...i.mobileTarget.device_name?{deviceName:i.mobileTarget.device_name}:{},...i.mobileTarget.app?{app:i.mobileTarget.app}:{}}:{}})}if(e.tags&&e.tags.length>0){let c=new Set(e.tags.map(i=>i.toLowerCase()));return n.filter(i=>i.tags.some(a=>c.has(a))).sort((i,a)=>i.relPath.localeCompare(a.relPath))}return n.sort((c,i)=>c.relPath.localeCompare(i.relPath))}import{readFileSync as xl}from"fs";import{join as Sl}from"path";function ca(e){try{return JSON.parse(xl(Sl($e(e),".internal","meta.json"),"utf8"))}catch{return null}}var St=e=>typeof e=="string"&&e?e:void 0;function Cl(e,t){if(!t)return[];try{return qs(at(e.path),t.index)}catch{return[]}}function la(e,t){let r=Cl(e,t);return r.length===0?e:{...e,unresolved:r}}function da(e,t={}){let r=[],s,o,n;for(let a of e){if(a.mobile&&!t.remote&&(n??=(t.host??Qt)().supported,!n)){r.push({...a,memberClass:St(ca(a.path)?.test_id)?"replay":"author",failure:"mobile_host_unsupported"});continue}let d=ca(a.path);if(!d){r.push(la({...a,memberClass:"author"},t.variables));continue}let l={testcaseId:St(d.testcase_id),folderId:St(d.folder_id),commitId:St(d.commit_id),sessionName:St(d.session_name),tcId:xs(d.tc_id)},m=St(d.test_id),p=typeof d.org_id=="string"?d.org_id:void 0,g=typeof d.project_id=="string"?d.project_id:void 0,u=m?"replay":"author";if(s===void 0&&p&&(s=p),o===void 0&&g&&(o=g),p&&s&&p!==s){r.push({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u,failure:"org_mismatch"});continue}if(g&&o&&g!==o){r.push({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u,failure:"project_mismatch"});continue}r.push(la({...a,...l,testId:m,orgId:p,projectId:g,memberClass:u},t.variables))}let c=r.length>0&&r.every(a=>!a.failure),i=zs(r.map(a=>a.unresolved??[]));return{checks:r,valid:c,orgId:s,projectId:o,...i.length?{unresolved:i}:{}}}function Il(e){return e.tags?.length?`testrun --tags ${e.tags.join(",")}`:e.match?`testrun --match ${e.match}`:e.paths?.length?`testrun ${e.paths.length} paths`:"testrun"}async function ua(e,t={}){let r=await aa(e),s=e.cwd??process.cwd(),o=da(r,{...t,variables:{index:Ys(Ws(s))},...e.remote?{remote:!0}:{}}),n=Number(e.parallel??1),c=Number.isFinite(n)&&n>=1?Math.floor(n):1;if(c>1&&!e.remote&&r.some(i=>i.mobile))throw new ve("Mobile tests can only run one at a time on your local device. Please remove --parallel and try again.");if(e.deviceOverride&&new Set(r.filter(a=>a.mobile&&a.platform).map(a=>a.platform)).size>1)throw new ve("--device-name/--os-version name ONE device, but this selection has both emulator and simulator members \u2014 no device can serve both. Select one platform (--match/--tags) or drop the override.");return{...o,parallel:c,parallelClamped:!1,onFailure:e.onFailure??"continue",title:e.name??Il(e)}}import{basename as _l,join as Sa}from"path";import{readFileSync as Ia,existsSync as El}from"fs";import{promises as Ft}from"fs";import{existsSync as Lt}from"fs";import{join as Ze}from"path";async function gr(e){let t=e.status??"skipped",r=Ze(e.packDir,"tests",e.testId),s=Ze(r,"steps"),o=Ze(r,"logs");await Ft.mkdir(s,{recursive:!0});let n=Ze(s,".keep");Lt(n)||await Ft.writeFile(n,""),await Ft.mkdir(o,{recursive:!0});let c=Ze(o,"testrun.log");Lt(c)||await Ft.writeFile(c,e.reason+`
23
+ `);let i=Ze(r,e.definition.path);Lt(i)||await Ft.writeFile(i,e.definition.content);let a=Ze(o,"meta.yaml");if(!Lt(a)){let l=await ss(o);await os(e.packDir,e.testId,ns(l))}let d=Ze(r,"result.yaml");Lt(d)||await rs(e.packDir,e.testId,ts({testId:e.testId,status:t,definitionPath:e.definition.path,externalId:Qo(e.externalIdInput),tags:e.tags,environment:{},steps:[]}))}async function xn(e,t,r){let s=[],o=new Array(e.length).fill(!1),n=0,c=!1,i,a=!1,d=()=>{s.length<e.length&&(a=!0)};r.signal&&(r.signal.aborted?d():r.signal.addEventListener("abort",d,{once:!0}));async function l(){for(;;){if(c||r.signal?.aborted||n>=e.length)return;let p=n++,g=e[p];o[p]=!0;try{r.onStart?.(g);let u=await t(g);s.push({item:g,result:u}),r.onEnd?.(g,u),r.failFast&&r.isFailure(u)&&(c=!0)}catch(u){i=i??u,c=!0}}}let m=Math.max(1,Math.min(r.parallel,e.length));try{await Promise.all(Array.from({length:m},()=>l()))}finally{r.signal?.removeEventListener("abort",d)}if(i)throw i;return{done:s,skipped:e.filter((p,g)=>!o[g]),cancelled:a}}function ma(e){return{type:"testrun_plan",members:e.checks.map(t=>({path:t.path,test_id:t.testId,tags:t.tags,...t.mobile?{mobile:!0}:{},...t.contextId?{context_id:t.contextId}:{},...t.failure?{failure:t.failure}:{},...t.unresolved?.length?{unresolved:t.unresolved}:{}})),valid:e.valid,parallel:e.parallel,...e.parallelClamped?{parallel_clamped:!0}:{}}}function pa(e,t){return{type:"testrun_start",execution_id:e,members:t.checks.map(r=>r.relPath),parallel:t.parallel}}function fa(e){return{type:"testrun_member_start",path:e.path,test_id:e.testId,...e.contextId?{context_id:e.contextId}:{}}}function ga(e,t){return{type:"testrun_member_end",path:e.path,test_id:e.testId,status:t.overallStatus,duration_s:t.durationS,...e.contextId?{context_id:e.contextId}:{}}}function ha(e){return{type:"testrun_authored_member_start",path:e.path}}function va(e){return{type:"testrun_authored_member_end",path:e.relPath,...e.testId?{test_id:e.testId}:{},status:e.overallStatus,duration_s:e.durationS}}function Ct(e,t){return{type:"testrun_evidence_ingest",status:e.ok?"ok":"failed",evidence_id:t,...e.stage?{stage:e.stage}:{}}}function Sn(e){return{type:"testrun_summary",execution:e.execution,authored:e.authored,totals:e.totals,duration_s:e.durationS,upload:e.upload,cancelled:e.cancelled,...e.remote?{remote:e.remote}:{}}}function It(e,t){return{type:"testrun_done",execution_id:e,overall_status:t}}function ba(e){return{type:"remote_start",backend:e.backend,env:e.env}}function wa(e){return{type:"remote_device",platform:e.platform,slug:e.slug,name:e.name,os_version:e.osVersion,...e.avdId?{avd_id:e.avdId}:{},...e.pool?{pool:e.pool}:{}}}function ya(e){return{type:"remote_app",path:e.path,app_id:e.appId,source:e.source}}function hr(e){return{type:"remote_device_hint",reason:e.reason,detail:e.detail}}function ka(e){return{type:"remote_dispatched",job_id:e.jobId,job_url:e.jobUrl}}function et(e){return{type:"reconcile_merge_degraded",code:"RECONCILE_MERGE_DEGRADED",reason:e.reason,...e.detail?{detail:e.detail}:{},...e.excludedPack?{excluded_pack:e.excludedPack}:{},...e.standaloneIds?{standalone_execution_ids:e.standaloneIds}:{}}}function Vt(e){return{type:"remote_import_tape",path:e.path,status:e.status,...e.reason?{reason:e.reason}:{},...e.dispatchCommit?{dispatch_commit:e.dispatchCommit}:{},...e.gridCommit?{grid_commit:e.gridCommit}:{},...e.localCommit?{local_commit:e.localCommit}:{}}}function Ge(e){return{type:"remote_exec_sync",code:{skipped:"REMOTE_EXEC_SYNC_SKIPPED",warning:"REMOTE_EXEC_SYNC_WARNING",failed:"REMOTE_EXEC_SYNC_FAILED"}[e.status],status:e.status,reason:e.reason,...e.detail?{detail:e.detail}:{},...e.executionId?{execution_id:e.executionId}:{}}}function vr(e){return{type:"remote_coverage",code:{skipped:"REMOTE_COVERAGE_SKIPPED",failed:"REMOTE_COVERAGE_FAILED"}[e.status],status:e.status,reason:e.reason,...e.detail?{detail:e.detail}:{}}}function Cn(e){return{type:"remote_error",code:e.code,detail:e.detail}}function Ut(e){return{type:"remote_done",status:e.status,exit:e.exit,job_id:e.jobId,sessions_path:e.sessionsPath}}function xa(e,t){let r=e.unresolved??[];return r.length>0?gn(r,{cwd:t}):null}var _t=e=>e.overallStatus==="failed"||e.overallStatus==="broken"||e.overallStatus==="interrupted";function Ca(e){try{return Ia(e,"utf8")}catch{return""}}async function _a(e,t){let r=t.cwd??process.cwd(),s=Date.now(),o=yt();t.onExecutionId?.(o);let n=f=>({execution_id:o,test_id:f.testId,testcase_id:f.testcaseId,project_id:f.projectId,folder_id:f.folderId,org_id:f.orgId,commit_id:f.commitId,session_name:f.sessionName,tc_id:f.tcId,user_name:t.operator?.userName,user_email:t.operator?.userEmail}),c=await es({execution_id:o,title:e.title,started:new Date().toISOString(),producerVersion:be,run_kind:"author",origin:"testrun",pid:process.pid},r);t.emit(pa(o,e));let i=[...new Set(e.checks.flatMap(f=>f.tags))];t.log?.("info","TESTRUN_START","Testrun started",{execution_id:o,member_count:e.checks.length,parallel:e.parallel,on_failure:e.onFailure,tags:i});let a=0,d=e.checks.map(f=>({key:f.path,value:f})),l=await xn(d,f=>t.executeMember(f.value,a++),{parallel:e.parallel,failFast:e.onFailure==="fail-fast",isFailure:_t,signal:t.signal,onStart:f=>t.emit(fa(f.value)),onEnd:(f,k)=>{t.emit(ga(f.value,k)),t.log?.("info","TESTRUN_MEMBER_END","Testrun member ended",{execution_id:o,member_test_id:f.value.testId??Re(f.value.relPath),status:k.overallStatus,result_code:k.resultCode??null,duration_s:k.durationS,run_kind:k.runKind})}}),m=l.done.find(f=>_t(f.result));for(let f of l.skipped)await gr({packDir:c,testId:Re(f.value.relPath),definition:{path:"test.md",content:Ca(f.value.path)},externalIdInput:n(f.value),tags:f.value.tags,reason:l.cancelled?"skipped: testrun cancelled":`skipped: fail-fast after ${m?_l(m.item.value.path):"failure"}`});let p=new Map(l.done.map(f=>[f.item.value.relPath,f.result]));for(let f of e.checks){let k=Re(f.relPath);if(El(Sa(c,"tests",k,"result.yaml")))continue;let h=p.get(f.relPath);await gr({packDir:c,testId:k,definition:{path:"test.md",content:Ca(f.path)},externalIdInput:n(f),tags:f.tags,reason:`member ended '${h?.overallStatus??"broken"}' before writing its result (chrome-slot failure or pre-run crash \u2014 see member session logs)`,status:"broken"}),h&&!_t(h)&&(h.overallStatus="broken",h.exitCode=2)}let g=l.done.flatMap(f=>f.result.pendingInvestigations??[]);if(g.length>0){t.emit({type:"testrun_investigations_wait",count:g.length});let f=g.map(R=>R.exited),k,h=!1;try{await Promise.race([Promise.allSettled(f),new Promise(R=>{k=setTimeout(()=>{h=!0,R()},t.investigationTimeoutMs??12e4)})])}finally{clearTimeout(k)}if(h){for(let O of g)try{O.cancel()}catch{}let R;try{await Promise.race([Promise.allSettled(f),new Promise(O=>{R=setTimeout(O,15e3)})])}finally{clearTimeout(R)}}}try{let f=R=>R==="passed"||R==="failed"||R==="skipped"?R:"broken",k=R=>{try{let O=vt(Ia(Sa(c,"tests",R,"result.yaml"),"utf8"));return dn(O.steps??[])}catch{return[]}},h=un({cwd:r,members:l.done.map(R=>({path:R.item.value.path,verdict:f(R.result.overallStatus),acs:k(R.result.testId),executionId:o,startedAt:new Date().toISOString(),durationMs:Math.round(R.result.durationS*1e3),mode:"testrun",local:!t.shouldPublish}))});for(let R of h.warnings)t.log?.("warn","TESTRUN_EXEC_SYNC_WARNING",R,{execution_id:o})}catch(f){t.log?.("warn","TESTRUN_EXEC_SYNC_FAILED","Testrun exec-sync failed",{execution_id:o,error:String(f)})}try{let f=(t.coverageWriter??kt)(c,He(r));f.status==="skipped"&&t.log?.("warn","TESTRUN_COVERAGE_SKIPPED",`Testrun coverage/usecases.yaml not written: ${f.reason}`,{execution_id:o,reason:f.reason})}catch(f){t.log?.("warn","TESTRUN_COVERAGE_WRITER_THREW","Testrun coverage writer threw",{execution_id:o,error:String(f)})}let u=await wt(c,new Date().toISOString()),v;try{let f=await bt(De(o,r),"L1");v=f.valid,f.valid||t.log?.("warn","EVIDENCE_INVALID","Sealed testrun pack failed L1 validation",{execution_id:o,first_code:String(f.diagnostics?.[0]?.code??""),surface:"testrun"})}catch(f){t.log?.("warn","TESTRUN_VALIDATION_ERROR","Testrun pack validation threw",{execution_id:o,error:String(f)})}let x="skipped";if(t.shouldPublish&&!l.cancelled&&t.publish){let f=e.checks[0],k=await t.publish({testId:f.testId,sessionId:o,executionId:o,sealedPackPath:De(o,r),projectId:e.projectId});x=k.ok?"ok":"failed",t.emit(Ct(k,o))}else t.shouldPublish&&l.cancelled&&t.log?.("info","PUBLISH_SKIPPED","Testrun evidence publish skipped",{surface:"testrun",reason:"cancel"});let T=new Map(l.done.map(f=>[f.item.value.path,f.result]));for(let f of e.checks){let k=T.get(f.path);await ln($e(f.path),{execution_id:o,run_kind:k?.runKind??"author",status:k?_t(k)?k.overallStatus==="failed"?"failed":"broken":"passed":"skipped",valid:v,uploaded:x==="ok",at:new Date().toISOString()})}let S={tests:e.checks.length,passed:l.done.filter(f=>!_t(f.result)).length,failed:l.done.filter(f=>f.result.overallStatus==="failed").length,broken:l.done.filter(f=>["broken","interrupted"].includes(f.result.overallStatus)).length,skipped:l.skipped.length,creditsConsumed:l.done.reduce((f,k)=>f+(k.result.creditsConsumed??0),0)};t.log?.("info","TESTRUN_SUMMARY","Testrun summary",{execution_id:o,totals:{passed:S.passed,failed:S.failed,broken:S.broken,skipped:S.skipped},upload:x});let w=l.done.some(f=>_t(f.result)),C=l.cancelled?3:w?1:0;return t.log?.("info","TESTRUN_DONE","Testrun done",{execution_id:o,exit_code:C}),{exitCode:C,executionId:o,totals:S,upload:x}}import{readFileSync as Rl}from"fs";function Ea(e,t){if(e.mobile)return t;let{deviceName:r,osVersion:s,...o}=t;return o}function Tl(e,t){return{testId:e,overallStatus:t.overallStatus,exitCode:t.exitCode,durationS:t.durationS??0,...t.creditsConsumed!==void 0?{creditsConsumed:t.creditsConsumed}:{},runKind:Zs(!!t.anyAuthorStepRan),resultCode:t.resultCode??null,...t.pendingInvestigations?.length?{pendingInvestigations:t.pendingInvestigations}:{}}}function Ra(e){let t=e.cdpEndpoint!==void 0?{...e.passThroughOpts,cdpEndpoint:e.cdpEndpoint}:{...e.passThroughOpts};return{path:e.abs,cwd:e.cwd,opts:t,isAgent:!0,disableAskUser:!0,resolved:e.cdpEndpoint!==void 0?{...e.resolved,chrome:{...e.resolved.chrome,cdp_endpoint:e.cdpEndpoint}}:e.resolved,resolvedAuth:e.resolvedAuth,cliOverrides:{},environment:e.environment,envConfig:e.envConfig,profile:e.profile,model:e.model,creds:e.creds,configStore:e.configStore,session:e.session,skipGlobalRemoteLogger:!0,evidenceAttach:e.attach,suppressEvidenceOffer:!0,onFatalExit:r=>{throw new Error(`project/folder gate failed: ${r.split(`
24
+ `)[0]}`)},signal:e.signal}}async function br(e,t,r,s,o=lr){let n=Re(e.relPath),c=Date.now();try{let i=await ds.attach({packDir:r.packDir,testId:n,definition:{path:"test.md",content:Rl(e.path,"utf8")},cwd:r.cwd}),a=Ea(e,r.passThroughOpts),d=Ra({abs:e.path,cwd:r.cwd,resolved:at(e.path),resolvedAuth:r.resolvedAuth,environment:r.environment,envConfig:r.envConfig,profile:r.profile,model:r.model,creds:r.creds,configStore:r.configStore,session:new Mt({report:!1}),passThroughOpts:a,...t?{cdpEndpoint:t.cdpEndpoint}:{},attach:i,signal:r.signal}),{host:l,lifecycle:m}=s(e),p=()=>{try{m.cleanup("runner","testrun cancelled")}catch{}};r.signal?.addEventListener("abort",p);try{let g=await o(d,l,m);return Tl(n,g)}finally{r.signal?.removeEventListener("abort",p)}}catch(i){return process.stderr.write(`member ${e.relPath} broken: ${i.message}
25
+ `),{testId:n,overallStatus:"broken",exitCode:2,durationS:(Date.now()-c)/1e3,runKind:"replay"}}finally{t?.release()}}async function wr(e,t,r,s,o=lr){let n=Date.now();try{let c=Ea(e,r.passThroughOpts),i=Ra({abs:e.path,cwd:r.cwd,resolved:at(e.path),resolvedAuth:r.resolvedAuth,environment:r.environment,envConfig:r.envConfig,profile:r.profile,model:r.model,creds:r.creds,configStore:r.configStore,session:new Mt({report:!1}),passThroughOpts:c,...t?{cdpEndpoint:t.cdpEndpoint}:{},attach:void 0,signal:r.signal}),{host:a,lifecycle:d}=s(e),l=()=>{try{d.cleanup("runner","testrun cancelled")}catch{}};r.signal?.addEventListener("abort",l);try{let m=await o(i,a,d);return{relPath:e.relPath,testId:m.ownPack?.testId,testcaseId:m.ownPack?.testcaseId,commitId:m.ownPack?.commitId,executionId:m.ownPack?.executionId,overallStatus:m.overallStatus,exitCode:m.exitCode,durationS:m.durationS??0,creditsConsumed:m.creditsConsumed??0,published:m.ownPack?m.ownPack.published?"yes":"no":"unknown"}}finally{r.signal?.removeEventListener("abort",l)}}catch(c){return process.stderr.write(`author member ${e.relPath} broken: ${c.message}
26
+ `),{relPath:e.relPath,overallStatus:"broken",exitCode:2,durationS:(Date.now()-n)/1e3,published:"no"}}finally{t?.release()}}var Pl=e=>e.overallStatus==="failed"||e.overallStatus==="broken"||e.overallStatus==="interrupted";async function Ta(e,t){if(e.length===0)return{results:[],cancelled:!1,skipped:[]};let r=0,s=e.map(n=>({key:n.path,value:n})),o=await xn(s,n=>t.executeAuthorMember(n.value,r++),{parallel:t.parallel,failFast:!1,isFailure:Pl,signal:t.signal,onStart:n=>t.emit(ha(n.value)),onEnd:(n,c)=>t.emit(va(c))});return{results:o.done.map(n=>n.result),cancelled:o.cancelled,skipped:o.skipped.map(n=>n.value)}}import{mkdtempSync as Al,rmSync as Dl}from"fs";import{tmpdir as $l}from"os";import{join as Ml}from"path";function Pa(e){let t=Promise.resolve(),r=new Map,s=n=>{try{Dl(n,{recursive:!0,force:!0})}catch{}};function o(n){let c=t.then(async()=>{if(r.has(n))throw new Error(`chrome slot ${n} already acquired (one acquire per worker index)`);let i=Al(Ml($l(),"kane-testrun-chrome-")),a;try{a=await e.launch({userDataDir:i,width:e.width,height:e.height,headless:e.headless})}catch(d){throw s(i),d}return r.set(n,{chrome:a,dataDir:i}),{cdpEndpoint:a.cdpEndpoint,release(){let d=r.get(n);if(d){r.delete(n);try{d.chrome.kill()}catch{}s(d.dataDir)}}}});return t=c.catch(()=>{}),c}return{acquire:o,killAll(){for(let[,n]of r){try{n.chrome.kill()}catch{}s(n.dataDir)}r.clear()}}}function Aa(){let e=new Map;return{register(t,r){e.set(t,r)},deregister(t){e.delete(t)},cleanup(t,r){let s=e.get(t);if(s){e.delete(t);try{s()}catch{}}},remoteLogger:null}}import{EventEmitter as Ol}from"events";import{Writable as Nl}from"stream";function jl(){return new Nl({write(e,t,r){r()}})}function Fl(){let e=new Ol;return Object.assign(e,{isTTY:!0,setEncoding(){},setRawMode(t){return e},ref(){return e},unref(){return e},read(){return null}}),e}function Da(){let e=process.env.KANE_TESTRUN_MEMBER_DEBUG;return e==="1"||e==="true"}function $a(){return{...Is({isAgent:!0,log:()=>{},stdout:Da()?process.stderr:jl(),stdin:Fl()}),onAgentEvent:Da()?t=>{process.stderr.write(`[member] ${JSON.stringify(t)}
27
+ `)}:()=>{},onLockState:()=>{},onAdaptiveHeal:()=>{}}}import{randomUUID as nu}from"crypto";import{appendFileSync as ru}from"fs";import{join as ou,relative as Pr}from"path";import{execFileSync as Ul}from"child_process";import{existsSync as Oa}from"fs";import{isAbsolute as Na,resolve as ja,relative as Fa,sep as La}from"path";import{basename as Ll}from"path";function In(e){return e==="ios"?"simulator":"emulator"}function Vl(e){return e.filter(t=>t.app&&!$t(t.app.trim()))}async function Ma(e,t,r={}){let s=e.checks.filter(m=>m.mobile),o=Vl(s);if(o.length===0)return{ok:!0,app:{byMember:{},uploads:[]}};let n=[...new Set(o.map(m=>m.app.trim()))];if(t.dryRun)return{ok:!0,app:{byMember:{},uploads:n.map(m=>({path:m,appId:"",source:"dry-run"}))}};let c=r.upload??Co,i=new Map,a=[],d=[];for(let m of n){let p=o.find(u=>u.app.trim()===m).platform,g=await c({path:m,type:In(p),env:t.env,orgId:t.orgId,userId:t.userId,auth:{username:t.auth.username,accessKey:t.auth.accessKey,orgId:t.orgId},baseUrl:st(t.env),...t.onProgress?{onProgress:t.onProgress}:{}});if(xo(g)){d.push({code:"mobile_app_upload_failed",detail:`${Ll(m)} could not be uploaded, and the grid has no other way to get it: ${g.reason}
28
+ Fix the upload, or set the file's \`app:\` to an APP\u2026 id from \`kane-cli apps list --target ${In(p)}\`.`});continue}i.set(m,g.appId),a.push({path:m,appId:g.appId,source:g.fromCache?"cache":"uploaded"})}if(d.length)return{ok:!1,errors:d};let l={};for(let m of o)l[m.relPath]=i.get(m.app.trim());return{ok:!0,app:{byMember:l,uploads:a}}}function yr(e,t){return`project conflict: this profile is configured for project ${e}, but the selected members were authored in project ${t}.
29
29
  Dispatching would mint authored tests into ${e} while their evidence publishes to ${t}.
30
- Fix: \`kane-cli config project ${t}\`, or select only members belonging to ${e}.`}function Ll(e,t){return e.filter(r=>t.checkIgnore(r))}function Vl(e,t){try{return Fl("git",["check-ignore","-q",e],{cwd:t,stdio:"ignore"}),!0}catch{return!1}}function Na(e,t={}){let r=t.env??process.env,i=t.collectBundleFn??wi,o=t.checkIgnore??Vl,n=[];r.KANE_CLI_MODE==="hyperexecute"&&n.push({code:"on_grid",detail:"already running on a HyperExecute grid \u2014 --remote cannot re-dispatch"}),e.plan.valid||n.push({code:"invalid_plan",detail:"members do not share one org/project, or the plan is otherwise invalid"});let c=e.plan.checks.filter(u=>u.mobile),s=e.plan.checks.filter(u=>!u.mobile),a=c.filter(u=>u.platform==="android"),d=c.filter(u=>u.platform==="ios");if(c.length){let u=c.filter(w=>w.platform!=="android"&&w.platform!=="ios");u.length&&n.push({code:"mobile_remote_unsupported",detail:`${u.length} test(s) need a device --remote cannot provide (Android emulators and iOS simulators only):
30
+ Fix: \`kane-cli config project ${t}\`, or select only members belonging to ${e}.`}function Bl(e,t){return e.filter(r=>t.checkIgnore(r))}function Kl(e,t){try{return Ul("git",["check-ignore","-q",e],{cwd:t,stdio:"ignore"}),!0}catch{return!1}}function Va(e,t={}){let r=t.env??process.env,s=t.collectBundleFn??Ss,o=t.checkIgnore??Kl,n=[];r.KANE_CLI_MODE==="hyperexecute"&&n.push({code:"on_grid",detail:"already running on a HyperExecute grid \u2014 --remote cannot re-dispatch"}),e.plan.valid||n.push({code:"invalid_plan",detail:"members do not share one org/project, or the plan is otherwise invalid"});let c=e.plan.checks.filter(u=>u.mobile),i=e.plan.checks.filter(u=>!u.mobile),a=c.filter(u=>u.platform==="android"),d=c.filter(u=>u.platform==="ios");if(c.length){let u=c.filter(w=>w.platform!=="android"&&w.platform!=="ios");u.length&&n.push({code:"mobile_remote_unsupported",detail:`${u.length} test(s) need a device --remote cannot provide (Android emulators and iOS simulators only):
31
31
  `+u.map(w=>` ${w.relPath}${w.platform?` (${w.platform})`:" (frontmatter did not parse)"}`).join(`
32
32
  `)+`
33
- Run them locally (drop --remote), or deselect them (--match/--tags).`}),s.length&&n.push({code:"mobile_remote_mixed",detail:`this selection mixes ${s.length} web and ${c.length} device test(s), and one grid job runs one or the other.
33
+ Run them locally (drop --remote), or deselect them (--match/--tags).`}),i.length&&n.push({code:"mobile_remote_mixed",detail:`this selection mixes ${i.length} web and ${c.length} device test(s), and one grid job runs one or the other.
34
34
  Split it into two runs (--match/--tags), e.g. one for the device tests and one for the rest.`}),a.length&&d.length&&n.push({code:"mobile_remote_mixed_platform",detail:`this selection mixes ${a.length} emulator and ${d.length} simulator test(s), and one grid job runs one platform.
35
35
  Split it into two runs (--match/--tags), one per platform.`});let v=[...new Set(a.map(w=>w.osVersion).filter(w=>!!w))];v.length>1&&n.push({code:"mobile_os_version_split",detail:`device tests in this selection ask for different Android versions (${v.join(", ")}), and one grid job allocates one device.
36
- Split it into one run per version (--match/--tags), or pass --os-version to force one.`});let k=t.exists??Aa,R=c.filter(w=>w.app&&!$t(w.app.trim())&&!k(w.app.trim()));R.length&&n.push({code:"mobile_app_missing",detail:`${R.length} device test(s) name a build that is not on this machine:
37
- `+R.map(w=>` ${w.relPath} -> ${w.app}`).join(`
38
- `)+"\n The build is uploaded from here before dispatch, so it has to exist here. Fix the path, or set the file's `app:` to an APP\u2026 id from `kane-cli apps list`."});let S=c.filter(w=>w.app&&!$t(w.app.trim())&&k(w.app.trim())).map(w=>({m:w,why:yo(w.app.trim(),xn(w.platform))})).filter(w=>w.why!==null);S.length&&n.push({code:"mobile_app_not_uploadable",detail:`${S.length} device test(s) name a build the cloud cannot take:
39
- `+S.map(({m:w,why:I})=>` ${w.relPath}: ${I}`).join(`
40
- `)+"\n Emulators take an .apk; simulators take a .zip of the .app bundle (built for the simulator). Or set the file's `app:` to an APP\u2026 id from `kane-cli apps list`."})}e.plan.checks.some(u=>u.memberClass==="author")&&e.projectId&&e.plan.projectId&&e.projectId!==e.plan.projectId&&n.push({code:"project_authority_conflict",detail:hr(e.projectId,e.plan.projectId)});let m=e.plan.checks.filter(u=>{let v=Ma(e.cwd,$a(u.path));return v===".."||v.startsWith(`..${Oa}`)||Da(v)});m.length&&n.push({code:"member_outside_payload",detail:`${m.length} test(s) live outside the directory being dispatched (${e.cwd}), so they cannot ride the payload:
36
+ Split it into one run per version (--match/--tags), or pass --os-version to force one.`});let x=t.exists??Oa,T=c.filter(w=>w.app&&!$t(w.app.trim())&&!x(w.app.trim()));T.length&&n.push({code:"mobile_app_missing",detail:`${T.length} device test(s) name a build that is not on this machine:
37
+ `+T.map(w=>` ${w.relPath} -> ${w.app}`).join(`
38
+ `)+"\n The build is uploaded from here before dispatch, so it has to exist here. Fix the path, or set the file's `app:` to an APP\u2026 id from `kane-cli apps list`."});let S=c.filter(w=>w.app&&!$t(w.app.trim())&&x(w.app.trim())).map(w=>({m:w,why:So(w.app.trim(),In(w.platform))})).filter(w=>w.why!==null);S.length&&n.push({code:"mobile_app_not_uploadable",detail:`${S.length} device test(s) name a build the cloud cannot take:
39
+ `+S.map(({m:w,why:C})=>` ${w.relPath}: ${C}`).join(`
40
+ `)+"\n Emulators take an .apk; simulators take a .zip of the .app bundle (built for the simulator). Or set the file's `app:` to an APP\u2026 id from `kane-cli apps list`."})}e.plan.checks.some(u=>u.memberClass==="author")&&e.projectId&&e.plan.projectId&&e.projectId!==e.plan.projectId&&n.push({code:"project_authority_conflict",detail:yr(e.projectId,e.plan.projectId)});let m=e.plan.checks.filter(u=>{let v=Fa(e.cwd,ja(u.path));return v===".."||v.startsWith(`..${La}`)||Na(v)});m.length&&n.push({code:"member_outside_payload",detail:`${m.length} test(s) live outside the directory being dispatched (${e.cwd}), so they cannot ride the payload:
41
41
  `+m.map(u=>` ${u.path}`).join(`
42
42
  `)+`
43
- Run from a directory that contains them, or move them into this one.`});let p=[];for(let u of e.plan.checks)if(u.memberClass==="replay")try{let v=i(u.path);for(let k of v.files)p.push(k.abs)}catch(v){n.push({code:"bundle_error",detail:`${u.relPath}: ${v instanceof Error?v.message:String(v)}`})}else p.push(u.path);if(e.kaneDist){let u=$a(e.cwd,e.kaneDist),v=Ma(e.cwd,u);v===".."||v.startsWith(`..${Oa}`)||Da(v)?n.push({code:"kane_dist_outside_cwd",detail:`--kane-dist ${e.kaneDist} resolves outside the payload \u2014 it cannot be uploaded.`}):(t.exists??Aa)(u)?p.push(u):n.push({code:"kane_dist_missing",detail:`--kane-dist ${e.kaneDist} does not exist.
44
- Build it (npm run build in kane-cli/) and copy the dist/ dir to that path inside this project.`})}let g=Ll(p,{checkIgnore:u=>o(u,e.cwd)});return g.length&&n.push({code:"gitignored_inputs",detail:`${g.length} required input(s) are gitignored and won't reach the grid:
43
+ Run from a directory that contains them, or move them into this one.`});let p=[];for(let u of e.plan.checks)if(u.memberClass==="replay")try{let v=s(u.path);for(let x of v.files)p.push(x.abs)}catch(v){n.push({code:"bundle_error",detail:`${u.relPath}: ${v instanceof Error?v.message:String(v)}`})}else p.push(u.path);if(e.kaneDist){let u=ja(e.cwd,e.kaneDist),v=Fa(e.cwd,u);v===".."||v.startsWith(`..${La}`)||Na(v)?n.push({code:"kane_dist_outside_cwd",detail:`--kane-dist ${e.kaneDist} resolves outside the payload \u2014 it cannot be uploaded.`}):(t.exists??Oa)(u)?p.push(u):n.push({code:"kane_dist_missing",detail:`--kane-dist ${e.kaneDist} does not exist.
44
+ Build it (npm run build in kane-cli/) and copy the dist/ dir to that path inside this project.`})}let g=Bl(p,{checkIgnore:u=>o(u,e.cwd)});return g.length&&n.push({code:"gitignored_inputs",detail:`${g.length} required input(s) are gitignored and won't reach the grid:
45
45
  `+g.map(u=>` ${u}`).join(`
46
- `)+"\n Fix: un-ignore them (e.g. `!output-*/`) or commit them, then re-run."}),{ok:n.length===0,errors:n,requiredInputs:p}}import{existsSync as Hl,mkdirSync as Gl,readFileSync as ql,writeFileSync as zl}from"fs";import{isAbsolute as Xl,join as br,relative as La,sep as Ql}from"path";function ja(e){let t=[];return e.author===!0&&t.push("--author"),e.adaptiveHeal===!1&&t.push("--no-adaptive-heal"),e.testmdSync===!1&&t.push("--no-testmd-sync"),typeof e.datasetId=="string"&&e.datasetId.trim()&&t.push("--dataset-id",e.datasetId.trim()),e.datasetRow!==void 0&&e.datasetRow!==null&&String(e.datasetRow).trim()&&t.push("--dataset-row",String(e.datasetRow).trim()),t}function Fa(e){return e.length?` ${e.join(" ")}`:""}import{existsSync as Ul,readFileSync as Bl}from"fs";var Kl={deviceName:"iPhone 15",osVersion:"17.5",runson:{}},Jl={runson:"mac26",deviceName:"Galaxy A53 5G",osVersion:"15",queueTimeout:300,appiumPort:4739,androidHome:"$HOME/android-sdk-shim",globalTimeout:90,testSuiteTimeout:90,testSuiteStep:45,ios:Kl},Wl={runson:"mac",concurrency:1,timeoutMinutes:120,mobile:Jl},dt=(e,t)=>typeof e=="string"&&e.trim()!==""?e.trim():t,ut=(e,t)=>typeof e=="number"&&Number.isInteger(e)&&e>0?e:t;function Sn(e=q,t="remote-execution"){let r={};try{let c=is(t,e);Ul(c)&&(r=JSON.parse(Bl(c,"utf8")))}catch{}let i=typeof r.mobile=="object"&&r.mobile!==null?r.mobile:{},o=typeof i.ios=="object"&&i.ios!==null?i.ios:{},n=Wl;return{runson:dt(r.runson,n.runson),concurrency:ut(r.concurrency,n.concurrency),timeoutMinutes:ut(r.timeoutMinutes,n.timeoutMinutes),mobile:{runson:dt(i.runson,n.mobile.runson),deviceName:dt(i.deviceName,n.mobile.deviceName),osVersion:dt(i.osVersion,n.mobile.osVersion),queueTimeout:ut(i.queueTimeout,n.mobile.queueTimeout),appiumPort:ut(i.appiumPort,n.mobile.appiumPort),androidHome:dt(i.androidHome,n.mobile.androidHome),globalTimeout:ut(i.globalTimeout,n.mobile.globalTimeout),testSuiteTimeout:ut(i.testSuiteTimeout,n.mobile.testSuiteTimeout),testSuiteStep:ut(i.testSuiteStep,n.mobile.testSuiteStep),ios:{deviceName:dt(o.deviceName,n.mobile.ios.deviceName),osVersion:dt(o.osVersion,n.mobile.ios.osVersion),runson:Yl(o.runson)}}}}function Yl(e){if(typeof e!="object"||e===null)return{};let t={};for(let[r,i]of Object.entries(e))r.trim()!==""&&typeof i=="string"&&i.trim()!==""&&(t[r.trim()]=i.trim());return t}var Zl={android:"emulator",ios:"simulator"};function ed(e){return e.plan.checks.some(t=>t.mobile)}function Va(e){let t=e.plan.checks.find(r=>r.mobile);if(t)return t.platform==="ios"?"ios":"android"}function td(e){if(!e)return{timeouts:"",deviceDirective:"",devicePre:"",devicePostLogin:""};let{platform:t,slug:r,mobile:i}=e;return{timeouts:`globalTimeout: ${i.globalTimeout}
47
- testSuiteTimeout: ${i.testSuiteTimeout}
48
- testSuiteStep: ${i.testSuiteStep}
46
+ `)+"\n Fix: un-ignore them (e.g. `!output-*/`) or commit them, then re-run."}),{ok:n.length===0,errors:n,requiredInputs:p}}import{existsSync as zl,mkdirSync as Xl,readFileSync as Ql,writeFileSync as Zl}from"fs";import{isAbsolute as ed,join as xr,relative as Ka,sep as td}from"path";function Ua(e){let t=[];return e.author===!0&&t.push("--author"),e.adaptiveHeal===!1&&t.push("--no-adaptive-heal"),e.testmdSync===!1&&t.push("--no-testmd-sync"),typeof e.datasetId=="string"&&e.datasetId.trim()&&t.push("--dataset-id",e.datasetId.trim()),e.datasetRow!==void 0&&e.datasetRow!==null&&String(e.datasetRow).trim()&&t.push("--dataset-row",String(e.datasetRow).trim()),t}function Ba(e){return e.length?` ${e.join(" ")}`:""}import{existsSync as Jl,readFileSync as Wl}from"fs";var Yl={deviceName:"iPhone 15",osVersion:"17.5",runson:{}},Hl={runson:"mac26",deviceName:"Galaxy A53 5G",osVersion:"15",queueTimeout:300,appiumPort:4739,androidHome:"$HOME/android-sdk-shim",globalTimeout:90,testSuiteTimeout:90,testSuiteStep:45,ios:Yl},Gl={runson:"mac",concurrency:1,timeoutMinutes:120,mobile:Hl},dt=(e,t)=>typeof e=="string"&&e.trim()!==""?e.trim():t,ut=(e,t)=>typeof e=="number"&&Number.isInteger(e)&&e>0?e:t;function _n(e=z,t="remote-execution"){let r={};try{let c=li(t,e);Jl(c)&&(r=JSON.parse(Wl(c,"utf8")))}catch{}let s=typeof r.mobile=="object"&&r.mobile!==null?r.mobile:{},o=typeof s.ios=="object"&&s.ios!==null?s.ios:{},n=Gl;return{runson:dt(r.runson,n.runson),concurrency:ut(r.concurrency,n.concurrency),timeoutMinutes:ut(r.timeoutMinutes,n.timeoutMinutes),mobile:{runson:dt(s.runson,n.mobile.runson),deviceName:dt(s.deviceName,n.mobile.deviceName),osVersion:dt(s.osVersion,n.mobile.osVersion),queueTimeout:ut(s.queueTimeout,n.mobile.queueTimeout),appiumPort:ut(s.appiumPort,n.mobile.appiumPort),androidHome:dt(s.androidHome,n.mobile.androidHome),globalTimeout:ut(s.globalTimeout,n.mobile.globalTimeout),testSuiteTimeout:ut(s.testSuiteTimeout,n.mobile.testSuiteTimeout),testSuiteStep:ut(s.testSuiteStep,n.mobile.testSuiteStep),ios:{deviceName:dt(o.deviceName,n.mobile.ios.deviceName),osVersion:dt(o.osVersion,n.mobile.ios.osVersion),runson:ql(o.runson)}}}}function ql(e){if(typeof e!="object"||e===null)return{};let t={};for(let[r,s]of Object.entries(e))r.trim()!==""&&typeof s=="string"&&s.trim()!==""&&(t[r.trim()]=s.trim());return t}var nd={android:"emulator",ios:"simulator"};function rd(e){return e.plan.checks.some(t=>t.mobile)}function Ja(e){let t=e.plan.checks.find(r=>r.mobile);if(t)return t.platform==="ios"?"ios":"android"}function od(e){if(!e)return{timeouts:"",deviceDirective:"",devicePre:"",devicePostLogin:""};let{platform:t,slug:r,mobile:s}=e;return{timeouts:`globalTimeout: ${s.globalTimeout}
47
+ testSuiteTimeout: ${s.testSuiteTimeout}
48
+ testSuiteStep: ${s.testSuiteStep}
49
49
  `,deviceDirective:`framework:
50
50
  name: kane-cli
51
51
  args:
52
52
  platformName: ${t}
53
53
  isRealMobile: false
54
54
  isVirtualDevice: true
55
- queueTimeout: ${i.queueTimeout}
55
+ queueTimeout: ${s.queueTimeout}
56
56
  devices:
57
57
  - "${r}"
58
- `,devicePre:"",devicePostLogin:` - kane-cli doctor --target ${Zl[t]} --install
59
- `}}function nd(e){let t=Object.entries(e.appIds??{});return t.length===0?"":` case "$test" in
60
- `+t.map(([r,i])=>` ${Ua(r)}) KANE_APP=${i} ;;
58
+ `,devicePre:"",devicePostLogin:` - kane-cli doctor --target ${nd[t]} --install
59
+ `}}function sd(e){let t=Object.entries(e.appIds??{});return t.length===0?"":` case "$test" in
60
+ `+t.map(([r,s])=>` ${Wa(r)}) KANE_APP=${s} ;;
61
61
  `).join("")+` *) KANE_APP= ;;
62
62
  esac
63
- `}function Ua(e){return`'${e.replace(/'/g,"'\\''")}'`}function rd(e){let t=e.devicePlatform??Va(e),r=Object.keys(e.appIds??{}).length?" ${KANE_APP:+--app $KANE_APP}":"";if(t==="ios"){let i=e.deviceFlags??{};return(i.deviceName?` --device-name ${Ua(i.deviceName)}`:"")+(i.osVersion?` --os-version ${i.osVersion}`:"")+r}return t==="android"?(e.deviceLabel?.osVersion?` --os-version ${e.deviceLabel.osVersion}`:"")+r:""}function vr(e,t){let r=e;for(let[i,o]of Object.entries(t))r=r.split(`{{${i}}}`).join(o);return r}function od(e){let t=e.map(o=>({relPath:o.relPath,absPath:o.path,memberClass:o.memberClass,testId:o.testId,commitId:o.commitId}));return{discoveryCommand:`printf '%s\\n' ${t.map(o=>`'${o.relPath}'`).join(" ")}`,members:t}}function id(e,t,r=[]){let i=e.map(c=>La(t,Ae(c.absPath))),o=[...new Set(r)].filter(c=>!i.includes(c));return[...[...i,...o].map(c=>` - "${c}/**"`)," - .testmuai/evidence/**"," - artifacts/session/**"].join(`
64
- `)}function sd(e,t,r){let i=r??(a=>{try{return at(a).unitFiles.map(d=>d.file).filter(d=>d!==a)}catch{return[]}}),o=new Set(e.map(a=>a.absPath)),n=[],c=[],s=new Set;for(let a of e)for(let d of i(a.absPath)){if(o.has(d)||s.has(d))continue;s.add(d);let l=Ae(d),m=La(t,l);if(m===".."||m.startsWith(`..${Ql}`)||Xl(m)){c.push({unitAbsPath:d,reason:"outside payload cwd \u2014 cannot round-trip through the grid"});continue}let p;try{let g=br(l,".internal","meta.json");if(Hl(g)){let u=JSON.parse(ql(g,"utf8"));typeof u.commit_id=="string"&&u.commit_id&&(p=u.commit_id)}}catch{}n.push({unitAbsPath:d,tapeDir:l,relTape:m,...p?{dispatchCommitId:p}:{}})}return{tapes:n,skipped:c}}function ad(e){return e.projectId?` --project-id ${e.projectId}${e.folderId?` --folder-id ${e.folderId}`:""}`:""}var cd=new Set(["--author","--no-testmd-sync","--dataset-id","--dataset-row"]);function ld(e){return e.some(t=>cd.has(t))?he:"latest"}async function dd(e){let t=new Di(re(e.env).secretsBaseUrl),r={username:e.auth.username,accessKey:e.auth.access_key,orgId:e.orgId};await t.pushSecret({secretKey:"LT_USERNAME",secretValue:e.auth.username,...r}),await t.pushSecret({secretKey:"LT_ACCESS_KEY",secretValue:e.auth.access_key,...r})}async function Ba(e,t={}){let r=t.base??q,i=br(ss("remote-execution",r),e.jobId);Gl(i,{recursive:!0});let{discoveryCommand:o,members:n}=od(e.plan.checks),{tapes:c,skipped:s}=sd(n,e.cwd);await(t.pushSecrets??dd)(e);let a=t.config??Sn(r),d=ed(e);if(d&&!e.deviceSlug)throw new Error("device job prepared without a resolved device slug \u2014 preflight should have set one");let l=d?e.devicePlatform??Va(e):void 0;if(l==="ios"&&!e.devicePool&&!e.runson&&!t.runson)throw new Error("simulator job prepared without a resolved pool \u2014 preflight should have set one");let m=td(d?{platform:l,slug:e.deviceSlug,mobile:a.mobile}:null),p=t.runson??e.runson??(l==="ios"?e.devicePool:d?a.mobile.runson:a.runson),g=l==="ios"?ps:d?ms:ds,u=e.memberFlags??[],v=e.kaneDist?vr(us,{kaneDist:e.kaneDist}):"",k=vr(as,{runnerBody:g}),R=vr(k,{runson:p,concurrency:String(e.parallel),env:e.env,kaneVersion:t.kaneVersion??e.kaneVersion??ld(u),discoveryCommand:o,uploadPaths:id(n,e.cwd,c.map(w=>w.relTape)),projectFolderFlags:ad(e),memberFlags:Fa(u),deviceFlags:rd(e),appLookup:nd(e),kaneDistSwap:v,sessionMark:cs,sessionCopy:ls,...m}),S=br(i,".hyperexecute.yaml");return zl(S,R),{job:e,jobDir:i,yamlPath:S,members:n,importTapes:c,...s.length>0?{skippedImports:s}:{}}}import{spawn as ud,execFileSync as md}from"child_process";import{join as pd}from"path";function fd(e){let t=e.match(/Job Link:\s*(https?:\/\/\S*?[?&]jobId=([0-9a-fA-F-]{36}))/);return t?{url:t[1],jobId:t[2]}:null}function gd(){try{return md("hyperexecute",["--version"],{stdio:"ignore",timeout:2e3}),!0}catch{return!1}}function hd(e){return e.binaryPath?e.binaryPath:(e.onPath??gd)()?"hyperexecute":hn()}function Ka(e,t){if(!e)return;let r="";e.on("data",i=>{r+=String(i);let o;for(;(o=r.indexOf(`
65
- `))>=0;)t(r.slice(0,o)),r=r.slice(o+1)}),e.on("end",()=>{r.length&&t(r)})}async function Ja(e,t={}){let r=e.job,i=hd(t),o=pd(e.jobDir,"dl"),n=["--user",r.auth.username,"--key",r.auth.access_key,"--env",r.env,"--config",e.yamlPath,"--concurrency",String(r.parallel),"--download-artifacts","--download-artifacts-path",o],s=(t.spawnImpl??((u,v,k)=>ud(u,v,{cwd:k.cwd})))(i,n,{cwd:r.cwd}),a="",d="",l=u=>{if(t.onLine?.(u),!a){let v=fd(u);v&&(a=v.jobId,d=v.url)}};Ka(s.stdout,l),Ka(s.stderr,l);let m=!1,p=()=>{m=!0;try{s.kill("SIGTERM")}catch{}};t.signal&&(t.signal.aborted?p():t.signal.addEventListener("abort",p,{once:!0}));let g=await new Promise(u=>{s.on("close",v=>u(m?3:typeof v=="number"?v:1)),s.on("error",()=>u(1))});return t.signal?.removeEventListener?.("abort",p),{job:r,prepared:e,hxJobId:a,jobUrl:d,downloadDir:o,exitCode:g,cancelled:m}}import{existsSync as Fe,readdirSync as _n,statSync as Ga,mkdirSync as vd,cpSync as In,readFileSync as qa,writeFileSync as kr,rmSync as wr,mkdtempSync as bd}from"fs";import{tmpdir as wd}from"os";import{join as z,basename as Be,relative as za}from"path";function yd(e,t){if(Fe(e)){for(let r of _n(e).sort())if(r.endsWith(t))return z(e,r)}}function Xa(e){return Fe(e)?_n(e).map(t=>z(e,t)).filter(t=>Ga(t).isDirectory()):[]}function kd(e){let t=z(e,"kane-testrun");return Xa(t)}function mt(e){try{return JSON.parse(qa(e,"utf8"))}catch{return}}async function Qa(e){let t=e.prepared.members,r=e.job.cwd,i=kd(e.downloadDir),o=t.map(s=>{let a=za(r,Ae(s.absPath));for(let d of i){let l=z(d,a);if(Fe(l))return{member:s,tapeDir:l}}return{member:s}}),n=new Map;for(let s of i)for(let a of Xa(z(s,"artifacts","session")))n.has(Be(a))||n.set(Be(a),a);let c=(e.prepared.importTapes??[]).map(s=>{for(let a of i){let d=z(a,s.relTape);if(Fe(d))return{prepared:s,pulledDir:d}}return{prepared:s}});return{result:e,perMember:o,sessionDirs:[...n.values()],importTapes:c}}function xd(e){let t=mt(z(e,"execution.json")),r=mt(z(e,"session.json")),i=Date.parse(String(t?.start_timestamp??"")),o=Date.parse(String(t?.end_timestamp??"")),n=Number.isFinite(i)&&Number.isFinite(o)&&o>=i?(o-i)/1e3:void 0;return{testId:t?.test_id,status:t?.status,packPath:yd(z(e,"evidence"),".evidence"),uploadStatus:r?.upload_status,...n!==void 0?{durationS:n}:{}}}function Wa(e){return e?.uploadStatus==="uploaded"?"yes":e?.uploadStatus==="failed"?"no":"unknown"}function Sd(e){if(e.member.memberClass==="replay"&&e.member.testId)return e.member.testId;if(e.tapeDir){let r=mt(z(e.tapeDir,".internal","meta.json"))?.test_id;if(r)return r;let o=mt(z(e.tapeDir,".internal","execution.json"))?.test_id;if(o)return o}return e.member.testId}function Id(e){if(!e.tapeDir)return;let r=mt(z(e.tapeDir,".internal","meta.json"))?.commit_id;return typeof r=="string"&&r?r:void 0}function xr(e){try{let t=vt(e,{schema:tn});return t&&typeof t=="object"?t:void 0}catch{return}}function Cn(e){try{return xr(qa(e,"utf8"))}catch{return}}function Ce(e){return e instanceof Error?e.message:String(e)}function Cd(e,t=3){let r=e.slice(0,t).join("; ");return e.length>t?`${r} (+${e.length-t} more)`:r}function _d(e){let t=[],r=[],i=o=>{if(!Fe(o))return;let n;try{n=_n(o).sort()}catch(c){r.push(`readdir ${o}: ${Ce(c)}`);return}for(let c of n){let s=z(o,c);try{if(Ga(s).isDirectory()){i(s);continue}}catch(a){r.push(`stat ${s}: ${Ce(a)}`);continue}c==="result.yaml"&&t.push(s)}};return i(e),{files:t,errors:r}}function Sr(e,t){let r=[],i=z(e,"run.yaml"),o=Cn(i),n=o?.environment,c=typeof n?.run_kind=="string"?n.run_kind:void 0;if(o&&n&&c!==void 0){let p={...n};delete p.run_kind,p.run_kind_observed=c,o.environment=p;try{kr(i,qn(o,{lineWidth:-1,schema:tn}))}catch(g){r.push(`write ${i}: ${Ce(g)}`)}}let s=new Map,a=new Map;for(let p of t){let g=p.evidenceClass??p.memberClass;p.gridTestId&&s.set(p.gridTestId,g),a.set(Ee(p.relPath),g)}let d=new Set(t.map(p=>p.evidenceClass??p.memberClass)),l=d.size===1?[...d][0]:void 0,m=_d(z(e,"tests"));r.push(...m.errors);for(let p of m.files){let g=Cn(p);if(!g)continue;let u={...g.environment??{}},v=typeof u.run_kind=="string"?u.run_kind:c,k=g.external_id,R=typeof k?.test_id=="string"?k.test_id:void 0,S=typeof g.test=="string"?g.test:void 0,w=(R?s.get(R):void 0)??(S?a.get(S)??a.get(S.replace(/-\d+$/,"")):void 0)??l;if(w){u.run_kind=w,v&&v!==w&&(u.run_kind_observed=v),g.environment=u;try{kr(p,qn(g,{lineWidth:-1,schema:tn}))}catch(I){r.push(`write ${p}: ${Ce(I)}`)}}}return{errors:r}}function Ed(e,t){let r=new Map,i=new Map,o=new Map;for(let s of t)s.gridTestId&&i.set(s.gridTestId,s.relPath),o.set(Ee(s.relPath),s.relPath);let n=z(e,"tests");if(!Fe(n))return r;let c;try{c=_n(n).sort()}catch{return r}for(let s of c){let a=Cn(z(n,s,"result.yaml"));if(!a)continue;let d=a.external_id,l=typeof d?.test_id=="string"?d.test_id:void 0,m=typeof a.test=="string"?a.test:s,p=(l?i.get(l):void 0)??o.get(m)??o.get(m.replace(/-\d+$/,""));if(!p||r.has(p))continue;let g=Array.isArray(a.steps)?a.steps:[],u=a.duration_ms;r.set(p,{acs:an(g),...typeof u=="number"?{durationMs:u}:{}})}return r}function Rd(e){let t=Cn(z(e,"run.yaml"));return typeof t?.started=="string"?t.started:void 0}function Ya(e){if(e.members.length===0)return;let t=[],r=Ye(e.cwd);if(!Fe(r))return e.emit(He({status:"skipped",reason:"no_context_store",detail:r})),{status:"skipped",reason:"no_context_store",detail:r,synced:0,warnings:t};for(let o of e.members){if(!o.drift)continue;let n=`sync: ${o.relPath} ran a healed definition on the grid (tape commit ${o.drift.tape} \u2260 local ${o.drift.local}) \u2014 the verdict is attached to the local, pre-heal definition`;t.push(n),e.emit(He({status:"warning",reason:"heal_drift",detail:n}))}let i=e.members.map(o=>{let n=e.packFacts.get(o.relPath);return{path:o.absPath,verdict:o.verdict,...n?.acs.length?{acs:n.acs}:{},executionId:o.executionId,...n?.durationMs!==void 0?{durationMs:n.durationMs}:{},startedAt:e.startedAt,mode:"testrun",local:e.local,...o.drift?{driftFlag:!0}:{}}});try{let o=e.syncFn({cwd:e.cwd,members:i});t.push(...o.warnings);for(let n of o.warnings)e.emit(He({status:"warning",reason:"sync_warning",detail:n}));return o.skipped?(e.emit(He({status:"skipped",reason:o.skipped})),{status:"skipped",reason:o.skipped,synced:0,warnings:t}):{status:"synced",synced:o.synced,warnings:t}}catch(o){let n=Ce(o);return e.emit(He({status:"failed",reason:"sync_error",detail:n})),{status:"failed",reason:"sync_error",detail:n,synced:0,warnings:t}}}function Ha(e,t){try{return t()}catch(r){let i=Ce(r);try{e(He({status:"failed",reason:"sync_error",detail:i}))}catch{}return{status:"failed",reason:"sync_error",detail:i,synced:0,warnings:[]}}}function Td(e,t,r,i){try{let o=i(e,Ye(t));o.status==="skipped"&&r(pr({status:"skipped",reason:o.reason}))}catch(o){let n=Ce(o);try{r(pr({status:"failed",reason:"coverage_error",detail:n}))}catch{}}}async function Ir(e){let t,r=-1/0;for(let i of e){let o;try{let s=await er(i.path,"run.yaml");s&&(o=xr(s))}catch{}let n=typeof o?.ended=="string"?o.ended:typeof o?.started=="string"?o.started:void 0;if(!n)continue;let c=Date.parse(n);!Number.isNaN(c)&&c>r&&(r=c,t=n)}return t}function Pd(e){let t=/collides between packs "([^"]+)" and "([^"]+)"/.exec(e);if(t)return[t[2],t[1]];let r=/^pack "([^"]+)"/.exec(e);return r?[r[1]]:[]}async function Ad(e,t){let r=Pd(e);if(r.length)for(let i of r){let o=t.find(n=>Be(n.path,".evidence")===i);if(o)return o;for(let n of t)try{let c=await er(n.path,"run.yaml");if(c&&xr(c)?.run_id===i)return n}catch{}}}async function yr(e,t){let r=[];for(let i of e){let o=Be(i.path,".evidence");try{await zo(i.path,o,t),r.push(o)}catch{}}return r}async function Dd(e,t,r){let i=r.emit??(()=>{}),o=r.mergeFn??on,n,c;try{n=bd(z(wd(),"kane-remote-merge-rules-")),c=z(n,"merge-rules.yaml"),kr(c,ln())}catch(d){n&&wr(n,{recursive:!0,force:!0});let l=Ce(d),m=await yr(e,t);return i(Qe({reason:"merge_rules_standalone",detail:l,standaloneIds:m})),{kind:"standalone",degraded:{reason:"merge_rules_standalone",detail:l,standaloneIds:m}}}let s=async d=>{let l=yt(),m=Pe(l,t);try{return await o(d.map(p=>p.path),{runId:l,out:m,rulesPath:c,finalize:!1}),{ok:!0,execId:l,out:m}}catch(p){return wr(m,{recursive:!0,force:!0}),{ok:!1,error:p}}},a=d=>d?.code==="ABORT";try{let d=await s(e);if(d.ok)return{kind:"merged",execId:d.execId,out:d.out,used:e};let l=a(d.error)?await Ad(Ce(d.error),e):void 0;if(l&&e.length>1){let u=Be(l.path,".evidence"),v=Ce(d.error);i(Qe({reason:"merge_abort_excluded_pack",detail:v,excludedPack:u}));let k=e.filter(I=>I!==l),R=await s(k);if(R.ok)return{kind:"merged",execId:R.execId,out:R.out,used:k,degraded:{reason:"merge_abort_excluded_pack",detail:v}};let S=await yr(e,t),w=Ce(R.error);return i(Qe({reason:"merge_abort_standalone",detail:w,standaloneIds:S})),{kind:"standalone",degraded:{reason:"merge_abort_standalone",detail:w,standaloneIds:S}}}let m=await yr(e,t),p=a(d.error)?"merge_abort_standalone":"merge_error_standalone",g=Ce(d.error);return i(Qe({reason:p,detail:g,standaloneIds:m})),{kind:"standalone",degraded:{reason:p,detail:g,standaloneIds:m}}}finally{n&&wr(n,{recursive:!0,force:!0})}}async function Za(e,t={}){let r=e.result,i=r.job.cwd,o=(r.job.memberFlags??[]).includes("--author"),n=t.sessionsRoot??z(q,"sessions","remote"),c=z(n,r.hxJobId||"unknown-job");vd(c,{recursive:!0});let s=new Map;for(let C of e.sessionDirs){Fe(C)&&In(C,z(c,Be(C)),{recursive:!0});let M=xd(C);M.testId&&!s.has(M.testId)&&s.set(M.testId,M)}let a=[],d=[],l=[],m=[],p=0,g=0,u=0,v=0,k,R;for(let C of e.perMember){let M=Id(C),O=C.member.commitId;C.tapeDir&&Fe(C.tapeDir)&&In(C.tapeDir,Ae(C.member.absPath),{recursive:!0});let W=Sd(C),D=W?s.get(W):void 0;D&&v++;let X=D?.status==="success"||D?.status==="passed";D?X?p++:g++:u++;let F=D?.packPath,we=C.member.memberClass;if(F){let ve={path:F,memberClass:we,gridTestId:W,relPath:C.member.relPath,...o?{evidenceClass:"author"}:{}};(we==="author"?l:d).push(ve),we==="replay"?k??=W:R??=W}if(m.push({absPath:C.member.absPath,relPath:C.member.relPath,verdict:X?"passed":"failed",...F?{packId:Be(F,".evidence")}:{},...W?{gridTestId:W}:{},...O&&M&&O!==M&&!o?{drift:{tape:M,local:O}}:{}}),we==="author"){let ve=D?X?"passed":"failed":"broken",Ze=D?X?0:1:2,et=D?.durationS??0;F?a.push({relPath:C.member.relPath,testId:W??C.member.testId,commitId:C.member.commitId,sourceExecutionId:Be(F,".evidence"),overallStatus:ve,exitCode:Ze,durationS:et,published:Wa(D)}):a.push({relPath:C.member.relPath,overallStatus:ve,exitCode:Ze,durationS:et,published:Wa(D)})}}let S=[...d,...l],w=null,I="skipped",f,x,h=t.emit??(()=>{}),P=t.syncFn??cn,N=!t.publishFn;{let C=new Set(r.prepared.members.map(M=>M.absPath));for(let M of e.importTapes??[]){let O=M.prepared;if(C.has(O.unitAbsPath)||!M.pulledDir||!Fe(M.pulledDir))continue;let W=mt(z(M.pulledDir,".internal","meta.json")),D=typeof W?.commit_id=="string"&&W.commit_id?W.commit_id:void 0,X=mt(z(O.tapeDir,".internal","meta.json")),F=typeof X?.commit_id=="string"&&X.commit_id?X.commit_id:void 0;if(O.dispatchCommitId?F!==void 0&&F!==O.dispatchCommitId:F!==void 0){h(Vt({path:O.relTape,status:"kept_local_drift",localCommit:F,...O.dispatchCommitId?{dispatchCommit:O.dispatchCommitId}:{},gridCommit:D}));continue}try{In(M.pulledDir,O.tapeDir,{recursive:!0})}catch(ve){h(He({status:"warning",reason:"import_tape_writeback_failed",detail:`${O.relTape}: ${ve instanceof Error?ve.message:String(ve)}`}));continue}h(Vt({path:O.relTape,status:"written",...O.dispatchCommitId?{dispatchCommit:O.dispatchCommitId}:{},...D?{gridCommit:D}:{}})),D&&O.dispatchCommitId&&D!==O.dispatchCommitId&&h(He({status:"warning",reason:"import_heal_drift",detail:`imported unit ${za(i,O.unitAbsPath)} healed on the grid (dispatch ${O.dispatchCommitId} \u2192 grid ${D}) \u2014 tape written home; the local source file still holds the pre-heal definition`}))}}if(S.length){let C=await Dd(S,i,t);if(f=C.degraded,C.kind==="merged"){try{let D=Sr(C.out,C.used);if(D.errors.length){let X=Cd(D.errors);h(Qe({reason:"stamp_incomplete",detail:X})),f=f??{reason:"stamp_incomplete",detail:X}}}catch(D){let X=Ce(D);h(Qe({reason:"stamp_failed",detail:X})),f=f??{reason:"stamp_failed",detail:X}}let M=new Set(C.used.map(D=>Be(D.path,".evidence")));x=Ha(h,()=>Ya({cwd:i,members:m.filter(D=>D.packId&&M.has(D.packId)).map(D=>({...D,executionId:C.execId})),packFacts:Ed(C.out,C.used),startedAt:Rd(C.out)??new Date().toISOString(),local:N,emit:h,syncFn:P})),Td(C.out,i,h,t.coverageWriter??kt);let O=!0;try{let D=await Ir(C.used)??new Date().toISOString();await(t.sealFn??wt)(C.out,D)}catch(D){let X=Ce(D);h(Qe({reason:"seal_failed",detail:X})),f={reason:"seal_failed",detail:X},O=!1}w={id:C.execId,status:g>0?"failed":"passed",evidenceId:C.execId};let W=new Set(C.used.map(D=>Be(D.path,".evidence")));for(let D of a)D.sourceExecutionId&&W.has(D.sourceExecutionId)&&(D.executionId=C.execId);try{Fe(C.out)&&In(C.out,z(c,`execution-${C.execId}.evidence`),{recursive:!0})}catch{}if(t.publishFn&&O&&!r.cancelled){try{let F=await(t.validateFn??bt)(C.out,"L1");F.valid||t.log?.("warn","EVIDENCE_INVALID","Sealed remote testrun pack failed L1 validation",{execution_id:C.execId,first_code:String(F.diagnostics?.[0]?.code??""),surface:"testrun_remote"})}catch(F){t.log?.("warn","TESTRUN_VALIDATION_ERROR","Remote testrun pack validation threw",{execution_id:C.execId,error:String(F)})}let D=k??R,X=r.job.plan.projectId??r.job.projectId;if(D&&X){let F=await t.publishFn({testId:D,sessionId:C.execId,executionId:C.execId,sealedPackPath:C.out,projectId:X});I=F.ok?"ok":"failed",h(It(F,C.execId))}}}else{let M=new Set(C.degraded.standaloneIds??[]);for(let O of a)O.sourceExecutionId&&M.has(O.sourceExecutionId)&&(O.executionId=O.sourceExecutionId);x=Ha(h,()=>Ya({cwd:i,members:m.filter(O=>O.packId&&M.has(O.packId)).map(O=>({...O,executionId:O.packId})),packFacts:new Map,startedAt:new Date().toISOString(),local:N,emit:h,syncFn:P}))}}let _={tests:e.perMember.length,passed:p,failed:g,broken:u,skipped:0,authored:a.length};return{execution:w,authored:a,totals:_,upload:I,hxJobId:r.hxJobId,jobUrl:r.jobUrl,sessionsPath:c,cancelled:r.cancelled,...e.perMember.length>0&&v===0?{artifactless:!0}:{},...f?{degraded:f}:{},...x?{execSync:x}:{}}}var ec={id:"hyper",preflight:Na,prepare:Ba,dispatch:Ja,collect:Qa,reconcile:Za};var $d={hyper:ec};function tc(e){return $d[e]}import{existsSync as oc,readFileSync as ic}from"fs";import{join as Od}from"path";var Md=["name","version","backendId","kaneCompat"];function nc(e){if(typeof e!="object"||e===null)throw new Error("manifest must be an object");let t=e;for(let i of Md)if(typeof t[i]!="string"||t[i].length===0)throw new Error(`manifest missing required string field '${i}'`);let r={name:t.name,version:t.version,backendId:t.backendId,kaneCompat:t.kaneCompat};return t.defaults&&typeof t.defaults=="object"&&(r.defaults=t.defaults),r}function rc(e,t){let r=n=>{let c=n.replace(/^[v=]+/,"").split(".").map(s=>parseInt(s,10));return[c[0]||0,c[1]||0,c[2]||0]},i=(n,c)=>n[0]-c[0]||n[1]-c[1]||n[2]-c[2],o=r(e);return t.startsWith(">=")?i(o,r(t.slice(2)))>=0:i(o,r(t))===0}function Et(e,t=q){let r=os(e,t);if(!oc(r))return{ok:!1,reason:"not_installed"};let i=ic(r,"utf8").trim();if(!i)return{ok:!1,reason:"corrupt",detail:"empty current pointer"};let o=rs(e,i,t),n=Od(o,"plugin.json");if(!oc(n))return{ok:!1,reason:"corrupt",detail:`current points at ${i} but ${n} is missing`};let c;try{c=nc(JSON.parse(ic(n,"utf8")))}catch(s){return{ok:!1,reason:"corrupt",detail:s.message}}return rc(he,c.kaneCompat)?{ok:!0,plugin:{name:e,version:i,dir:o,manifest:c}}:{ok:!1,reason:"incompatible",detail:`plugin needs kane-cli ${c.kaneCompat}, have ${he}`}}async function sc(e,t={}){let r=t.creds??new le,i=e.envFlag??r.getDefaultEnv()??"prod",o=Et("remote-execution",e.base);if(!o.ok)return{ok:!1,code:o.reason==="incompatible"?"plugin_incompatible":"plugin_missing",detail:o.reason==="incompatible"?`remote-execution plugin is incompatible${o.detail?`: ${o.detail}`:""}`:"remote-execution plugin is not installed \u2014 run `kane-cli plugin install remote-execution`"};let n=await Ue({creds:r,env:i,usernameFlag:e.usernameFlag,accessKeyFlag:e.accessKeyFlag,log:e.log});if(!n.basicAuth)return{ok:!1,code:"no_basic_auth",detail:"HyperExecute needs a LambdaTest username + access key \u2014 log in with basic auth or pass --user/--key"};let c=n.resolvedCreds?.org_id!=null?String(n.resolvedCreds.org_id):"",s=r.getActiveProfile()??"default",a=(e.memberClasses??[]).includes("author"),d=Po(r,s,i);if(a&&d.projectId&&e.planProjectId&&d.projectId!==e.planProjectId)return{ok:!1,code:"project_authority_conflict",detail:hr(d.projectId,e.planProjectId)};let l=d.projectId??void 0,m=d.folderId??void 0,p;if(a&&!e.dryRun){let g,u=await rn({creds:r,config:t.config??new Te,profile:s,env:i,tmsCreds:n.basicAuth,isLocal:!!e.local,log:e.log,onFatalExit:v=>{g=v}});if(u.status==="ok")l=u.projectId,m=u.folderId,p=u.autoDefaulted;else if(u.status!=="skip")return{ok:!1,code:"project_folder",detail:g?.trim()||"could not resolve a TMS project/folder for the grid login"}}return{ok:!0,ctx:{env:i,auth:n.basicAuth,orgId:c,plugin:o.plugin,projectId:l,folderId:m,resolvedCreds:n.resolvedCreds??null,...p?{autoDefaulted:p}:{}}}}import{mkdirSync as jd,readFileSync as Fd,renameSync as Ld,writeFileSync as Vd}from"fs";import{dirname as Ud}from"path";function Ke(e){let t=e.indexOf(".");return t>=0?e.slice(0,t):e}var Ge=e=>typeof e=="string"&&e.trim()!=="";function cc(e){if(typeof e!="object"||e===null)return{};let t={};for(let[r,i]of Object.entries(e))typeof i=="string"&&(t[r]=i);return t}function Nd(e,t,r){if(typeof e!="object"||e===null)return null;let i=e;if(!Ge(i.name)||!Ge(i.brand)||!Array.isArray(i.osVersions)||i.osVersions.length===0)return null;let o=[];for(let s of i.osVersions)Ge(s)&&r.has(s)&&!o.includes(s)&&o.push(s);if(o.length===0)return null;if(t==="ios")return{name:i.name,brand:i.brand,osVersions:o};if(!Ge(i.configName))return null;let n=i.avdIds;if(typeof n!="object"||n===null)return null;let c={};for(let s of o){let a=n[s];if(!Ge(a))return null;c[s]=a}return{name:i.name,brand:i.brand,configName:i.configName,osVersions:o,avdIds:c}}function En(e){if(typeof e!="object"||e===null)return{catalog:null,reason:"not an object"};let t=e;if(typeof t.schemaVersion!="number"||!Number.isInteger(t.schemaVersion)||t.schemaVersion<1)return{catalog:null,reason:"schemaVersion missing or not a positive integer"};if(t.schemaVersion>1)return{catalog:null,reason:`catalog schemaVersion ${t.schemaVersion} is newer than this kane-cli understands (${1}) \u2014 upgrade kane-cli`};if(!Ge(t.platform))return{catalog:null,reason:"platform is empty"};if(t.platform!=="android"&&t.platform!=="ios")return{catalog:null,reason:`platform "${t.platform}" is not android or ios`};let r=t.platform;if(!Array.isArray(t.supportedOsVersions)||t.supportedOsVersions.length===0)return{catalog:null,reason:"supportedOsVersions is empty"};let i=t.supportedOsVersions.filter(Ge);if(i.length===0)return{catalog:null,reason:"supportedOsVersions has no usable entries"};if(!Array.isArray(t.devices)||t.devices.length===0)return{catalog:null,reason:"catalog has no devices"};let o;if(r==="ios"){o=cc(t.runson);for(let d of i)if(!Ge(o[Ke(d)]))return{catalog:null,reason:`ios catalog has no runson pool for iOS ${Ke(d)}`}}let n=new Set(i),c=[],s=new Set;for(let d of t.devices){let l=Nd(d,r,n);l&&(s.has(l.name)||(s.add(l.name),c.push(l)))}if(c.length===0)return{catalog:null,reason:"no valid devices survived validation"};let a=typeof t.source=="object"&&t.source!==null?t.source:{};return{catalog:{schemaVersion:t.schemaVersion,generatedAt:typeof t.generatedAt=="string"?t.generatedAt:"",platform:r,supportedOsVersions:i,...o?{runson:o}:{},source:{marketApi:typeof a.marketApi=="string"?a.marketApi:"",deviceConfigVersions:cc(a.deviceConfigVersions),...Ge(a.filter)?{filter:a.filter}:{}},devices:c}}}var lc=1,Bd=1440*60*1e3;function dc(e,t=Date.now()){return e!==null&&t-e.fetchedAt<Bd}function uc(e,t=Date.now()){return Math.max(0,Math.floor((t-e.fetchedAt)/(3600*1e3)))}function mc(e,t="android",r=Wn(e,t)){try{let i=JSON.parse(Fd(r,"utf-8"));if(i.wrapperVersion!==lc)return null;let{catalog:o}=En(i.catalog);return!o||o.platform!==t?null:{catalog:o,fetchedAt:typeof i.fetchedAt=="number"?i.fetchedAt:0}}catch{return null}}function pc(e,t,r=Date.now(),i=Wn(e,t.platform)){try{jd(Ud(i),{recursive:!0});let o={wrapperVersion:lc,writtenByVersion:he,fetchedAt:r,catalog:t},n=`${i}.tmp`;Vd(n,`${JSON.stringify(o)}
66
- `,{encoding:"utf-8"}),Ld(n,i)}catch{}}async function Kd(e,t,r){return new gt(re(e).controllerBaseUrl,{username:t.username,accessKey:t.accessKey}).getMobileDeviceCatalog(r)}async function Bt(e,t,r={}){let i=r.now??Date.now,o=r.platform??"android",n=r.readCacheFn??mc,c=r.writeCacheFn??pc,s=r.fetchCatalog??Kd,a=null;try{a=n(e,o)}catch{a=null}if(dc(a,i()))return{ok:!0,catalog:a.catalog,origin:"cache"};let d;try{let l=await s(e,t,o),{catalog:m,reason:p}=En(l);if(m&&m.platform!==o)d=`the controller served the ${m.platform} catalog when ${o} was asked for (controller too old for ?platform=${o}?)`;else{if(m)return c(e,m,i()),{ok:!0,catalog:m,origin:"network"};d=`the controller returned a catalog this kane-cli cannot read (${p})`}}catch(l){d=l.message}if(a){let l=uc(a,i());return{ok:!0,catalog:a.catalog,origin:"stale-cache",ageHours:l,warning:`could not refresh the device catalog (${d}) \u2014 using the cached copy from ${l}h ago. A device added since then will not be listed.`}}return{ok:!1,reason:`could not fetch the ${o==="ios"?"simulator":"emulator"} device catalog: ${d}
63
+ `}function Wa(e){return`'${e.replace(/'/g,"'\\''")}'`}function id(e){let t=e.devicePlatform??Ja(e),r=Object.keys(e.appIds??{}).length?" ${KANE_APP:+--app $KANE_APP}":"";if(t==="ios"){let s=e.deviceFlags??{};return(s.deviceName?` --device-name ${Wa(s.deviceName)}`:"")+(s.osVersion?` --os-version ${s.osVersion}`:"")+r}return t==="android"?(e.deviceLabel?.osVersion?` --os-version ${e.deviceLabel.osVersion}`:"")+r:""}function kr(e,t){let r=e;for(let[s,o]of Object.entries(t))r=r.split(`{{${s}}}`).join(o);return r}function ad(e){let t=e.map(o=>({relPath:o.relPath,absPath:o.path,memberClass:o.memberClass,testId:o.testId,commitId:o.commitId}));return{discoveryCommand:`printf '%s\\n' ${t.map(o=>`'${o.relPath}'`).join(" ")}`,members:t}}function cd(e,t,r=[]){let s=e.map(c=>Ka(t,$e(c.absPath))),o=[...new Set(r)].filter(c=>!s.includes(c));return[...[...s,...o].map(c=>` - "${c}/**"`)," - .testmuai/evidence/**"," - artifacts/session/**"].join(`
64
+ `)}function ld(e,t,r){let s=r??(a=>{try{return at(a).unitFiles.map(d=>d.file).filter(d=>d!==a)}catch{return[]}}),o=new Set(e.map(a=>a.absPath)),n=[],c=[],i=new Set;for(let a of e)for(let d of s(a.absPath)){if(o.has(d)||i.has(d))continue;i.add(d);let l=$e(d),m=Ka(t,l);if(m===".."||m.startsWith(`..${td}`)||ed(m)){c.push({unitAbsPath:d,reason:"outside payload cwd \u2014 cannot round-trip through the grid"});continue}let p;try{let g=xr(l,".internal","meta.json");if(zl(g)){let u=JSON.parse(Ql(g,"utf8"));typeof u.commit_id=="string"&&u.commit_id&&(p=u.commit_id)}}catch{}n.push({unitAbsPath:d,tapeDir:l,relTape:m,...p?{dispatchCommitId:p}:{}})}return{tapes:n,skipped:c}}function dd(e){return e.projectId?` --project-id ${e.projectId}${e.folderId?` --folder-id ${e.folderId}`:""}`:""}var ud=new Set(["--author","--no-testmd-sync","--dataset-id","--dataset-row"]);function md(e){return e.some(t=>ud.has(t))?be:"latest"}async function pd(e){let t=new Ns(oe(e.env).secretsBaseUrl),r={username:e.auth.username,accessKey:e.auth.access_key,orgId:e.orgId};await t.pushSecret({secretKey:"LT_USERNAME",secretValue:e.auth.username,...r}),await t.pushSecret({secretKey:"LT_ACCESS_KEY",secretValue:e.auth.access_key,...r})}async function Ya(e,t={}){let r=t.base??z,s=xr(di("remote-execution",r),e.jobId);Xl(s,{recursive:!0});let{discoveryCommand:o,members:n}=ad(e.plan.checks),{tapes:c,skipped:i}=ld(n,e.cwd);await(t.pushSecrets??pd)(e);let a=t.config??_n(r),d=rd(e);if(d&&!e.deviceSlug)throw new Error("device job prepared without a resolved device slug \u2014 preflight should have set one");let l=d?e.devicePlatform??Ja(e):void 0;if(l==="ios"&&!e.devicePool&&!e.runson&&!t.runson)throw new Error("simulator job prepared without a resolved pool \u2014 preflight should have set one");let m=od(d?{platform:l,slug:e.deviceSlug,mobile:a.mobile}:null),p=t.runson??e.runson??(l==="ios"?e.devicePool:d?a.mobile.runson:a.runson),g=l==="ios"?vi:d?hi:fi,u=e.memberFlags??[],v=e.kaneDist?kr(gi,{kaneDist:e.kaneDist}):"",x=kr(ui,{runnerBody:g}),T=kr(x,{runson:p,concurrency:String(e.parallel),env:e.env,kaneVersion:t.kaneVersion??e.kaneVersion??md(u),discoveryCommand:o,uploadPaths:cd(n,e.cwd,c.map(w=>w.relTape)),projectFolderFlags:dd(e),memberFlags:Ba(u),deviceFlags:id(e),appLookup:sd(e),kaneDistSwap:v,sessionMark:mi,sessionCopy:pi,...m}),S=xr(s,".hyperexecute.yaml");return Zl(S,T),{job:e,jobDir:s,yamlPath:S,members:n,importTapes:c,...i.length>0?{skippedImports:i}:{}}}import{spawn as fd,execFileSync as gd}from"child_process";import{join as hd}from"path";function vd(e){let t=e.match(/Job Link:\s*(https?:\/\/\S*?[?&]jobId=([0-9a-fA-F-]{36}))/);return t?{url:t[1],jobId:t[2]}:null}function bd(){try{return gd("hyperexecute",["--version"],{stdio:"ignore",timeout:2e3}),!0}catch{return!1}}function wd(e){return e.binaryPath?e.binaryPath:(e.onPath??bd)()?"hyperexecute":wn()}function Ha(e,t){if(!e)return;let r="";e.on("data",s=>{r+=String(s);let o;for(;(o=r.indexOf(`
65
+ `))>=0;)t(r.slice(0,o)),r=r.slice(o+1)}),e.on("end",()=>{r.length&&t(r)})}async function Ga(e,t={}){let r=e.job,s=wd(t),o=hd(e.jobDir,"dl"),n=["--user",r.auth.username,"--key",r.auth.access_key,"--env",r.env,"--config",e.yamlPath,"--concurrency",String(r.parallel),"--download-artifacts","--download-artifacts-path",o],i=(t.spawnImpl??((u,v,x)=>fd(u,v,{cwd:x.cwd})))(s,n,{cwd:r.cwd}),a="",d="",l=u=>{if(t.onLine?.(u),!a){let v=vd(u);v&&(a=v.jobId,d=v.url)}};Ha(i.stdout,l),Ha(i.stderr,l);let m=!1,p=()=>{m=!0;try{i.kill("SIGTERM")}catch{}};t.signal&&(t.signal.aborted?p():t.signal.addEventListener("abort",p,{once:!0}));let g=await new Promise(u=>{i.on("close",v=>u(m?3:typeof v=="number"?v:1)),i.on("error",()=>u(1))});return t.signal?.removeEventListener?.("abort",p),{job:r,prepared:e,hxJobId:a,jobUrl:d,downloadDir:o,exitCode:g,cancelled:m}}import{existsSync as Le,readdirSync as Tn,statSync as Qa,mkdirSync as yd,cpSync as En,readFileSync as Za,writeFileSync as Ir,rmSync as Sr,mkdtempSync as kd}from"fs";import{tmpdir as xd}from"os";import{join as X,basename as Ke,relative as ec}from"path";function Sd(e,t){if(Le(e)){for(let r of Tn(e).sort())if(r.endsWith(t))return X(e,r)}}function tc(e){return Le(e)?Tn(e).map(t=>X(e,t)).filter(t=>Qa(t).isDirectory()):[]}function Cd(e){let t=X(e,"kane-testrun");return tc(t)}function mt(e){try{return JSON.parse(Za(e,"utf8"))}catch{return}}async function nc(e){let t=e.prepared.members,r=e.job.cwd,s=Cd(e.downloadDir),o=t.map(i=>{let a=ec(r,$e(i.absPath));for(let d of s){let l=X(d,a);if(Le(l))return{member:i,tapeDir:l}}return{member:i}}),n=new Map;for(let i of s)for(let a of tc(X(i,"artifacts","session")))n.has(Ke(a))||n.set(Ke(a),a);let c=(e.prepared.importTapes??[]).map(i=>{for(let a of s){let d=X(a,i.relTape);if(Le(d))return{prepared:i,pulledDir:d}}return{prepared:i}});return{result:e,perMember:o,sessionDirs:[...n.values()],importTapes:c}}function Id(e){let t=mt(X(e,"execution.json")),r=mt(X(e,"session.json")),s=Date.parse(String(t?.start_timestamp??"")),o=Date.parse(String(t?.end_timestamp??"")),n=Number.isFinite(s)&&Number.isFinite(o)&&o>=s?(o-s)/1e3:void 0;return{testId:t?.test_id,status:t?.status,packPath:Sd(X(e,"evidence"),".evidence"),uploadStatus:r?.upload_status,...typeof r?.credits_consumed=="number"&&Number.isFinite(r.credits_consumed)?{creditsConsumed:r.credits_consumed}:{},...n!==void 0?{durationS:n}:{}}}function qa(e){return e?.uploadStatus==="uploaded"?"yes":e?.uploadStatus==="failed"?"no":"unknown"}function _d(e){if(e.member.memberClass==="replay"&&e.member.testId)return e.member.testId;if(e.tapeDir){let r=mt(X(e.tapeDir,".internal","meta.json"))?.test_id;if(r)return r;let o=mt(X(e.tapeDir,".internal","execution.json"))?.test_id;if(o)return o}return e.member.testId}function Ed(e){if(!e.tapeDir)return;let r=mt(X(e.tapeDir,".internal","meta.json"))?.commit_id;return typeof r=="string"&&r?r:void 0}function _r(e){try{let t=vt(e,{schema:nn});return t&&typeof t=="object"?t:void 0}catch{return}}function Rn(e){try{return _r(Za(e,"utf8"))}catch{return}}function _e(e){return e instanceof Error?e.message:String(e)}function Rd(e,t=3){let r=e.slice(0,t).join("; ");return e.length>t?`${r} (+${e.length-t} more)`:r}function Td(e){let t=[],r=[],s=o=>{if(!Le(o))return;let n;try{n=Tn(o).sort()}catch(c){r.push(`readdir ${o}: ${_e(c)}`);return}for(let c of n){let i=X(o,c);try{if(Qa(i).isDirectory()){s(i);continue}}catch(a){r.push(`stat ${i}: ${_e(a)}`);continue}c==="result.yaml"&&t.push(i)}};return s(e),{files:t,errors:r}}function Er(e,t){let r=[],s=X(e,"run.yaml"),o=Rn(s),n=o?.environment,c=typeof n?.run_kind=="string"?n.run_kind:void 0;if(o&&n&&c!==void 0){let p={...n};delete p.run_kind,p.run_kind_observed=c,o.environment=p;try{Ir(s,Zn(o,{lineWidth:-1,schema:nn}))}catch(g){r.push(`write ${s}: ${_e(g)}`)}}let i=new Map,a=new Map;for(let p of t){let g=p.evidenceClass??p.memberClass;p.gridTestId&&i.set(p.gridTestId,g),a.set(Re(p.relPath),g)}let d=new Set(t.map(p=>p.evidenceClass??p.memberClass)),l=d.size===1?[...d][0]:void 0,m=Td(X(e,"tests"));r.push(...m.errors);for(let p of m.files){let g=Rn(p);if(!g)continue;let u={...g.environment??{}},v=typeof u.run_kind=="string"?u.run_kind:c,x=g.external_id,T=typeof x?.test_id=="string"?x.test_id:void 0,S=typeof g.test=="string"?g.test:void 0,w=(T?i.get(T):void 0)??(S?a.get(S)??a.get(S.replace(/-\d+$/,"")):void 0)??l;if(w){u.run_kind=w,v&&v!==w&&(u.run_kind_observed=v),g.environment=u;try{Ir(p,Zn(g,{lineWidth:-1,schema:nn}))}catch(C){r.push(`write ${p}: ${_e(C)}`)}}}return{errors:r}}function Pd(e,t){let r=new Map,s=new Map,o=new Map;for(let i of t)i.gridTestId&&s.set(i.gridTestId,i.relPath),o.set(Re(i.relPath),i.relPath);let n=X(e,"tests");if(!Le(n))return r;let c;try{c=Tn(n).sort()}catch{return r}for(let i of c){let a=Rn(X(n,i,"result.yaml"));if(!a)continue;let d=a.external_id,l=typeof d?.test_id=="string"?d.test_id:void 0,m=typeof a.test=="string"?a.test:i,p=(l?s.get(l):void 0)??o.get(m)??o.get(m.replace(/-\d+$/,""));if(!p||r.has(p))continue;let g=Array.isArray(a.steps)?a.steps:[],u=a.duration_ms;r.set(p,{acs:dn(g),...typeof u=="number"?{durationMs:u}:{}})}return r}function Ad(e){let t=Rn(X(e,"run.yaml"));return typeof t?.started=="string"?t.started:void 0}function za(e){if(e.members.length===0)return;let t=[],r=He(e.cwd);if(!Le(r))return e.emit(Ge({status:"skipped",reason:"no_context_store",detail:r})),{status:"skipped",reason:"no_context_store",detail:r,synced:0,warnings:t};for(let o of e.members){if(!o.drift)continue;let n=`sync: ${o.relPath} ran a healed definition on the grid (tape commit ${o.drift.tape} \u2260 local ${o.drift.local}) \u2014 the verdict is attached to the local, pre-heal definition`;t.push(n),e.emit(Ge({status:"warning",reason:"heal_drift",detail:n}))}let s=e.members.map(o=>{let n=e.packFacts.get(o.relPath);return{path:o.absPath,verdict:o.verdict,...n?.acs.length?{acs:n.acs}:{},executionId:o.executionId,...n?.durationMs!==void 0?{durationMs:n.durationMs}:{},startedAt:e.startedAt,mode:"testrun",local:e.local,...o.drift?{driftFlag:!0}:{}}});try{let o=e.syncFn({cwd:e.cwd,members:s});t.push(...o.warnings);for(let n of o.warnings)e.emit(Ge({status:"warning",reason:"sync_warning",detail:n}));return o.skipped?(e.emit(Ge({status:"skipped",reason:o.skipped})),{status:"skipped",reason:o.skipped,synced:0,warnings:t}):{status:"synced",synced:o.synced,warnings:t}}catch(o){let n=_e(o);return e.emit(Ge({status:"failed",reason:"sync_error",detail:n})),{status:"failed",reason:"sync_error",detail:n,synced:0,warnings:t}}}function Xa(e,t){try{return t()}catch(r){let s=_e(r);try{e(Ge({status:"failed",reason:"sync_error",detail:s}))}catch{}return{status:"failed",reason:"sync_error",detail:s,synced:0,warnings:[]}}}function Dd(e,t,r,s){try{let o=s(e,He(t));o.status==="skipped"&&r(vr({status:"skipped",reason:o.reason}))}catch(o){let n=_e(o);try{r(vr({status:"failed",reason:"coverage_error",detail:n}))}catch{}}}async function Rr(e){let t,r=-1/0;for(let s of e){let o;try{let i=await or(s.path,"run.yaml");i&&(o=_r(i))}catch{}let n=typeof o?.ended=="string"?o.ended:typeof o?.started=="string"?o.started:void 0;if(!n)continue;let c=Date.parse(n);!Number.isNaN(c)&&c>r&&(r=c,t=n)}return t}function $d(e){let t=/collides between packs "([^"]+)" and "([^"]+)"/.exec(e);if(t)return[t[2],t[1]];let r=/^pack "([^"]+)"/.exec(e);return r?[r[1]]:[]}async function Md(e,t){let r=$d(e);if(r.length)for(let s of r){let o=t.find(n=>Ke(n.path,".evidence")===s);if(o)return o;for(let n of t)try{let c=await or(n.path,"run.yaml");if(c&&_r(c)?.run_id===s)return n}catch{}}}async function Cr(e,t){let r=[];for(let s of e){let o=Ke(s.path,".evidence");try{await Zo(s.path,o,t),r.push(o)}catch{}}return r}async function Od(e,t,r){let s=r.emit??(()=>{}),o=r.mergeFn??cn,n,c;try{n=kd(X(xd(),"kane-remote-merge-rules-")),c=X(n,"merge-rules.yaml"),Ir(c,mn())}catch(d){n&&Sr(n,{recursive:!0,force:!0});let l=_e(d),m=await Cr(e,t);return s(et({reason:"merge_rules_standalone",detail:l,standaloneIds:m})),{kind:"standalone",degraded:{reason:"merge_rules_standalone",detail:l,standaloneIds:m}}}let i=async d=>{let l=yt(),m=De(l,t);try{return await o(d.map(p=>p.path),{runId:l,out:m,rulesPath:c,finalize:!1}),{ok:!0,execId:l,out:m}}catch(p){return Sr(m,{recursive:!0,force:!0}),{ok:!1,error:p}}},a=d=>d?.code==="ABORT";try{let d=await i(e);if(d.ok)return{kind:"merged",execId:d.execId,out:d.out,used:e};let l=a(d.error)?await Md(_e(d.error),e):void 0;if(l&&e.length>1){let u=Ke(l.path,".evidence"),v=_e(d.error);s(et({reason:"merge_abort_excluded_pack",detail:v,excludedPack:u}));let x=e.filter(C=>C!==l),T=await i(x);if(T.ok)return{kind:"merged",execId:T.execId,out:T.out,used:x,degraded:{reason:"merge_abort_excluded_pack",detail:v}};let S=await Cr(e,t),w=_e(T.error);return s(et({reason:"merge_abort_standalone",detail:w,standaloneIds:S})),{kind:"standalone",degraded:{reason:"merge_abort_standalone",detail:w,standaloneIds:S}}}let m=await Cr(e,t),p=a(d.error)?"merge_abort_standalone":"merge_error_standalone",g=_e(d.error);return s(et({reason:p,detail:g,standaloneIds:m})),{kind:"standalone",degraded:{reason:p,detail:g,standaloneIds:m}}}finally{n&&Sr(n,{recursive:!0,force:!0})}}async function rc(e,t={}){let r=e.result,s=r.job.cwd,o=(r.job.memberFlags??[]).includes("--author"),n=t.sessionsRoot??X(z,"sessions","remote"),c=X(n,r.hxJobId||"unknown-job");yd(c,{recursive:!0});let i=new Map;for(let I of e.sessionDirs){Le(I)&&En(I,X(c,Ke(I)),{recursive:!0});let L=Id(I);L.testId&&!i.has(L.testId)&&i.set(L.testId,L)}let a=[],d=[],l=[],m=[],p=0,g=0,u=0,v=0,x=0,T,S;for(let I of e.perMember){let L=Ed(I),$=I.member.commitId;I.tapeDir&&Le(I.tapeDir)&&En(I.tapeDir,$e(I.member.absPath),{recursive:!0});let Q=_d(I),M=Q?i.get(Q):void 0;M&&(v++,x+=M.creditsConsumed??0);let j=M?.status==="success"||M?.status==="passed";M?j?p++:g++:u++;let H=M?.packPath,Te=I.member.memberClass;if(H){let Ee={path:H,memberClass:Te,gridTestId:Q,relPath:I.member.relPath,...o?{evidenceClass:"author"}:{}};(Te==="author"?l:d).push(Ee),Te==="replay"?T??=Q:S??=Q}if(m.push({absPath:I.member.absPath,relPath:I.member.relPath,verdict:j?"passed":"failed",...H?{packId:Ke(H,".evidence")}:{},...Q?{gridTestId:Q}:{},...$&&L&&$!==L&&!o?{drift:{tape:L,local:$}}:{}}),Te==="author"){let Ee=M?j?"passed":"failed":"broken",ze=M?j?0:1:2,se=M?.durationS??0;H?a.push({relPath:I.member.relPath,testId:Q??I.member.testId,commitId:I.member.commitId,sourceExecutionId:Ke(H,".evidence"),overallStatus:Ee,exitCode:ze,durationS:se,published:qa(M),creditsConsumed:M?.creditsConsumed??0}):a.push({relPath:I.member.relPath,overallStatus:Ee,exitCode:ze,durationS:se,creditsConsumed:M?.creditsConsumed??0,published:qa(M)})}}let w=[...d,...l],C=null,f="skipped",k,h,R=t.emit??(()=>{}),O=t.syncFn??un,_=!t.publishFn;{let I=new Set(r.prepared.members.map(L=>L.absPath));for(let L of e.importTapes??[]){let $=L.prepared;if(I.has($.unitAbsPath)||!L.pulledDir||!Le(L.pulledDir))continue;let Q=mt(X(L.pulledDir,".internal","meta.json")),M=typeof Q?.commit_id=="string"&&Q.commit_id?Q.commit_id:void 0,j=mt(X($.tapeDir,".internal","meta.json")),H=typeof j?.commit_id=="string"&&j.commit_id?j.commit_id:void 0;if($.dispatchCommitId?H!==void 0&&H!==$.dispatchCommitId:H!==void 0){R(Vt({path:$.relTape,status:"kept_local_drift",localCommit:H,...$.dispatchCommitId?{dispatchCommit:$.dispatchCommitId}:{},gridCommit:M}));continue}try{En(L.pulledDir,$.tapeDir,{recursive:!0})}catch(Ee){R(Ge({status:"warning",reason:"import_tape_writeback_failed",detail:`${$.relTape}: ${Ee instanceof Error?Ee.message:String(Ee)}`}));continue}R(Vt({path:$.relTape,status:"written",...$.dispatchCommitId?{dispatchCommit:$.dispatchCommitId}:{},...M?{gridCommit:M}:{}})),M&&$.dispatchCommitId&&M!==$.dispatchCommitId&&R(Ge({status:"warning",reason:"import_heal_drift",detail:`imported unit ${ec(s,$.unitAbsPath)} healed on the grid (dispatch ${$.dispatchCommitId} \u2192 grid ${M}) \u2014 tape written home; the local source file still holds the pre-heal definition`}))}}if(w.length){let I=await Od(w,s,t);if(k=I.degraded,I.kind==="merged"){try{let M=Er(I.out,I.used);if(M.errors.length){let j=Rd(M.errors);R(et({reason:"stamp_incomplete",detail:j})),k=k??{reason:"stamp_incomplete",detail:j}}}catch(M){let j=_e(M);R(et({reason:"stamp_failed",detail:j})),k=k??{reason:"stamp_failed",detail:j}}let L=new Set(I.used.map(M=>Ke(M.path,".evidence")));h=Xa(R,()=>za({cwd:s,members:m.filter(M=>M.packId&&L.has(M.packId)).map(M=>({...M,executionId:I.execId})),packFacts:Pd(I.out,I.used),startedAt:Ad(I.out)??new Date().toISOString(),local:_,emit:R,syncFn:O})),Dd(I.out,s,R,t.coverageWriter??kt);let $=!0;try{let M=await Rr(I.used)??new Date().toISOString();await(t.sealFn??wt)(I.out,M)}catch(M){let j=_e(M);R(et({reason:"seal_failed",detail:j})),k={reason:"seal_failed",detail:j},$=!1}C={id:I.execId,status:g>0?"failed":"passed",evidenceId:I.execId};let Q=new Set(I.used.map(M=>Ke(M.path,".evidence")));for(let M of a)M.sourceExecutionId&&Q.has(M.sourceExecutionId)&&(M.executionId=I.execId);try{Le(I.out)&&En(I.out,X(c,`execution-${I.execId}.evidence`),{recursive:!0})}catch{}if(t.publishFn&&$&&!r.cancelled){try{let H=await(t.validateFn??bt)(I.out,"L1");H.valid||t.log?.("warn","EVIDENCE_INVALID","Sealed remote testrun pack failed L1 validation",{execution_id:I.execId,first_code:String(H.diagnostics?.[0]?.code??""),surface:"testrun_remote"})}catch(H){t.log?.("warn","TESTRUN_VALIDATION_ERROR","Remote testrun pack validation threw",{execution_id:I.execId,error:String(H)})}let M=T??S,j=r.job.plan.projectId??r.job.projectId;if(M&&j){let H=await t.publishFn({testId:M,sessionId:I.execId,executionId:I.execId,sealedPackPath:I.out,projectId:j});f=H.ok?"ok":"failed",R(Ct(H,I.execId))}}}else{let L=new Set(I.degraded.standaloneIds??[]);for(let $ of a)$.sourceExecutionId&&L.has($.sourceExecutionId)&&($.executionId=$.sourceExecutionId);h=Xa(R,()=>za({cwd:s,members:m.filter($=>$.packId&&L.has($.packId)).map($=>({...$,executionId:$.packId})),packFacts:new Map,startedAt:new Date().toISOString(),local:_,emit:R,syncFn:O}))}}let V={tests:e.perMember.length,passed:p,failed:g,broken:u,skipped:0,authored:a.length,creditsConsumed:x};return{execution:C,authored:a,totals:V,upload:f,hxJobId:r.hxJobId,jobUrl:r.jobUrl,sessionsPath:c,cancelled:r.cancelled,...e.perMember.length>0&&v===0?{artifactless:!0}:{},...k?{degraded:k}:{},...h?{execSync:h}:{}}}var oc={id:"hyper",preflight:Va,prepare:Ya,dispatch:Ga,collect:nc,reconcile:rc};var Nd={hyper:oc};function sc(e){return Nd[e]}import{existsSync as cc,readFileSync as lc}from"fs";import{join as Fd}from"path";var jd=["name","version","backendId","kaneCompat"];function ic(e){if(typeof e!="object"||e===null)throw new Error("manifest must be an object");let t=e;for(let s of jd)if(typeof t[s]!="string"||t[s].length===0)throw new Error(`manifest missing required string field '${s}'`);let r={name:t.name,version:t.version,backendId:t.backendId,kaneCompat:t.kaneCompat};return t.defaults&&typeof t.defaults=="object"&&(r.defaults=t.defaults),r}function ac(e,t){let r=n=>{let c=n.replace(/^[v=]+/,"").split(".").map(i=>parseInt(i,10));return[c[0]||0,c[1]||0,c[2]||0]},s=(n,c)=>n[0]-c[0]||n[1]-c[1]||n[2]-c[2],o=r(e);return t.startsWith(">=")?s(o,r(t.slice(2)))>=0:s(o,r(t))===0}function Et(e,t=z){let r=ci(e,t);if(!cc(r))return{ok:!1,reason:"not_installed"};let s=lc(r,"utf8").trim();if(!s)return{ok:!1,reason:"corrupt",detail:"empty current pointer"};let o=ai(e,s,t),n=Fd(o,"plugin.json");if(!cc(n))return{ok:!1,reason:"corrupt",detail:`current points at ${s} but ${n} is missing`};let c;try{c=ic(JSON.parse(lc(n,"utf8")))}catch(i){return{ok:!1,reason:"corrupt",detail:i.message}}return ac(be,c.kaneCompat)?{ok:!0,plugin:{name:e,version:s,dir:o,manifest:c}}:{ok:!1,reason:"incompatible",detail:`plugin needs kane-cli ${c.kaneCompat}, have ${be}`}}async function dc(e,t={}){let r=t.creds??new me,s=e.envFlag??r.getDefaultEnv()??"prod",o=Et("remote-execution",e.base);if(!o.ok)return{ok:!1,code:o.reason==="incompatible"?"plugin_incompatible":"plugin_missing",detail:o.reason==="incompatible"?`remote-execution plugin is incompatible${o.detail?`: ${o.detail}`:""}`:"remote-execution plugin is not installed \u2014 run `kane-cli plugin install remote-execution`"};let n=await Be({creds:r,env:s,usernameFlag:e.usernameFlag,accessKeyFlag:e.accessKeyFlag,log:e.log});if(!n.basicAuth)return{ok:!1,code:"no_basic_auth",detail:"HyperExecute needs a LambdaTest username + access key \u2014 log in with basic auth or pass --user/--key"};let c=n.resolvedCreds?.org_id!=null?String(n.resolvedCreds.org_id):"",i=r.getActiveProfile()??"default",a=(e.memberClasses??[]).includes("author"),d=$o(r,i,s);if(a&&d.projectId&&e.planProjectId&&d.projectId!==e.planProjectId)return{ok:!1,code:"project_authority_conflict",detail:yr(d.projectId,e.planProjectId)};let l=d.projectId??void 0,m=d.folderId??void 0,p;if(a&&!e.dryRun){let g,u=await an({creds:r,config:t.config??new Ae,profile:i,env:s,tmsCreds:n.basicAuth,isLocal:!!e.local,log:e.log,onFatalExit:v=>{g=v}});if(u.status==="ok")l=u.projectId,m=u.folderId,p=u.autoDefaulted;else if(u.status!=="skip")return{ok:!1,code:"project_folder",detail:g?.trim()||"could not resolve a TMS project/folder for the grid login"}}return{ok:!0,ctx:{env:s,auth:n.basicAuth,orgId:c,plugin:o.plugin,projectId:l,folderId:m,resolvedCreds:n.resolvedCreds??null,...p?{autoDefaulted:p}:{}}}}import{mkdirSync as Vd,readFileSync as Ud,renameSync as Bd,writeFileSync as Kd}from"fs";import{dirname as Jd}from"path";function Je(e){let t=e.indexOf(".");return t>=0?e.slice(0,t):e}var qe=e=>typeof e=="string"&&e.trim()!=="";function mc(e){if(typeof e!="object"||e===null)return{};let t={};for(let[r,s]of Object.entries(e))typeof s=="string"&&(t[r]=s);return t}function Ld(e,t,r){if(typeof e!="object"||e===null)return null;let s=e;if(!qe(s.name)||!qe(s.brand)||!Array.isArray(s.osVersions)||s.osVersions.length===0)return null;let o=[];for(let i of s.osVersions)qe(i)&&r.has(i)&&!o.includes(i)&&o.push(i);if(o.length===0)return null;if(t==="ios")return{name:s.name,brand:s.brand,osVersions:o};if(!qe(s.configName))return null;let n=s.avdIds;if(typeof n!="object"||n===null)return null;let c={};for(let i of o){let a=n[i];if(!qe(a))return null;c[i]=a}return{name:s.name,brand:s.brand,configName:s.configName,osVersions:o,avdIds:c}}function Pn(e){if(typeof e!="object"||e===null)return{catalog:null,reason:"not an object"};let t=e;if(typeof t.schemaVersion!="number"||!Number.isInteger(t.schemaVersion)||t.schemaVersion<1)return{catalog:null,reason:"schemaVersion missing or not a positive integer"};if(t.schemaVersion>1)return{catalog:null,reason:`catalog schemaVersion ${t.schemaVersion} is newer than this kane-cli understands (${1}) \u2014 upgrade kane-cli`};if(!qe(t.platform))return{catalog:null,reason:"platform is empty"};if(t.platform!=="android"&&t.platform!=="ios")return{catalog:null,reason:`platform "${t.platform}" is not android or ios`};let r=t.platform;if(!Array.isArray(t.supportedOsVersions)||t.supportedOsVersions.length===0)return{catalog:null,reason:"supportedOsVersions is empty"};let s=t.supportedOsVersions.filter(qe);if(s.length===0)return{catalog:null,reason:"supportedOsVersions has no usable entries"};if(!Array.isArray(t.devices)||t.devices.length===0)return{catalog:null,reason:"catalog has no devices"};let o;if(r==="ios"){o=mc(t.runson);for(let d of s)if(!qe(o[Je(d)]))return{catalog:null,reason:`ios catalog has no runson pool for iOS ${Je(d)}`}}let n=new Set(s),c=[],i=new Set;for(let d of t.devices){let l=Ld(d,r,n);l&&(i.has(l.name)||(i.add(l.name),c.push(l)))}if(c.length===0)return{catalog:null,reason:"no valid devices survived validation"};let a=typeof t.source=="object"&&t.source!==null?t.source:{};return{catalog:{schemaVersion:t.schemaVersion,generatedAt:typeof t.generatedAt=="string"?t.generatedAt:"",platform:r,supportedOsVersions:s,...o?{runson:o}:{},source:{marketApi:typeof a.marketApi=="string"?a.marketApi:"",deviceConfigVersions:mc(a.deviceConfigVersions),...qe(a.filter)?{filter:a.filter}:{}},devices:c}}}var pc=1,Wd=1440*60*1e3;function fc(e,t=Date.now()){return e!==null&&t-e.fetchedAt<Wd}function gc(e,t=Date.now()){return Math.max(0,Math.floor((t-e.fetchedAt)/(3600*1e3)))}function hc(e,t="android",r=qn(e,t)){try{let s=JSON.parse(Ud(r,"utf-8"));if(s.wrapperVersion!==pc)return null;let{catalog:o}=Pn(s.catalog);return!o||o.platform!==t?null:{catalog:o,fetchedAt:typeof s.fetchedAt=="number"?s.fetchedAt:0}}catch{return null}}function vc(e,t,r=Date.now(),s=qn(e,t.platform)){try{Vd(Jd(s),{recursive:!0});let o={wrapperVersion:pc,writtenByVersion:be,fetchedAt:r,catalog:t},n=`${s}.tmp`;Kd(n,`${JSON.stringify(o)}
66
+ `,{encoding:"utf-8"}),Bd(n,s)}catch{}}async function Yd(e,t,r){return new gt(oe(e).controllerBaseUrl,{username:t.username,accessKey:t.accessKey}).getMobileDeviceCatalog(r)}async function Bt(e,t,r={}){let s=r.now??Date.now,o=r.platform??"android",n=r.readCacheFn??hc,c=r.writeCacheFn??vc,i=r.fetchCatalog??Yd,a=null;try{a=n(e,o)}catch{a=null}if(fc(a,s()))return{ok:!0,catalog:a.catalog,origin:"cache"};let d;try{let l=await i(e,t,o),{catalog:m,reason:p}=Pn(l);if(m&&m.platform!==o)d=`the controller served the ${m.platform} catalog when ${o} was asked for (controller too old for ?platform=${o}?)`;else{if(m)return c(e,m,s()),{ok:!0,catalog:m,origin:"network"};d=`the controller returned a catalog this kane-cli cannot read (${p})`}}catch(l){d=l.message}if(a){let l=gc(a,s());return{ok:!0,catalog:a.catalog,origin:"stale-cache",ageHours:l,warning:`could not refresh the device catalog (${d}) \u2014 using the cached copy from ${l}h ago. A device added since then will not be listed.`}}return{ok:!1,reason:`could not fetch the ${o==="ios"?"simulator":"emulator"} device catalog: ${d}
67
67
  The catalog names which devices HyperExecute can provision, so a device cannot be validated without it.
68
- Check your connection and credentials`+(o==="android"?", or bypass validation with --device-slug <slug>.":".")}}function Rt(e){return e.toLowerCase().replace(/\+/g,"plus").replace(/[^a-z0-9]/g,"")}function Rn(e){return e==="ios"?{os:"iOS",device:"simulator",target:"simulator"}:{os:"Android",device:"emulator",target:"emulator"}}var Jd=.4,Wd=3;function Yd(e,t,r){let i=Rt(t);if(i==="")return[];let o=Math.max(1,Math.round(i.length*Jd)),n=[];for(let c of e.devices){if(r&&!c.osVersions.includes(r))continue;let s=Math.min(jt(i,Rt(c.name)),c.configName?jt(i,Rt(c.configName)):1/0);s<=o&&n.push({device:c,score:s})}return n.sort((c,s)=>c.score-s.score||c.device.name.localeCompare(s.device.name)),n.slice(0,Wd).map(c=>c.device)}function Hd(e,t){let r=Number.parseFloat(t);if(!Number.isFinite(r))return e.osVersions[e.osVersions.length-1];let i,o=1/0;for(let n of e.osVersions){let c=Math.abs(Number.parseFloat(n)-r);Number.isFinite(c)&&c<o&&(o=c,i=n)}return i??e.osVersions[e.osVersions.length-1]}function fc(e){return` See all devices: kane-cli devices list --target ${Rn(e).target} --remote`}function Gd(e,t){let r=Rt(t);return e.devices.find(i=>Rt(i.name)===r||i.configName!==void 0&&Rt(i.configName)===r)}function gc(e,t){return e.runson?.[Ke(t)]}function Cr(e,t,r){let i=Rn(e.platform),o=Gd(e,t);if(!o){let n=Yd(e,t,r),c=n.length?` Did you mean: ${n.map(s=>`${s.name} (${s.osVersions.join(", ")})`).join(`
68
+ Check your connection and credentials`+(o==="android"?", or bypass validation with --device-slug <slug>.":".")}}function Rt(e){return e.toLowerCase().replace(/\+/g,"plus").replace(/[^a-z0-9]/g,"")}function An(e){return e==="ios"?{os:"iOS",device:"simulator",target:"simulator"}:{os:"Android",device:"emulator",target:"emulator"}}var Hd=.4,Gd=3;function qd(e,t,r){let s=Rt(t);if(s==="")return[];let o=Math.max(1,Math.round(s.length*Hd)),n=[];for(let c of e.devices){if(r&&!c.osVersions.includes(r))continue;let i=Math.min(jt(s,Rt(c.name)),c.configName?jt(s,Rt(c.configName)):1/0);i<=o&&n.push({device:c,score:i})}return n.sort((c,i)=>c.score-i.score||c.device.name.localeCompare(i.device.name)),n.slice(0,Gd).map(c=>c.device)}function zd(e,t){let r=Number.parseFloat(t);if(!Number.isFinite(r))return e.osVersions[e.osVersions.length-1];let s,o=1/0;for(let n of e.osVersions){let c=Math.abs(Number.parseFloat(n)-r);Number.isFinite(c)&&c<o&&(o=c,s=n)}return s??e.osVersions[e.osVersions.length-1]}function bc(e){return` See all devices: kane-cli devices list --target ${An(e).target} --remote`}function Xd(e,t){let r=Rt(t);return e.devices.find(s=>Rt(s.name)===r||s.configName!==void 0&&Rt(s.configName)===r)}function wc(e,t){return e.runson?.[Je(t)]}function Tr(e,t,r){let s=An(e.platform),o=Xd(e,t);if(!o){let n=qd(e,t,r),c=n.length?` Did you mean: ${n.map(i=>`${i.name} (${i.osVersions.join(", ")})`).join(`
69
69
  `)}
70
- `:"";return{ok:!1,code:"device_not_found",detail:`no ${i.device} device named "${t}"`+(r&&n.length?` running ${i.os} ${r}`:"")+`.
71
- ${c}${fc(e.platform)}`}}if(!o.osVersions.includes(r)){let n=Hd(o,r);return{ok:!1,code:"device_os_version_unsupported",detail:`${o.name} does not run ${i.os} ${r}.
70
+ `:"";return{ok:!1,code:"device_not_found",detail:`no ${s.device} device named "${t}"`+(r&&n.length?` running ${s.os} ${r}`:"")+`.
71
+ ${c}${bc(e.platform)}`}}if(!o.osVersions.includes(r)){let n=zd(o,r);return{ok:!1,code:"device_os_version_unsupported",detail:`${o.name} does not run ${s.os} ${r}.
72
72
  Supported: ${o.osVersions.join(", ")}`+(n?` \u2014 nearest is ${n}.`:".")+`
73
- ${fc(e.platform)}`}}return e.platform==="ios"?{ok:!0,resolved:{device:o,osVersion:r,slug:`${o.name}-${r}`,...gc(e,r)?{pool:gc(e,r)}:{}}}:{ok:!0,resolved:{device:o,osVersion:r,slug:`${o.configName}-${r}`,avdId:o.avdIds?.[r]}}}function qd(e){let t=e.lastIndexOf("-");if(t<0)return;let r=e.slice(t+1);return/^\d+(\.\d+)*$/.test(r)?r:void 0}function zd(e){let t=e.checks.find(r=>r.mobile);if(t)return t.platform==="ios"?"ios":"android"}async function hc(e,t,r={}){let i=r.config??Sn(r.base),o=zd(e);if(!o)return{ok:!1,errors:[{code:"invalid_plan",detail:"no device member in a device job"}]};let n=e.checks.filter(c=>c.mobile);return o==="ios"?Qd(n,t,i,r):Xd(n,t,i,r)}async function Xd(e,t,r,i){let o=e.filter(l=>l.deviceName).map(l=>`${l.relPath} (device_name: ${l.deviceName})`),n=e.find(l=>l.osVersion)?.osVersion,c=(t.osVersion??n??r.mobile.osVersion).trim();if(t.deviceSlug){let l=t.deviceSlug.trim(),m=qd(l);return{ok:!0,device:{platform:"android",slug:l,label:{name:l,osVersion:m??c,avdId:"(unvalidated --device-slug)"},ignoredDeviceNames:o}}}let s=(t.deviceName??r.mobile.deviceName).trim(),a=await(i.resolveCatalogFn??Bt)(t.env,t.auth,{platform:"android"});if(!a.ok)return{ok:!1,errors:[{code:"device_catalog_unavailable",detail:a.reason}]};let d=Cr(a.catalog,s,c);return d.ok?{ok:!0,device:{platform:"android",slug:d.resolved.slug,label:{name:d.resolved.device.name,osVersion:d.resolved.osVersion,...d.resolved.avdId?{avdId:d.resolved.avdId}:{}},ignoredDeviceNames:o,...a.warning?{warning:a.warning}:{}}}:{ok:!1,errors:[{code:d.code,detail:d.detail+(t.deviceName?"":`
74
- (device name came from the remote-execution plugin config, not a flag \u2014 pass --device-name to override)`)}]}}async function Qd(e,t,r,i){let o=Rn("ios");if(t.deviceSlug)return{ok:!1,errors:[{code:"device_slug_android_only",detail:`--device-slug names a HyperExecute emulator slug; a simulator job has no slug to bypass to.
75
- Use --device-name/--os-version, or the members' own device_name:/os_version:.`}]};let n=await(i.resolveCatalogFn??Bt)(t.env,t.auth,{platform:"ios"});if(!n.ok)return{ok:!1,errors:[{code:"device_catalog_unavailable",detail:n.reason}]};let c=n.catalog,s=t.deviceName?.trim(),a=t.osVersion?.trim(),d=v=>r.mobile.ios.runson[Ke(v)]??c.runson?.[Ke(v)],l=new Map,m=new Map,p;for(let v of e){let k=s??v.deviceName?.trim()??r.mobile.ios.deviceName,R=a??v.osVersion?.trim()??r.mobile.ios.osVersion,S=Cr(c,k,R);if(!S.ok){let x=s?"--device-name":v.deviceName?`${v.relPath} device_name:`:"the remote-execution plugin config",h=a?"--os-version":v.osVersion?`${v.relPath} os_version:`:"the remote-execution plugin config",P=`${S.code}
76
- ${S.detail}`,N=l.get(P)??{code:S.code,detail:S.detail,sources:[]};N.sources.push(`device name from ${x}; ${o.os} version from ${h}`),l.set(P,N);continue}let w=S.resolved.pool??d(R);if(!w){let x=`device_pool_unknown
77
- ${R}`,h=l.get(x)??{code:"device_pool_unknown",detail:`no HyperExecute pool is known for ${o.os} ${R}.
78
- The catalog's runson map names a pool per iOS major; set mobile.ios.runson["${Ke(R)}"] in the remote-execution plugin config to override.`,sources:[]};h.sources.push(v.relPath),l.set(x,h);continue}let f=r.mobile.ios.runson[Ke(R)]??w;m.set(f,[...m.get(f)??[],`${v.relPath} (${o.os} ${R})`]),p??={name:S.resolved.device.name,osVersion:R,slug:S.resolved.slug}}if(l.size)return{ok:!1,errors:[...l.values()].map(v=>({code:v.code,detail:`${v.detail}
73
+ ${bc(e.platform)}`}}return e.platform==="ios"?{ok:!0,resolved:{device:o,osVersion:r,slug:`${o.name}-${r}`,...wc(e,r)?{pool:wc(e,r)}:{}}}:{ok:!0,resolved:{device:o,osVersion:r,slug:`${o.configName}-${r}`,avdId:o.avdIds?.[r]}}}function Qd(e){let t=e.lastIndexOf("-");if(t<0)return;let r=e.slice(t+1);return/^\d+(\.\d+)*$/.test(r)?r:void 0}function Zd(e){let t=e.checks.find(r=>r.mobile);if(t)return t.platform==="ios"?"ios":"android"}async function yc(e,t,r={}){let s=r.config??_n(r.base),o=Zd(e);if(!o)return{ok:!1,errors:[{code:"invalid_plan",detail:"no device member in a device job"}]};let n=e.checks.filter(c=>c.mobile);return o==="ios"?tu(n,t,s,r):eu(n,t,s,r)}async function eu(e,t,r,s){let o=e.filter(l=>l.deviceName).map(l=>`${l.relPath} (device_name: ${l.deviceName})`),n=e.find(l=>l.osVersion)?.osVersion,c=(t.osVersion??n??r.mobile.osVersion).trim();if(t.deviceSlug){let l=t.deviceSlug.trim(),m=Qd(l);return{ok:!0,device:{platform:"android",slug:l,label:{name:l,osVersion:m??c,avdId:"(unvalidated --device-slug)"},ignoredDeviceNames:o}}}let i=(t.deviceName??r.mobile.deviceName).trim(),a=await(s.resolveCatalogFn??Bt)(t.env,t.auth,{platform:"android"});if(!a.ok)return{ok:!1,errors:[{code:"device_catalog_unavailable",detail:a.reason}]};let d=Tr(a.catalog,i,c);return d.ok?{ok:!0,device:{platform:"android",slug:d.resolved.slug,label:{name:d.resolved.device.name,osVersion:d.resolved.osVersion,...d.resolved.avdId?{avdId:d.resolved.avdId}:{}},ignoredDeviceNames:o,...a.warning?{warning:a.warning}:{}}}:{ok:!1,errors:[{code:d.code,detail:d.detail+(t.deviceName?"":`
74
+ (device name came from the remote-execution plugin config, not a flag \u2014 pass --device-name to override)`)}]}}async function tu(e,t,r,s){let o=An("ios");if(t.deviceSlug)return{ok:!1,errors:[{code:"device_slug_android_only",detail:`--device-slug names a HyperExecute emulator slug; a simulator job has no slug to bypass to.
75
+ Use --device-name/--os-version, or the members' own device_name:/os_version:.`}]};let n=await(s.resolveCatalogFn??Bt)(t.env,t.auth,{platform:"ios"});if(!n.ok)return{ok:!1,errors:[{code:"device_catalog_unavailable",detail:n.reason}]};let c=n.catalog,i=t.deviceName?.trim(),a=t.osVersion?.trim(),d=v=>r.mobile.ios.runson[Je(v)]??c.runson?.[Je(v)],l=new Map,m=new Map,p;for(let v of e){let x=i??v.deviceName?.trim()??r.mobile.ios.deviceName,T=a??v.osVersion?.trim()??r.mobile.ios.osVersion,S=Tr(c,x,T);if(!S.ok){let k=i?"--device-name":v.deviceName?`${v.relPath} device_name:`:"the remote-execution plugin config",h=a?"--os-version":v.osVersion?`${v.relPath} os_version:`:"the remote-execution plugin config",R=`${S.code}
76
+ ${S.detail}`,O=l.get(R)??{code:S.code,detail:S.detail,sources:[]};O.sources.push(`device name from ${k}; ${o.os} version from ${h}`),l.set(R,O);continue}let w=S.resolved.pool??d(T);if(!w){let k=`device_pool_unknown
77
+ ${T}`,h=l.get(k)??{code:"device_pool_unknown",detail:`no HyperExecute pool is known for ${o.os} ${T}.
78
+ The catalog's runson map names a pool per iOS major; set mobile.ios.runson["${Je(T)}"] in the remote-execution plugin config to override.`,sources:[]};h.sources.push(v.relPath),l.set(k,h);continue}let f=r.mobile.ios.runson[Je(T)]??w;m.set(f,[...m.get(f)??[],`${v.relPath} (${o.os} ${T})`]),p??={name:S.resolved.device.name,osVersion:T,slug:S.resolved.slug}}if(l.size)return{ok:!1,errors:[...l.values()].map(v=>({code:v.code,detail:`${v.detail}
79
79
  (${[...new Set(v.sources)].join(`
80
80
  `)})`}))};if(m.size>1)return{ok:!1,errors:[{code:"mobile_pool_split",detail:`simulator tests in this selection need different HyperExecute pools, and one grid job runs on one:
81
- `+[...m.entries()].map(([v,k])=>` ${v}: ${k.join(", ")}`).join(`
81
+ `+[...m.entries()].map(([v,x])=>` ${v}: ${x.join(", ")}`).join(`
82
82
  `)+`
83
- Split it into one run per pool (--match/--tags), or pass --os-version to force one.`}]};let g=[...m.keys()][0],u=s||a?{...s?{deviceName:s}:{},...a?{osVersion:a}:{}}:void 0;return{ok:!0,device:{platform:"ios",slug:p.slug,label:{name:p.name,osVersion:p.osVersion},ignoredDeviceNames:[],pool:g,...u?{deviceFlags:u}:{},...n.warning?{warning:n.warning}:{}}}}var vc="\x1B[2m",bc="\x1B[0m";function nu(e){return e.local?{shouldPublish:!1,reason:"local"}:e.hasAuth?e.projectId==null?{shouldPublish:!1,reason:"no_project"}:e.evidencePublish===!1?{shouldPublish:!1,reason:"flag"}:{shouldPublish:!0}:{shouldPublish:!1,reason:"no_auth"}}function ru(e,t){if(e.cancelled)return{status:"cancelled",exit:3};if(e.artifactless)return t!==0?{status:"failed",exit:t}:{status:"broken",exit:1};let r=o=>Number(e.totals?.[o]??0);return r("failed")>0||r("broken")>0?{status:"failed",exit:1}:{status:e.execution?.status??(e.authored.length?"authored":"passed"),exit:0}}async function wc(e,t,r,i){let o=_=>{for(let C of _)i.emit(kn(C));if(!i.isAgent)for(let C of _)process.stderr.write(`error: [${C.code}] ${C.detail}
84
- `);i.emit(Ct("","failed")),i.emit(Ut({status:"failed",exit:2,jobId:"",sessionsPath:""})),process.exitCode=2},n=typeof t.remote=="string"&&t.remote?t.remote:"hyper",s=(i.findBackendFn??tc)(n);if(!s){o([{code:"unknown_backend",detail:`unknown remote backend '${n}'`}]);return}let a=i.log??(()=>{}),l=await(i.resolveContext??sc)({envFlag:t.env,usernameFlag:t.username,accessKeyFlag:t.accessKey,memberClasses:e.checks.map(_=>_.memberClass),planProjectId:e.projectId,dryRun:!!t.dryRun,local:!!t.local,log:a},{});if(!l.ok){o([{code:l.code,detail:l.detail}]);return}i.isAgent&&l.ctx.autoDefaulted&&i.emit(Do(l.ctx.autoDefaulted));let m={command:"testrun",plan:e,cwd:r,jobId:Zd(),parallel:Number(t.parallel??1),env:l.ctx.env,auth:l.ctx.auth,orgId:l.ctx.orgId,plugin:l.ctx.plugin,projectId:l.ctx.projectId,folderId:l.ctx.folderId,...t.kaneVersion?{kaneVersion:t.kaneVersion}:{},...t.runson?{runson:t.runson}:{},...t.kaneDist?{kaneDist:t.kaneDist}:{},memberFlags:ja(t)},p=s.preflight(m);if(!p.ok){o(p.errors);return}if(e.checks.some(_=>_.mobile)){let _=await(i.resolveDevice??hc)(e,{deviceName:t.deviceName,osVersion:t.osVersion,deviceSlug:t.deviceSlug,env:m.env,auth:{username:m.auth.username,accessKey:m.auth.access_key}});if(!_.ok){o(_.errors);return}m.deviceSlug=_.device.slug,m.deviceLabel=_.device.label,m.devicePlatform=_.device.platform,_.device.pool&&(m.devicePool=_.device.pool),_.device.deviceFlags&&(m.deviceFlags=_.device.deviceFlags);for(let M of _.device.ignoredDeviceNames){let O=mr({reason:"device_name_ignored",detail:`${M} \u2014 a remote job's device is named by the grid catalog, not by a local AVD name. Use --device-name to choose a grid device.`});i.emit(O),i.isAgent||process.stderr.write(`note: ${O.detail}
85
- `)}if(_.device.warning){let M=mr({reason:"catalog_stale",detail:_.device.warning});i.emit(M),i.isAgent||process.stderr.write(`warning: ${M.detail}
86
- `)}i.emit(ga({platform:_.device.platform,slug:_.device.slug,..._.device.label,..._.device.pool?{pool:_.device.pool}:{}})),i.isAgent||process.stderr.write(_.device.platform==="ios"?`simulators: pool ${_.device.pool}`+(_.device.deviceFlags?` \xB7 ${_.device.deviceFlags.deviceName??"each file's device_name:"} \xB7 iOS ${_.device.deviceFlags.osVersion??"each file's os_version:"}`:" \xB7 each member binds its own device_name:/os_version:")+`
83
+ Split it into one run per pool (--match/--tags), or pass --os-version to force one.`}]};let g=[...m.keys()][0],u=i||a?{...i?{deviceName:i}:{},...a?{osVersion:a}:{}}:void 0;return{ok:!0,device:{platform:"ios",slug:p.slug,label:{name:p.name,osVersion:p.osVersion},ignoredDeviceNames:[],pool:g,...u?{deviceFlags:u}:{},...n.warning?{warning:n.warning}:{}}}}var kc="\x1B[2m",xc="\x1B[0m";function su(e){return e.local?{shouldPublish:!1,reason:"local"}:e.hasAuth?e.projectId==null?{shouldPublish:!1,reason:"no_project"}:e.evidencePublish===!1?{shouldPublish:!1,reason:"flag"}:{shouldPublish:!0}:{shouldPublish:!1,reason:"no_auth"}}function iu(e,t){if(e.cancelled)return{status:"cancelled",exit:3};if(e.artifactless)return t!==0?{status:"failed",exit:t}:{status:"broken",exit:1};let r=o=>Number(e.totals?.[o]??0);return r("failed")>0||r("broken")>0?{status:"failed",exit:1}:{status:e.execution?.status??(e.authored.length?"authored":"passed"),exit:0}}async function Sc(e,t,r,s){let o=_=>{for(let V of _)s.emit(Cn(V));if(!s.isAgent)for(let V of _)process.stderr.write(`error: [${V.code}] ${V.detail}
84
+ `);s.emit(It("","failed")),s.emit(Ut({status:"failed",exit:2,jobId:"",sessionsPath:""})),process.exitCode=2},n=typeof t.remote=="string"&&t.remote?t.remote:"hyper",i=(s.findBackendFn??sc)(n);if(!i){o([{code:"unknown_backend",detail:`unknown remote backend '${n}'`}]);return}let a=s.log??(()=>{}),l=await(s.resolveContext??dc)({envFlag:t.env,usernameFlag:t.username,accessKeyFlag:t.accessKey,memberClasses:e.checks.map(_=>_.memberClass),planProjectId:e.projectId,dryRun:!!t.dryRun,local:!!t.local,log:a},{});if(!l.ok){o([{code:l.code,detail:l.detail}]);return}s.isAgent&&l.ctx.autoDefaulted&&s.emit(Oo(l.ctx.autoDefaulted));let m={command:"testrun",plan:e,cwd:r,jobId:nu(),parallel:Number(t.parallel??1),env:l.ctx.env,auth:l.ctx.auth,orgId:l.ctx.orgId,plugin:l.ctx.plugin,projectId:l.ctx.projectId,folderId:l.ctx.folderId,...t.kaneVersion?{kaneVersion:t.kaneVersion}:{},...t.runson?{runson:t.runson}:{},...t.kaneDist?{kaneDist:t.kaneDist}:{},memberFlags:Ua(t)},p=i.preflight(m);if(!p.ok){o(p.errors);return}if(e.checks.some(_=>_.mobile)){let _=await(s.resolveDevice??yc)(e,{deviceName:t.deviceName,osVersion:t.osVersion,deviceSlug:t.deviceSlug,env:m.env,auth:{username:m.auth.username,accessKey:m.auth.access_key}});if(!_.ok){o(_.errors);return}m.deviceSlug=_.device.slug,m.deviceLabel=_.device.label,m.devicePlatform=_.device.platform,_.device.pool&&(m.devicePool=_.device.pool),_.device.deviceFlags&&(m.deviceFlags=_.device.deviceFlags);for(let I of _.device.ignoredDeviceNames){let L=hr({reason:"device_name_ignored",detail:`${I} \u2014 a remote job's device is named by the grid catalog, not by a local AVD name. Use --device-name to choose a grid device.`});s.emit(L),s.isAgent||process.stderr.write(`note: ${L.detail}
85
+ `)}if(_.device.warning){let I=hr({reason:"catalog_stale",detail:_.device.warning});s.emit(I),s.isAgent||process.stderr.write(`warning: ${I.detail}
86
+ `)}s.emit(wa({platform:_.device.platform,slug:_.device.slug,..._.device.label,..._.device.pool?{pool:_.device.pool}:{}})),s.isAgent||process.stderr.write(_.device.platform==="ios"?`simulators: pool ${_.device.pool}`+(_.device.deviceFlags?` \xB7 ${_.device.deviceFlags.deviceName??"each file's device_name:"} \xB7 iOS ${_.device.deviceFlags.osVersion??"each file's os_version:"}`:" \xB7 each member binds its own device_name:/os_version:")+`
87
87
  `:`device: ${_.device.label.name} \xB7 Android ${_.device.label.osVersion} \xB7 slug ${_.device.slug} \xB7 avd ${_.device.label.avdId}
88
- `);let C=await(i.resolveApp??Pa)(e,{env:m.env,auth:{username:m.auth.username,accessKey:m.auth.access_key},orgId:m.orgId,userId:String(l.ctx.resolvedCreds?.user_id??""),dryRun:!!t.dryRun,...i.isAgent?{}:{onProgress:M=>process.stderr.write(`${M}
89
- `)}});if(!C.ok){o(C.errors);return}Object.keys(C.app.byMember).length&&(m.appIds=C.app.byMember);for(let M of C.app.uploads)i.emit(ha({path:M.path,appId:M.appId,source:M.source})),i.isAgent||process.stderr.write(M.source==="dry-run"?`app: ${_r(r,M.path)||M.path} \u2014 would be uploaded before dispatch (dry run)
90
- `:`app: ${_r(r,M.path)||M.path} \u2192 ${M.appId} (${M.source==="cache"?"already in the cloud":"uploaded"})
91
- `)}if(t.dryRun){i.isAgent||process.stderr.write(`\u2713 remote preflight passed \u2014 ${m.plan.checks.length} member(s), backend '${n}', env '${m.env}'`+(m.devicePlatform==="ios"?`, pool '${m.runson??m.devicePool}'`:m.deviceSlug?`, device '${m.deviceSlug}'`:"")+`
92
- `),process.exitCode=0;return}i.emit(fa({backend:n,env:m.env})),i.isTTYView&&process.stderr.write(`
93
- ${vc}remote testrun \xB7 ${n} \xB7 env ${m.env} \xB7 dispatching\u2026${bc}
94
- `);let g=await s.prepare(m);for(let _ of g.skippedImports??[])i.emit(Vt({path:_r(m.cwd,_.unitAbsPath),status:"skipped",reason:_.reason}));let u=tu(g.jobDir,"hyper.log"),v=Date.now(),k=await s.dispatch(g,{signal:i.signal,onLine:_=>{try{eu(u,_+`
95
- `)}catch{}i.isTTYView&&/Job Link:|ERR::|error|failed|✔|✗|scenario|completed/i.test(_)&&process.stderr.write(`${vc}${_}${bc}
96
- `)}});i.emit(va({jobId:k.hxJobId,jobUrl:k.jobUrl}));let R=await s.collect(k),S=e.projectId??m.projectId,w=nu({local:!!t.local,hasAuth:!!(m.auth?.username&&m.auth?.access_key),projectId:S,evidencePublish:t.evidencePublish});w.shouldPublish||a("info","PUBLISH_SKIPPED","Remote testrun evidence publish skipped",{surface:"testrun_remote",reason:w.reason});let I=re(m.env),f=l.ctx.resolvedCreds,x=w.shouldPublish?async _=>{let C=await pn({controller:new gt(I.controllerBaseUrl,{username:m.auth.username,accessKey:m.auth.access_key}),tms:new en(I.tmsBaseUrl,f?.username??m.auth.username,f?.access_key??m.auth.access_key),..._});if(C.ok)return a("info","EVIDENCE_PUBLISH_OK","Remote testrun evidence published",{surface:"testrun_remote",execution_id:_.executionId}),{ok:!0};let M=/\b(\d{3})\b/.exec(C.error)?.[1]??null;return a("error","EVIDENCE_PUBLISH_FAILED","Remote testrun evidence publish failed",{surface:"testrun_remote",stage:C.stage,http_status:M?Number(M):null,error:C.error}),{ok:!1,stage:C.stage}}:void 0,h=await s.reconcile(R,{emit:i.emit,publishFn:x,log:a});w.shouldPublish&&h.cancelled&&a("info","PUBLISH_SKIPPED","Remote testrun evidence publish skipped",{surface:"testrun_remote",reason:"cancel"}),h.degraded&&!i.isAgent&&(process.stderr.write(`
88
+ `);let V=await(s.resolveApp??Ma)(e,{env:m.env,auth:{username:m.auth.username,accessKey:m.auth.access_key},orgId:m.orgId,userId:String(l.ctx.resolvedCreds?.user_id??""),dryRun:!!t.dryRun,...s.isAgent?{}:{onProgress:I=>process.stderr.write(`${I}
89
+ `)}});if(!V.ok){o(V.errors);return}Object.keys(V.app.byMember).length&&(m.appIds=V.app.byMember);for(let I of V.app.uploads)s.emit(ya({path:I.path,appId:I.appId,source:I.source})),s.isAgent||process.stderr.write(I.source==="dry-run"?`app: ${Pr(r,I.path)||I.path} \u2014 would be uploaded before dispatch (dry run)
90
+ `:`app: ${Pr(r,I.path)||I.path} \u2192 ${I.appId} (${I.source==="cache"?"already in the cloud":"uploaded"})
91
+ `)}if(t.dryRun){s.isAgent||process.stderr.write(`\u2713 remote preflight passed \u2014 ${m.plan.checks.length} member(s), backend '${n}', env '${m.env}'`+(m.devicePlatform==="ios"?`, pool '${m.runson??m.devicePool}'`:m.deviceSlug?`, device '${m.deviceSlug}'`:"")+`
92
+ `),process.exitCode=0;return}s.emit(ba({backend:n,env:m.env})),s.isTTYView&&process.stderr.write(`
93
+ ${kc}remote testrun \xB7 ${n} \xB7 env ${m.env} \xB7 dispatching\u2026${xc}
94
+ `);let g=await i.prepare(m);for(let _ of g.skippedImports??[])s.emit(Vt({path:Pr(m.cwd,_.unitAbsPath),status:"skipped",reason:_.reason}));let u=ou(g.jobDir,"hyper.log"),v=Date.now(),x=await i.dispatch(g,{signal:s.signal,onLine:_=>{try{ru(u,_+`
95
+ `)}catch{}s.isTTYView&&/Job Link:|ERR::|error|failed|✔|✗|scenario|completed/i.test(_)&&process.stderr.write(`${kc}${_}${xc}
96
+ `)}});s.emit(ka({jobId:x.hxJobId,jobUrl:x.jobUrl}));let T=await i.collect(x),S=e.projectId??m.projectId,w=su({local:!!t.local,hasAuth:!!(m.auth?.username&&m.auth?.access_key),projectId:S,evidencePublish:t.evidencePublish});w.shouldPublish||a("info","PUBLISH_SKIPPED","Remote testrun evidence publish skipped",{surface:"testrun_remote",reason:w.reason});let C=oe(m.env),f=l.ctx.resolvedCreds,k=w.shouldPublish?async _=>{let V=await hn({controller:new gt(C.controllerBaseUrl,{username:m.auth.username,accessKey:m.auth.access_key}),tms:new tn(C.tmsBaseUrl,f?.username??m.auth.username,f?.access_key??m.auth.access_key),..._});if(V.ok)return a("info","EVIDENCE_PUBLISH_OK","Remote testrun evidence published",{surface:"testrun_remote",execution_id:_.executionId}),{ok:!0};let I=/\b(\d{3})\b/.exec(V.error)?.[1]??null;return a("error","EVIDENCE_PUBLISH_FAILED","Remote testrun evidence publish failed",{surface:"testrun_remote",stage:V.stage,http_status:I?Number(I):null,error:V.error}),{ok:!1,stage:V.stage}}:void 0,h=await i.reconcile(T,{emit:s.emit,publishFn:k,log:a});w.shouldPublish&&h.cancelled&&a("info","PUBLISH_SKIPPED","Remote testrun evidence publish skipped",{surface:"testrun_remote",reason:"cancel"}),h.degraded&&!s.isAgent&&(process.stderr.write(`
97
97
  warning: evidence merge degraded (${h.degraded.reason})${h.degraded.detail?` \u2014 ${h.degraded.detail}`:""}
98
98
  `),h.degraded.standaloneIds?.length&&process.stderr.write(` packs kept standalone: ${h.degraded.standaloneIds.join(", ")}
99
- `));let P=h.execSync;if(P&&!i.isAgent){P.status==="failed"&&process.stderr.write(`
100
- warning: execution facts were not recorded in the local assurance graph${P.detail?` \u2014 ${P.detail}`:""}
101
- `);for(let _ of P.warnings)process.stderr.write(` ${_}
102
- `)}i.emit(yn({execution:h.execution?{id:h.execution.id,status:h.execution.status,evidence_id:h.execution.evidenceId}:null,authored:h.authored.map(_=>({path:_.relPath,test_id:_.testId,commit_id:_.commitId,execution_id:_.executionId,..._.sourceExecutionId?{source_execution_id:_.sourceExecutionId}:{},status:_.overallStatus,published:_.published})),totals:h.totals,durationS:(Date.now()-v)/1e3,upload:h.upload,cancelled:h.cancelled,remote:{backend:n,jobId:h.hxJobId,jobUrl:h.jobUrl,sessionsPath:h.sessionsPath}}));try{let _=fs({executionId:h.execution?.id,executionStatus:h.execution?.status,authored:h.authored,cwd:r});if(i.isTTYView)process.stderr.write(`
99
+ `));let R=h.execSync;if(R&&!s.isAgent){R.status==="failed"&&process.stderr.write(`
100
+ warning: execution facts were not recorded in the local assurance graph${R.detail?` \u2014 ${R.detail}`:""}
101
+ `);for(let _ of R.warnings)process.stderr.write(` ${_}
102
+ `)}s.emit(Sn({execution:h.execution?{id:h.execution.id,status:h.execution.status,evidence_id:h.execution.evidenceId}:null,authored:h.authored.map(_=>({path:_.relPath,test_id:_.testId,commit_id:_.commitId,execution_id:_.executionId,..._.sourceExecutionId?{source_execution_id:_.sourceExecutionId}:{},status:_.overallStatus,published:_.published})),totals:h.totals,durationS:(Date.now()-v)/1e3,upload:h.upload,cancelled:h.cancelled,remote:{backend:n,jobId:h.hxJobId,jobUrl:h.jobUrl,sessionsPath:h.sessionsPath}}));try{let _=bi({executionId:h.execution?.id,executionStatus:h.execution?.status,authored:h.authored,cwd:r});if(s.isTTYView)process.stderr.write(`
103
103
  Remote job: ${h.jobUrl||"(job id not captured)"}
104
104
  `),process.stderr.write(`Sessions: ${h.sessionsPath}
105
- `),_.length&&await hs({rows:_,env:m.env});else if(!i.isAgent){process.stderr.write(`
105
+ `),_.length&&await yi({rows:_,env:m.env});else if(!s.isAgent){process.stderr.write(`
106
106
  Remote job: ${h.jobUrl||"(job id not captured)"}
107
107
  `),process.stderr.write(`Sessions: ${h.sessionsPath}
108
- `);let C=gs(_);if(C.length){process.stderr.write(`
108
+ `);let V=wi(_);if(V.length){process.stderr.write(`
109
109
  Evidence \u2014 view locally:
110
- `);for(let M of C)process.stderr.write(` ${M}
111
- `)}}}catch(_){i.isAgent||process.stderr.write(`warning: evidence presentation failed: ${_.message}
112
- `)}let N=ru(h,k.exitCode);h.artifactless&&k.exitCode===0&&!i.isAgent&&process.stderr.write(`
110
+ `);for(let I of V)process.stderr.write(` ${I}
111
+ `)}}}catch(_){s.isAgent||process.stderr.write(`warning: evidence presentation failed: ${_.message}
112
+ `)}let O=iu(h,x.exitCode);h.artifactless&&x.exitCode===0&&!s.isAgent&&process.stderr.write(`
113
113
  error: the grid job exited 0 but no session artifacts came home \u2014 nothing to reconcile. Check the job's dashboard artifacts (${h.jobUrl||h.hxJobId}).
114
- `),i.emit(Ct(h.execution?.id??"",N.status==="cancelled"?"cancelled":N.status==="failed"||N.status==="broken"?"failed":"passed")),i.emit(Ut({status:N.status,exit:N.exit,jobId:h.hxJobId,sessionsPath:h.sessionsPath})),process.exitCode=N.exit}import{randomUUID as cu}from"crypto";import{existsSync as yc,mkdtempSync as ou,readFileSync as iu,rmSync as Tn,writeFileSync as su}from"fs";import{tmpdir as au}from"os";import{join as Er}from"path";function xc(e){let t=e.checks.some(r=>r.memberClass==="author");return{willConsolidate:t,interimShouldPublish:e.shouldPublish&&!t}}function Sc(e,t){for(let r of e)r.executionId&&(r.sourceExecutionId=r.executionId,r.executionId=t)}var Tt=e=>e instanceof Error?e.message:String(e);async function kc(e,t){if(!e.shouldPublish||!e.publish)return"skipped";let r=e.checks.find(o=>o.memberClass==="replay"&&o.testId)?.testId??e.authored.find(o=>o.testId)?.testId;if(!r||e.projectId==null)return"skipped";let i=await e.publish({testId:r,sessionId:t,executionId:t,sealedPackPath:Pe(t,e.cwd),projectId:e.projectId});return e.emit(It(i,t)),i.ok?"ok":"failed"}async function Ic(e){let t=e.mergeFn??on,r=e.sealFn??wt,i=e.authored.filter(u=>u.executionId).map(u=>({id:u.executionId,path:Pe(u.executionId,e.cwd)})).filter(u=>yc(u.path)),o=e.interim?Pe(e.interim.executionId,e.cwd):null,n=async u=>(e.log("warn","TESTRUN_CONSOLIDATION_DEGRADED","Local consolidation fell back to split evidence",{reason:u}),{kind:"split",upload:e.interim?await kc(e,e.interim.executionId):"skipped",reason:u});if(i.length===0)return n("no authored packs to fold in");let c,s;try{c=ou(Er(au(),"kane-local-merge-rules-")),s=Er(c,"merge-rules.yaml"),su(s,ln())}catch(u){return c&&Tn(c,{recursive:!0,force:!0}),n(`merge rules unavailable: ${Tt(u)}`)}let a=yt(),d=Pe(a,e.cwd),l=[...o&&yc(o)?[o]:[],...i.map(u=>u.path)];try{await t(l,{runId:a,out:d,rulesPath:s,finalize:!1})}catch(u){return Tn(d,{recursive:!0,force:!0}),n(`merge failed: ${Tt(u)}`)}finally{c&&Tn(c,{recursive:!0,force:!0})}let m=e.checks.map(u=>({path:"",memberClass:u.memberClass,relPath:u.relPath}));try{let u=Sr(d,m);u.errors.length&&e.log("warn","TESTRUN_CONSOLIDATION_STAMP_INCOMPLETE","Some merged tests missed their run_kind stamp",{execution_id:a,errors:u.errors.slice(0,5)})}catch(u){e.log("warn","TESTRUN_CONSOLIDATION_STAMP_FAILED","run_kind stamping threw",{execution_id:a,error:Tt(u)})}try{(e.coverageWriter??kt)(d,Ye(e.cwd))}catch(u){e.log("warn","TESTRUN_COVERAGE_WRITER_THREW","Coverage writer threw on the consolidated pack",{execution_id:a,error:Tt(u)})}let p=new Map;for(let u of e.checks)try{let v=vt(iu(Er(d,"tests",Ee(u.relPath),"result.yaml"),"utf8"));typeof v?.status=="string"&&p.set(u.relPath,v.status)}catch{}try{let u=l.map(k=>({path:k,memberClass:"replay",relPath:""})),v=await Ir(u)??new Date().toISOString();await r(d,v)}catch(u){return Tn(d,{recursive:!0,force:!0}),n(`seal failed: ${Tt(u)}`)}try{let u=await(e.validateFn??bt)(d,"L1");u.valid||e.log("warn","EVIDENCE_INVALID","Sealed consolidated pack failed L1 validation",{execution_id:a,first_code:String(u.diagnostics?.[0]?.code??""),surface:"testrun"})}catch(u){e.log("warn","TESTRUN_VALIDATION_ERROR","Consolidated pack validation threw",{execution_id:a,error:Tt(u)})}let g=await kc(e,a);for(let u of e.checks){let v=p.get(u.relPath);if(v)try{await sn(Ae(u.path),{execution_id:a,run_kind:u.memberClass==="author"?"author":"replay",status:v,at:new Date().toISOString(),...g==="ok"?{uploaded:!0}:{}})}catch{}}return{kind:"merged",executionId:a,upload:g}}function Cc(e,t){return t.concat(e.split(",").map(r=>r.trim()).filter(r=>r.length>0))}function Pr(e){return e===1?"failed":e===3?"cancelled":"passed"}function lu(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new es(`--parallel must be a positive integer, got: ${e}`);return e}function Ec(){let e=new ct("testrun").description("Run M authored *_test.md files as one execution (one sealed evidence pack)");return e.command("run [paths...]").description("Select + preflight + execute *_test.md members").option("--match <regex>","Filter candidates by project-relative path regex").option("--tags <list>","ANY-match on frontmatter tags (repeatable or comma-separated)",Cc,[]).option("--from-context <ids>","Select members by assurance-graph test ids, e.g. T-1,T-2 (repeatable or comma-separated; unions with explicit paths)",Cc,[]).option("--parallel <n>","Worker count",lu,"1").option("--on-failure <mode>","continue | fail-fast",t=>{if(t!=="continue"&&t!=="fail-fast")throw new Error(`--on-failure must be continue|fail-fast, got: ${t}`);return t},"continue").option("--name <label>","run.yaml title (default: derived from the selection query)").option("--dry-run","Plan + validate only, execute nothing").option("--remote [backend]","Dispatch to a remote grid instead of local Chrome (default backend: hyper). Requires `kane-cli plugin install remote-execution`.").option("--no-adaptive-heal","disable adaptive heal for every member \u2014 a replay miss becomes terminal instead of re-authoring the failing tail (default: heal on, 3 attempts then a full re-author)").option("--author","re-author every member in place on its existing identity and commit a new version").addOption(new B("--no-testmd-sync","skip the testmd bundle push before each member's commit \u2014 the caller owns the bundle").hideHelp()).option("--bug-detection <mode>","detect product bugs while authoring member steps: off|stop|continue. Overrides `config set-bug-detection`.",t=>{if(t!=="off"&&t!=="stop"&&t!=="continue")throw new Error(`--bug-detection must be off, stop or continue, got: ${t}`);return t}).addOption(new B("--retry","(retired) adaptive heal is on by default").hideHelp()).addOption(new B("--retry-count <n>","(retired) heal budget is fixed at 3").argParser(t=>{let r=parseInt(t,10);if(Number.isNaN(r)||r<0)throw new Error(`--retry-count must be a non-negative integer, got: ${t}`);return t}).hideHelp()).option("--headless","Run Chrome in headless mode").option("--device-name <name>","Device for the run's mobile members. Locally: as `kane-cli devices list` shows it. With --remote: a grid device from `kane-cli devices list --target emulator --remote`, validated before dispatch. The OS version comes from --os-version or each member's own os_version:").option("--os-version <version>","OS version for the run's mobile members (e.g. 17.5, 14). Alone = any device on that version").option("--dataset-id <id>","Test Manager dataset whose row supplies every member's ${column} parameters (overrides each file's dataset:)").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (overrides each file's dataset.row)").addOption(new B("--device-slug <slug>","(--remote, emulator) raw HyperExecute device slug (<configName>-<androidVersion>), bypassing catalog validation; the member binds the slug's version").hideHelp()).addOption(new B("--runson <label>","(--remote) HyperExecute host pool override").hideHelp()).addOption(new B("--kane-version <version>","(--remote) kane-cli version the grid installs (default: latest)").hideHelp()).addOption(new B("--kane-dist <dir>","(--remote, dev) cwd-relative dir holding a built kane-cli dist/ to swap over the grid's npm install").hideHelp()).option("--env <name>","Environment (prod or stage)").addOption(new B("--local","Skip TMS integration (no uploads, no evidence publish)").hideHelp()).addOption(new B("--no-evidence-publish","skip the sealed pack's evidence publish (blob upload + TMS /evidence/ingest) \u2014 the run leaves no execution record in TMS").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").action(async(t,r)=>{await du(t,r)}),e}async function du(e,t){let r=xi(t);r&&process.stderr.write(r+`
115
- `);let i=t.cwd??process.cwd(),o=!process.stdin.isTTY,n=!o&&!!process.stderr.isTTY,c={current:null};{let $=Pi({deviceName:t.deviceName,osVersion:t.osVersion});if(!$.ok){process.stderr.write(`error: ${$.message}
116
- `),process.exitCode=2;return}}let s;try{s=await aa({paths:e.length>0?e:void 0,match:t.match,tags:t.tags?.length?t.tags:void 0,fromContext:t.fromContext?.length?t.fromContext:void 0,parallel:t.parallel!==void 0?Number(t.parallel):void 0,onFailure:t.onFailure,name:t.name,deviceOverride:t.deviceName!==void 0||t.osVersion!==void 0,remote:!!t.remote,cwd:i})}catch($){if($ instanceof pe){process.stderr.write(`error: ${$.message}
117
- `),process.exitCode=2;return}throw $}let a=n&&s.valid&&!t.dryRun&&!t.remote,d=gu(o,a?$=>c.current?.($):void 0);if(o?d(ca(s)):a?(s.unresolved??[]).length>0&&process.stderr.write(Nt(s.unresolved,{cwd:process.cwd()})):_c(s),vu(s,o,d,i),t.remote){if(!s.valid){o||Rr(s),process.exitCode=2;return}let $=t.__runRemote??wc;try{await $(s,t,i,{emit:d,isAgent:o,isTTYView:n})}catch(be){let Q=be.message;d(kn({code:"internal_error",detail:Q})),d(Ct("","failed")),d(Ut({status:"failed",exit:1,jobId:"",sessionsPath:""})),o||process.stderr.write(`error: remote run crashed: ${Q}
118
- `),process.exitCode=1}return}if(t.dryRun){!s.valid&&!o&&Rr(s),process.exitCode=s.valid?0:2;return}if(!s.valid){o||Rr(s),process.exitCode=2;return}let l=new le,m=new Te,p=l.getActiveProfile()??"default",g=t.env??l.getDefaultEnv()??"prod",u=re(g),v="v16-alpha",k;try{k=await Ue({creds:l,env:g,usernameFlag:t.username,accessKeyFlag:t.accessKey,log:()=>{}})}catch($){a&&_c(s,{receipt:!1}),$ instanceof Ot&&$.code==="not_authenticated"?process.stderr.write(`error: Not authenticated. Choose one:
114
+ `),s.emit(It(h.execution?.id??"",O.status==="cancelled"?"cancelled":O.status==="failed"||O.status==="broken"?"failed":"passed")),await on({env:m.env,userId:Number(l.ctx.resolvedCreds?.user_id??0),runsCompleted:(h.totals.passed??0)+(h.totals.failed??0)+(h.totals.broken??0),data:{referenceId:h.execution?.id||h.hxJobId,startedAt:new Date(v).toISOString(),completedAt:new Date().toISOString(),creditsConsumed:h.totals.creditsConsumed??0,runType:"testrun",target:rn(e.checks)},log:s.log}),s.emit(Ut({status:O.status,exit:O.exit,jobId:h.hxJobId,sessionsPath:h.sessionsPath})),process.exitCode=O.exit}import{randomUUID as uu}from"crypto";import{existsSync as Cc,mkdtempSync as au,readFileSync as cu,rmSync as Dn,writeFileSync as lu}from"fs";import{tmpdir as du}from"os";import{join as Ar}from"path";function _c(e){let t=e.checks.some(r=>r.memberClass==="author");return{willConsolidate:t,interimShouldPublish:e.shouldPublish&&!t}}function Ec(e,t){for(let r of e)r.executionId&&(r.sourceExecutionId=r.executionId,r.executionId=t)}var Tt=e=>e instanceof Error?e.message:String(e);async function Ic(e,t){if(!e.shouldPublish||!e.publish)return"skipped";let r=e.checks.find(o=>o.memberClass==="replay"&&o.testId)?.testId??e.authored.find(o=>o.testId)?.testId;if(!r||e.projectId==null)return"skipped";let s=await e.publish({testId:r,sessionId:t,executionId:t,sealedPackPath:De(t,e.cwd),projectId:e.projectId});return e.emit(Ct(s,t)),s.ok?"ok":"failed"}async function Rc(e){let t=e.mergeFn??cn,r=e.sealFn??wt,s=e.authored.filter(u=>u.executionId).map(u=>({id:u.executionId,path:De(u.executionId,e.cwd)})).filter(u=>Cc(u.path)),o=e.interim?De(e.interim.executionId,e.cwd):null,n=async u=>(e.log("warn","TESTRUN_CONSOLIDATION_DEGRADED","Local consolidation fell back to split evidence",{reason:u}),{kind:"split",upload:e.interim?await Ic(e,e.interim.executionId):"skipped",reason:u});if(s.length===0)return n("no authored packs to fold in");let c,i;try{c=au(Ar(du(),"kane-local-merge-rules-")),i=Ar(c,"merge-rules.yaml"),lu(i,mn())}catch(u){return c&&Dn(c,{recursive:!0,force:!0}),n(`merge rules unavailable: ${Tt(u)}`)}let a=yt(),d=De(a,e.cwd),l=[...o&&Cc(o)?[o]:[],...s.map(u=>u.path)];try{await t(l,{runId:a,out:d,rulesPath:i,finalize:!1})}catch(u){return Dn(d,{recursive:!0,force:!0}),n(`merge failed: ${Tt(u)}`)}finally{c&&Dn(c,{recursive:!0,force:!0})}let m=e.checks.map(u=>({path:"",memberClass:u.memberClass,relPath:u.relPath}));try{let u=Er(d,m);u.errors.length&&e.log("warn","TESTRUN_CONSOLIDATION_STAMP_INCOMPLETE","Some merged tests missed their run_kind stamp",{execution_id:a,errors:u.errors.slice(0,5)})}catch(u){e.log("warn","TESTRUN_CONSOLIDATION_STAMP_FAILED","run_kind stamping threw",{execution_id:a,error:Tt(u)})}try{(e.coverageWriter??kt)(d,He(e.cwd))}catch(u){e.log("warn","TESTRUN_COVERAGE_WRITER_THREW","Coverage writer threw on the consolidated pack",{execution_id:a,error:Tt(u)})}let p=new Map;for(let u of e.checks)try{let v=vt(cu(Ar(d,"tests",Re(u.relPath),"result.yaml"),"utf8"));typeof v?.status=="string"&&p.set(u.relPath,v.status)}catch{}try{let u=l.map(x=>({path:x,memberClass:"replay",relPath:""})),v=await Rr(u)??new Date().toISOString();await r(d,v)}catch(u){return Dn(d,{recursive:!0,force:!0}),n(`seal failed: ${Tt(u)}`)}try{let u=await(e.validateFn??bt)(d,"L1");u.valid||e.log("warn","EVIDENCE_INVALID","Sealed consolidated pack failed L1 validation",{execution_id:a,first_code:String(u.diagnostics?.[0]?.code??""),surface:"testrun"})}catch(u){e.log("warn","TESTRUN_VALIDATION_ERROR","Consolidated pack validation threw",{execution_id:a,error:Tt(u)})}let g=await Ic(e,a);for(let u of e.checks){let v=p.get(u.relPath);if(v)try{await ln($e(u.path),{execution_id:a,run_kind:u.memberClass==="author"?"author":"replay",status:v,at:new Date().toISOString(),...g==="ok"?{uploaded:!0}:{}})}catch{}}return{kind:"merged",executionId:a,upload:g}}function Tc(e,t){return t.concat(e.split(",").map(r=>r.trim()).filter(r=>r.length>0))}function Mr(e){return e===1?"failed":e===3?"cancelled":"passed"}function mu(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new oi(`--parallel must be a positive integer, got: ${e}`);return e}function Ac(){let e=new ct("testrun").description("Run M authored *_test.md files as one execution (one sealed evidence pack)");return e.command("run [paths...]").description("Select + preflight + execute *_test.md members").option("--match <regex>","Filter candidates by project-relative path regex").option("--tags <list>","ANY-match on frontmatter tags (repeatable or comma-separated)",Tc,[]).option("--from-context <ids>","Select members by assurance-graph test ids, e.g. T-1,T-2 (repeatable or comma-separated; unions with explicit paths)",Tc,[]).option("--parallel <n>","Worker count",mu,"1").option("--on-failure <mode>","continue | fail-fast",t=>{if(t!=="continue"&&t!=="fail-fast")throw new Error(`--on-failure must be continue|fail-fast, got: ${t}`);return t},"continue").option("--name <label>","run.yaml title (default: derived from the selection query)").option("--dry-run","Plan + validate only, execute nothing").option("--remote [backend]","Dispatch to a remote grid instead of local Chrome (default backend: hyper). Requires `kane-cli plugin install remote-execution`.").option("--no-adaptive-heal","disable adaptive heal for every member \u2014 a replay miss becomes terminal instead of re-authoring the failing tail (default: heal on, 3 attempts then a full re-author)").option("--author","re-author every member in place on its existing identity and commit a new version").addOption(new J("--no-testmd-sync","skip the testmd bundle push before each member's commit \u2014 the caller owns the bundle").hideHelp()).option("--bug-detection <mode>","detect product bugs while authoring member steps: off|stop|continue. Overrides `config set-bug-detection`.",t=>{if(t!=="off"&&t!=="stop"&&t!=="continue")throw new Error(`--bug-detection must be off, stop or continue, got: ${t}`);return t}).addOption(new J("--retry","(retired) adaptive heal is on by default").hideHelp()).addOption(new J("--retry-count <n>","(retired) heal budget is fixed at 3").argParser(t=>{let r=parseInt(t,10);if(Number.isNaN(r)||r<0)throw new Error(`--retry-count must be a non-negative integer, got: ${t}`);return t}).hideHelp()).option("--headless","Run Chrome in headless mode").option("--device-name <name>","Device for the run's mobile members. Locally: as `kane-cli devices list` shows it. With --remote: a grid device from `kane-cli devices list --target emulator --remote`, validated before dispatch. The OS version comes from --os-version or each member's own os_version:").option("--os-version <version>","OS version for the run's mobile members (e.g. 17.5, 14). Alone = any device on that version").option("--dataset-id <id>","Test Manager dataset whose row supplies every member's ${column} parameters (overrides each file's dataset:)").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (overrides each file's dataset.row)").addOption(new J("--device-slug <slug>","(--remote, emulator) raw HyperExecute device slug (<configName>-<androidVersion>), bypassing catalog validation; the member binds the slug's version").hideHelp()).addOption(new J("--runson <label>","(--remote) HyperExecute host pool override").hideHelp()).addOption(new J("--kane-version <version>","(--remote) kane-cli version the grid installs (default: latest)").hideHelp()).addOption(new J("--kane-dist <dir>","(--remote, dev) cwd-relative dir holding a built kane-cli dist/ to swap over the grid's npm install").hideHelp()).option("--env <name>","Environment (prod or stage)").addOption(new J("--local","Skip TMS integration (no uploads, no evidence publish)").hideHelp()).addOption(new J("--no-evidence-publish","skip the sealed pack's evidence publish (blob upload + TMS /evidence/ingest) \u2014 the run leaves no execution record in TMS").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").action(async(t,r)=>{await pu(t,r)}),e}async function pu(e,t){let r=_s(t);r&&process.stderr.write(r+`
115
+ `);let s=t.cwd??process.cwd(),o=!process.stdin.isTTY,n=!o&&!!process.stderr.isTTY,c={current:null};{let D=Ms({deviceName:t.deviceName,osVersion:t.osVersion});if(!D.ok){process.stderr.write(`error: ${D.message}
116
+ `),process.exitCode=2;return}}let i;try{i=await ua({paths:e.length>0?e:void 0,match:t.match,tags:t.tags?.length?t.tags:void 0,fromContext:t.fromContext?.length?t.fromContext:void 0,parallel:t.parallel!==void 0?Number(t.parallel):void 0,onFailure:t.onFailure,name:t.name,deviceOverride:t.deviceName!==void 0||t.osVersion!==void 0,remote:!!t.remote,cwd:s})}catch(D){if(D instanceof ve){process.stderr.write(`error: ${D.message}
117
+ `),process.exitCode=2;return}throw D}let a=n&&i.valid&&!t.dryRun&&!t.remote,d=bu(o,a?D=>c.current?.(D):void 0);if(o?d(ma(i)):a?(i.unresolved??[]).length>0&&process.stderr.write(Nt(i.unresolved,{cwd:process.cwd()})):Pc(i),yu(i,o,d,s),t.remote){if(!i.valid){o||Dr(i),process.exitCode=2;return}let D=t.__runRemote??Sc;try{await D(i,t,s,{emit:d,isAgent:o,isTTYView:n})}catch(we){let Z=we.message;d(Cn({code:"internal_error",detail:Z})),d(It("","failed")),d(Ut({status:"failed",exit:1,jobId:"",sessionsPath:""})),o||process.stderr.write(`error: remote run crashed: ${Z}
118
+ `),process.exitCode=1}return}if(t.dryRun){!i.valid&&!o&&Dr(i),process.exitCode=i.valid?0:2;return}if(!i.valid){o||Dr(i),process.exitCode=2;return}let l=new me,m=new Ae,p=l.getActiveProfile()??"default",g=t.env??l.getDefaultEnv()??"prod",u=oe(g),v="v16-alpha",x;try{x=await Be({creds:l,env:g,usernameFlag:t.username,accessKeyFlag:t.accessKey,log:()=>{}})}catch(D){a&&Pc(i,{receipt:!1}),D instanceof Ot&&D.code==="not_authenticated"?process.stderr.write(`error: Not authenticated. Choose one:
119
119
  \u2022 Pass credentials inline: --username <user> --access-key <key>
120
120
  \u2022 Run 'kane-cli login --oauth' (browser-based)
121
121
  \u2022 Run 'kane-cli login --username <user> --access-key <key>'
122
- `):$ instanceof Ot&&$.code==="refresh_failed"?process.stderr.write(`error: Token refresh failed. Run 'kane-cli login' to re-authenticate.
123
- `):process.stderr.write(`error: auth resolution failed: ${$.message}
124
- `),process.exitCode=2;return}let R=null;a&&(R=rt(Tr.default.createElement(ot,null,Tr.default.createElement(ea,{members:s.checks.map($=>({relPath:$.relPath,memberClass:$.memberClass,tags:$.tags})),title:s.title,env:g,dispatchRef:c})),{stdout:process.stderr,exitOnCtrlC:!1}));let S=t.log?{log:t.log,shutdown:async()=>{}}:fu({environment:g,resolvedAuth:k,isAgent:o}),w=S.log,I={adaptiveHeal:t.adaptiveHeal,author:t.author,testmdSync:t.testmdSync,headless:t.headless,env:t.env,local:t.local,username:t.username,accessKey:t.accessKey,bugDetection:t.bugDetection,deviceName:t.deviceName,osVersion:t.osVersion,datasetId:t.datasetId,datasetRow:t.datasetRow},f=m.load(),x=_a({launch:Fo,width:f.window_size.width,height:f.window_size.height,headless:!!t.headless});ht("testrun-slots",()=>x.killAll());let h={packDir:"",resolvedAuth:k,environment:g,envConfig:u,creds:l,configStore:m,profile:p,model:v,passThroughOpts:I,cwd:i},P=$=>({host:Ta(),lifecycle:Ea()}),N="",_=async($,be)=>{if($.mobile)return fr($,null,h,P);let Q;try{Q=await x.acquire(be)}catch(Y){let _e=Y.message;process.stderr.write(`member ${$.relPath}: chrome slot failed: ${_e}
125
- `);let $e=Ee($.relPath),Re=$.testId??$e;return oi(ri(h.packDir,$e),"warn","TESTRUN_SLOT_FAILURE",{execution_id:N,slot_index:be,member_test_id:Re,phase:"launch",error:_e},w),{testId:$.testId??"",overallStatus:"broken",exitCode:2,durationS:0,runKind:"replay"}}return fr($,Q,h,P)},C=!t.local&&!!k.basicAuth&&s.projectId!=null&&t.evidencePublish!==!1,{willConsolidate:M,interimShouldPublish:O}=xc({checks:s.checks,shouldPublish:C});if(C&&M&&w("info","PUBLISH_SKIPPED","Interim testrun evidence publish deferred to the consolidated pack",{surface:"testrun",reason:"consolidation"}),!C){let $=t.local?"local":k.basicAuth?s.projectId==null?"no_project":"flag":"no_auth";w("info","PUBLISH_SKIPPED","Testrun evidence publish skipped",{surface:"testrun",reason:$})}let W=k.basicAuth?async $=>{let be=k.basicAuth,Q=await pn({controller:new gt(u.controllerBaseUrl,{username:be.username,accessKey:be.access_key}),tms:new en(u.tmsBaseUrl,k.resolvedCreds?.username??be.username,k.resolvedCreds?.access_key??be.access_key),...$});if(Q.ok)return w("info","EVIDENCE_PUBLISH_OK","Testrun evidence published",{surface:"testrun",execution_id:$.executionId}),{ok:!0};let Y=/\b(\d{3})\b/.exec(Q.error)?.[1]??null;return w("error","EVIDENCE_PUBLISH_FAILED","Testrun evidence publish failed",{surface:"testrun",stage:Q.stage,http_status:Y?Number(Y):null,error:Q.error}),{ok:!1,stage:Q.stage}}:void 0,D=new AbortController;h.signal=D.signal;let X=pu(D),F={executeMember:_,publish:W,emit:d,log:w,shouldPublish:O,operator:{userName:k.resolvedCreds?.username??void 0,userEmail:k.resolvedCreds?.email??void 0},signal:D.signal,cwd:i,onExecutionId:$=>{N=$,h.packDir=Pe($,i)}},we=s.checks.filter($=>$.memberClass==="replay"),ve=s.checks.filter($=>$.memberClass==="author"),Ze=async($,be)=>{if($.mobile)return gr($,null,h,P);let Q;try{Q=await x.acquire(be)}catch(Y){return process.stderr.write(`author member ${$.relPath}: chrome slot failed: ${Y.message}
126
- `),{relPath:$.relPath,overallStatus:"broken",exitCode:2,durationS:0,published:"no"}}return gr($,Q,h,P)},et=Date.now(),fe=null,ye=[],tt=[],Wt=!1,ke=!1;try{if(we.length>0&&(fe=await xa({...s,checks:we},F),fe.exitCode===3&&(ke=!0)),ve.length>0&&!ke)try{let K=await Ca(ve,{executeAuthorMember:Ze,emit:d,parallel:s.parallel,signal:D.signal});ye=K.results,tt=K.skipped,ke=ke||K.cancelled}catch(K){process.stderr.write(`error: author pass failed: ${K.message}
127
- `),ye=[],tt=ve,Wt=!0}let $=fe?fe.exitCode===1:!1,be=Wt||ye.some(K=>K.overallStatus==="failed"||K.overallStatus==="broken"||K.overallStatus==="interrupted"),Q=ke?3:$||be?1:0;process.exitCode=Q;let Y=null;if(M&&!ke){try{Y=await Ic({interim:fe?{executionId:fe.executionId}:null,authored:ye,checks:s.checks,cwd:i,projectId:s.projectId,shouldPublish:C,publish:W,emit:d,log:w})}catch(K){o||process.stderr.write(`warning: evidence consolidation failed: ${K.message}
128
- `)}Y?.kind==="merged"&&Sc(ye,Y.executionId)}let _e=Y?.kind==="merged"?Y.executionId:fe?.executionId,$e=Y?Y.upload:fe?.upload??"skipped",Re=fe?.totals??{tests:0,passed:0,failed:0,broken:0,skipped:0},We=ye.filter(K=>K.overallStatus==="passed").length;d(yn({execution:Y?.kind==="merged"?{id:Y.executionId,status:Pr(Q),evidence_id:Y.executionId}:fe?{id:fe.executionId,status:Pr(fe.exitCode),evidence_id:fe.executionId}:null,authored:ye.map(K=>({path:K.relPath,test_id:K.testId,commit_id:K.commitId,execution_id:K.executionId,...K.sourceExecutionId?{source_execution_id:K.sourceExecutionId}:{},status:K.overallStatus,published:K.published})),totals:{tests:(Re.tests??0)+ye.length+tt.length,passed:(Re.passed??0)+We,failed:(Re.failed??0)+ye.filter(K=>K.overallStatus==="failed").length,broken:(Re.broken??0)+ye.filter(K=>K.overallStatus==="broken"||K.overallStatus==="interrupted").length,skipped:(Re.skipped??0)+tt.length,authored:ye.length},durationS:(Date.now()-et)/1e3,upload:$e,cancelled:ke})),d(Ct(_e??"",Q===0?"passed":Q===3?"cancelled":"failed")),R&&await R.waitUntilExit(),await uu({executionResult:Y?.kind==="merged"?{executionId:Y.executionId,exitCode:Q}:fe,authored:ye,cwd:i,environment:g,isAgent:o,cancelled:ke})}catch($){R?.unmount(),process.stderr.write(`error: testrun failed: ${$.message}
129
- `),process.exitCode=1}finally{X(),x.killAll(),fo("testrun-slots"),await S.shutdown()}}async function uu(e,t=mu){try{await t(e)}catch(r){e.isAgent||process.stderr.write(`warning: evidence presentation failed: ${r.message}
130
- `)}}async function mu(e){let{collectEvidenceRows:t,serveCommands:r}=await import("./evidence-presentation-XF23B7F2.js"),i=t({executionId:e.executionResult?.executionId,executionStatus:e.executionResult?Pr(e.executionResult.exitCode):void 0,authored:e.authored,cwd:e.cwd});if(i.length===0)return;if(!(!e.isAgent&&!e.cancelled&&!!process.stdin.isTTY&&!!process.stderr.isTTY)){process.stderr.write(`
122
+ `):D instanceof Ot&&D.code==="refresh_failed"?process.stderr.write(`error: Token refresh failed. Run 'kane-cli login' to re-authenticate.
123
+ `):process.stderr.write(`error: auth resolution failed: ${D.message}
124
+ `),process.exitCode=2;return}let T=null;a&&(T=rt($r.default.createElement(ot,null,$r.default.createElement(oa,{members:i.checks.map(D=>({relPath:D.relPath,memberClass:D.memberClass,tags:D.tags})),title:i.title,env:g,dispatchRef:c})),{stdout:process.stderr,exitOnCtrlC:!1}));let S=t.log?{log:t.log,shutdown:async()=>{}}:vu({environment:g,resolvedAuth:x,isAgent:o}),w=S.log,C={adaptiveHeal:t.adaptiveHeal,author:t.author,testmdSync:t.testmdSync,headless:t.headless,env:t.env,local:t.local,username:t.username,accessKey:t.accessKey,bugDetection:t.bugDetection,deviceName:t.deviceName,osVersion:t.osVersion,datasetId:t.datasetId,datasetRow:t.datasetRow},f=m.load(),k=Pa({launch:Uo,width:f.window_size.width,height:f.window_size.height,headless:!!t.headless});ht("testrun-slots",()=>k.killAll());let h={packDir:"",resolvedAuth:x,environment:g,envConfig:u,creds:l,configStore:m,profile:p,model:v,passThroughOpts:C,cwd:s},R=D=>({host:$a(),lifecycle:Aa()}),O="",_=async(D,we)=>{if(D.mobile)return br(D,null,h,R);let Z;try{Z=await k.acquire(we)}catch(W){let xe=W.message;process.stderr.write(`member ${D.relPath}: chrome slot failed: ${xe}
125
+ `);let Pe=Re(D.relPath),ye=D.testId??Pe;return as(is(h.packDir,Pe),"warn","TESTRUN_SLOT_FAILURE",{execution_id:O,slot_index:we,member_test_id:ye,phase:"launch",error:xe},w),{testId:D.testId??"",overallStatus:"broken",exitCode:2,durationS:0,runKind:"replay"}}return br(D,Z,h,R)},V=!t.local&&!!x.basicAuth&&i.projectId!=null&&t.evidencePublish!==!1,{willConsolidate:I,interimShouldPublish:L}=_c({checks:i.checks,shouldPublish:V});if(V&&I&&w("info","PUBLISH_SKIPPED","Interim testrun evidence publish deferred to the consolidated pack",{surface:"testrun",reason:"consolidation"}),!V){let D=t.local?"local":x.basicAuth?i.projectId==null?"no_project":"flag":"no_auth";w("info","PUBLISH_SKIPPED","Testrun evidence publish skipped",{surface:"testrun",reason:D})}let $=x.basicAuth?async D=>{let we=x.basicAuth,Z=await hn({controller:new gt(u.controllerBaseUrl,{username:we.username,accessKey:we.access_key}),tms:new tn(u.tmsBaseUrl,x.resolvedCreds?.username??we.username,x.resolvedCreds?.access_key??we.access_key),...D});if(Z.ok)return w("info","EVIDENCE_PUBLISH_OK","Testrun evidence published",{surface:"testrun",execution_id:D.executionId}),{ok:!0};let W=/\b(\d{3})\b/.exec(Z.error)?.[1]??null;return w("error","EVIDENCE_PUBLISH_FAILED","Testrun evidence publish failed",{surface:"testrun",stage:Z.stage,http_status:W?Number(W):null,error:Z.error}),{ok:!1,stage:Z.stage}}:void 0,Q=new AbortController;h.signal=Q.signal;let M=hu(Q),j={executeMember:_,publish:$,emit:d,log:w,shouldPublish:L,operator:{userName:x.resolvedCreds?.username??void 0,userEmail:x.resolvedCreds?.email??void 0},signal:Q.signal,cwd:s,onExecutionId:D=>{O=D,h.packDir=De(D,s)}},H=i.checks.filter(D=>D.memberClass==="replay"),Te=i.checks.filter(D=>D.memberClass==="author"),Ee=async(D,we)=>{if(D.mobile)return wr(D,null,h,R);let Z;try{Z=await k.acquire(we)}catch(W){return process.stderr.write(`author member ${D.relPath}: chrome slot failed: ${W.message}
126
+ `),{relPath:D.relPath,overallStatus:"broken",exitCode:2,durationS:0,published:"no"}}return wr(D,Z,h,R)},ze=Date.now(),se=null,fe=[],tt=[],Wt=!1,ke=!1;try{if(H.length>0&&(se=await _a({...i,checks:H},j),se.exitCode===3&&(ke=!0)),Te.length>0&&!ke)try{let K=await Ta(Te,{executeAuthorMember:Ee,emit:d,parallel:i.parallel,signal:Q.signal});fe=K.results,tt=K.skipped,ke=ke||K.cancelled}catch(K){process.stderr.write(`error: author pass failed: ${K.message}
127
+ `),fe=[],tt=Te,Wt=!0}let D=se?se.exitCode===1:!1,we=Wt||fe.some(K=>K.overallStatus==="failed"||K.overallStatus==="broken"||K.overallStatus==="interrupted"),Z=ke?3:D||we?1:0;process.exitCode=Z;let W=null;if(I&&!ke){try{W=await Rc({interim:se?{executionId:se.executionId}:null,authored:fe,checks:i.checks,cwd:s,projectId:i.projectId,shouldPublish:V,publish:$,emit:d,log:w})}catch(K){o||process.stderr.write(`warning: evidence consolidation failed: ${K.message}
128
+ `)}W?.kind==="merged"&&Ec(fe,W.executionId)}let xe=W?.kind==="merged"?W.executionId:se?.executionId,Pe=W?W.upload:se?.upload??"skipped",ye=se?.totals??{tests:0,passed:0,failed:0,broken:0,skipped:0},Ye=fe.filter(K=>K.overallStatus==="passed").length;if(d(Sn({execution:W?.kind==="merged"?{id:W.executionId,status:Mr(Z),evidence_id:W.executionId}:se?{id:se.executionId,status:Mr(se.exitCode),evidence_id:se.executionId}:null,authored:fe.map(K=>({path:K.relPath,test_id:K.testId,commit_id:K.commitId,execution_id:K.executionId,...K.sourceExecutionId?{source_execution_id:K.sourceExecutionId}:{},status:K.overallStatus,published:K.published})),totals:{tests:(ye.tests??0)+fe.length+tt.length,passed:(ye.passed??0)+Ye,failed:(ye.failed??0)+fe.filter(K=>K.overallStatus==="failed").length,broken:(ye.broken??0)+fe.filter(K=>K.overallStatus==="broken"||K.overallStatus==="interrupted").length,skipped:(ye.skipped??0)+tt.length,authored:fe.length},durationS:(Date.now()-ze)/1e3,upload:Pe,cancelled:ke})),d(It(xe??"",Z===0?"passed":Z===3?"cancelled":"failed")),!t.local){let K=(ye.passed??0)+(ye.failed??0)+(ye.broken??0)+fe.length,ue=new Date().toISOString();await on({env:g,userId:Number(x.resolvedCreds?.user_id??0),runsCompleted:K,data:{referenceId:xe||O||fe[0]?.executionId||"",startedAt:new Date(ze).toISOString(),completedAt:ue,creditsConsumed:(se?.totals.creditsConsumed??0)+fe.reduce((Yt,Fn)=>Yt+(Fn.creditsConsumed??0),0),runType:"testrun",target:rn(i.checks)},log:w})}T&&await T.waitUntilExit(),await fu({executionResult:W?.kind==="merged"?{executionId:W.executionId,exitCode:Z}:se,authored:fe,cwd:s,environment:g,isAgent:o,cancelled:ke})}catch(D){T?.unmount(),process.stderr.write(`error: testrun failed: ${D.message}
129
+ `),process.exitCode=1}finally{M(),k.killAll(),vo("testrun-slots"),await S.shutdown()}}async function fu(e,t=gu){try{await t(e)}catch(r){e.isAgent||process.stderr.write(`warning: evidence presentation failed: ${r.message}
130
+ `)}}async function gu(e){let{collectEvidenceRows:t,serveCommands:r}=await import("./evidence-presentation-XF23B7F2.js"),s=t({executionId:e.executionResult?.executionId,executionStatus:e.executionResult?Mr(e.executionResult.exitCode):void 0,authored:e.authored,cwd:e.cwd});if(s.length===0)return;if(!(!e.isAgent&&!e.cancelled&&!!process.stdin.isTTY&&!!process.stderr.isTTY)){process.stderr.write(`
131
131
  Evidence \u2014 view locally:
132
- `);for(let c of r(i))process.stderr.write(` ${c}
133
- `);return}let{renderTestrunEvidenceTable:n}=await import("./TestrunEvidenceTable-6UE5EMON.js");await n({rows:i,env:e.environment})}function pu(e){let t=process.listeners("SIGINT");process.removeAllListeners("SIGINT");let r=()=>e.abort();return process.on("SIGINT",r),()=>{process.removeListener("SIGINT",r);for(let i of t)process.on("SIGINT",i)}}function fu(e){let t=null;try{let o=e.resolvedAuth.resolvedCreds;o&&(t=Li({sessionId:cu(),identity:{org_id:String(o.org_id??""),user_id:String(o.user_id??""),machine_id:Oo(),email:o.email??null,email_domain:o.email_domain??"unknown",user_type:o.user_type??"unknown",env:e.environment,plan:o.plan??"unknown"},invocationMode:e.isAgent?"agent":"cli",getToken:async()=>e.resolvedAuth.token??null}),t.start())}catch{t=null}return{log:(o,n,c,s)=>{try{t?.log(o,n,c,s)}catch{}},shutdown:async()=>{try{await t?.shutdown()}catch{}}}}function gu(e,t){return e?r=>process.stdout.write(JSON.stringify(r)+`
134
- `):t||(r=>hu(r))}function hu(e){switch(e.type){case"testrun_start":process.stdout.write(`
132
+ `);for(let c of r(s))process.stderr.write(` ${c}
133
+ `);return}let{renderTestrunEvidenceTable:n}=await import("./TestrunEvidenceTable-FYDS3ZVU.js");await n({rows:s,env:e.environment})}function hu(e){let t=process.listeners("SIGINT");process.removeAllListeners("SIGINT");let r=()=>e.abort();return process.on("SIGINT",r),()=>{process.removeListener("SIGINT",r);for(let s of t)process.on("SIGINT",s)}}function vu(e){let t=null;try{let o=e.resolvedAuth.resolvedCreds;o&&(t=Ks({sessionId:uu(),identity:{org_id:String(o.org_id??""),user_id:String(o.user_id??""),machine_id:Fo(),email:o.email??null,email_domain:o.email_domain??"unknown",user_type:o.user_type??"unknown",env:e.environment,plan:o.plan??"unknown"},invocationMode:e.isAgent?"agent":"cli",getToken:async()=>e.resolvedAuth.token??null}),t.start())}catch{t=null}return{log:(o,n,c,i)=>{try{t?.log(o,n,c,i)}catch{}},shutdown:async()=>{try{await t?.shutdown()}catch{}}}}function bu(e,t){return e?r=>process.stdout.write(JSON.stringify(r)+`
134
+ `):t||(r=>wu(r))}function wu(e){switch(e.type){case"testrun_start":process.stdout.write(`
135
135
  running ${e.members.length} test(s) (parallel=${e.parallel})
136
136
  `);break;case"testrun_member_start":process.stdout.write(` -> ${e.path}
137
137
  `);break;case"testrun_member_end":process.stdout.write(` ${e.status==="passed"?"PASS":"FAIL"} ${e.path} (${e.status}, ${e.duration_s}s)
@@ -143,50 +143,50 @@ execution ${r.id}: ${r.status} (${t.passed} passed, ${t.failed} failed, ${t.bro
143
143
  `),(t.authored??0)>0&&process.stdout.write(`authored: ${t.authored} test(s)
144
144
  `),process.stdout.write(`(${e.duration_s}s, upload: ${e.upload})
145
145
  `);break}case"testrun_done":process.stdout.write(`testrun ${e.execution_id}: ${e.overall_status}
146
- `);break;default:break}}function vu(e,t,r,i){if(!t)return;let o=ba(e,i);o&&r(o)}function _c(e,t={}){process.stdout.write(`
146
+ `);break;default:break}}function yu(e,t,r,s){if(!t)return;let o=xa(e,s);o&&r(o)}function Pc(e,t={}){process.stdout.write(`
147
147
  testrun: ${e.title}
148
148
  `),process.stdout.write(` parallel=${e.parallel} on-failure=${e.onFailure}
149
149
 
150
- `);for(let i of e.checks){let o=i.failure?"x":"+",n=i.tags.length>0?` [${i.tags.join(", ")}]`:"",c=i.mobile?" (mobile)":"";process.stdout.write(` ${o} ${i.relPath}${c}${n}
150
+ `);for(let s of e.checks){let o=s.failure?"x":"+",n=s.tags.length>0?` [${s.tags.join(", ")}]`:"",c=s.mobile?" (mobile)":"";process.stdout.write(` ${o} ${s.relPath}${c}${n}
151
151
  `)}process.stdout.write(`
152
152
  ${e.checks.length} test(s) selected \u2014 plan ${e.valid?"valid":"INVALID"}
153
153
  `);let r=e.unresolved??[];t.receipt!==!1&&r.length>0&&process.stdout.write(`
154
- `+Nt(r,{cwd:process.cwd()}))}function Rr(e){let t=e.checks.filter(r=>r.failure);if(t.length===0){process.stderr.write(`error: no *_test.md files selected.
154
+ `+Nt(r,{cwd:process.cwd()}))}function Dr(e){let t=e.checks.filter(r=>r.failure);if(t.length===0){process.stderr.write(`error: no *_test.md files selected.
155
155
  `);return}process.stderr.write(`
156
156
  error: plan invalid \u2014 ${t.length} offending test(s):
157
157
  `);for(let r of t)process.stderr.write(` ${r.relPath}: ${r.failure}
158
158
  `);t.some(r=>r.failure==="mobile_host_unsupported")&&process.stderr.write(`
159
159
  mobile members need a machine that can drive a device (macOS on Apple Silicon) \u2014 deselect them (--match/--tags) to run the web members here.
160
- `)}import{existsSync as bu,readdirSync as wu}from"fs";function Rc(e=q){let t=ts(e);if(!bu(t))return[];let r=[];for(let i of wu(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name)){let o=Et(i,e);o.ok&&r.push({name:i,version:o.plugin.version,backendId:o.plugin.manifest.backendId})}return r.sort((i,o)=>i.name.localeCompare(o.name))}import{existsSync as yu,rmSync as ku}from"fs";function Tc(e,t=q){let r=ns(e,t);return yu(r)?(ku(r,{recursive:!0,force:!0}),{removed:!0}):{removed:!1}}import{existsSync as xu}from"fs";import{execFileSync as Su}from"child_process";function Iu(){try{return!!new le().getActiveProfile()}catch{return!1}}function Cu(e){try{return Su("hyperexecute",["--version"],{stdio:"ignore",timeout:2e3}),"hyperexecute"}catch{}let t=hn(e);return xu(t)?t:null}function Pc(e,t={}){let r=t.base??q,i=t.isLoggedIn??Iu,o=t.findBinary??(()=>Cu(r)),n=[],c=Et(e,r);if(!c.ok)return n.push({id:"installed",ok:!1,level:"error",message:c.reason==="not_installed"?`plugin '${e}' is not installed \u2014 run \`kane-cli plugin install ${e}\``:`plugin '${e}' is ${c.reason}${c.detail?`: ${c.detail}`:""}`}),n;n.push({id:"installed",ok:!0,level:"ok",message:`plugin '${e}' v${c.plugin.version} installed`});let s=o();n.push({id:"binary-present",ok:!!s,level:s?"ok":"error",message:s?`hyperexecute binary found (${s})`:`hyperexecute binary not found \u2014 run \`kane-cli plugin install ${e}\` to download it`});let a=i();return n.push({id:"logged-in",ok:a,level:a?"ok":"warn",message:a?"authenticated":"not logged in \u2014 run `kane-cli login`"}),n}function Ac(e,t){let r=o=>o.level==="ok"?"\u2713":o.level==="warn"?"\u26A0":"\u2717",i=[`plugin doctor \u2014 ${e}`];for(let o of t)i.push(` ${r(o)} ${o.message}`);return i.join(`
161
- `)}function Dc(){let e=new ct("plugin").description("Manage kane-cli plugins (install, list, remove, doctor)"),t=i=>i.base??q,r=()=>!process.stdin.isTTY;return e.command("install").argument("<name>","plugin name (e.g. remote-execution)").option("--version <v>","specific version (defaults to the bundled version)").addOption(new B("--base <dir>","override base dir (test seam)").hideHelp()).action(async(i,o)=>{let n=vs(i,{version:o.version,base:t(o)});if(n.status==="failed"){process.stderr.write(`error: ${n.error}
162
- `),process.exitCode=/unknown plugin/i.test(n.error??"")?2:1;return}let c=i==="remote-execution"?await bs(t(o)):void 0;r()?process.stdout.write(JSON.stringify({type:"plugin_install_result",status:n.status,name:n.name,version:n.version,dir:n.dir,binary:c})+`
160
+ `)}import{existsSync as ku,readdirSync as xu}from"fs";function Dc(e=z){let t=si(e);if(!ku(t))return[];let r=[];for(let s of xu(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name)){let o=Et(s,e);o.ok&&r.push({name:s,version:o.plugin.version,backendId:o.plugin.manifest.backendId})}return r.sort((s,o)=>s.name.localeCompare(o.name))}import{existsSync as Su,rmSync as Cu}from"fs";function $c(e,t=z){let r=ii(e,t);return Su(r)?(Cu(r,{recursive:!0,force:!0}),{removed:!0}):{removed:!1}}import{existsSync as Iu}from"fs";import{execFileSync as _u}from"child_process";function Eu(){try{return!!new me().getActiveProfile()}catch{return!1}}function Ru(e){try{return _u("hyperexecute",["--version"],{stdio:"ignore",timeout:2e3}),"hyperexecute"}catch{}let t=wn(e);return Iu(t)?t:null}function Mc(e,t={}){let r=t.base??z,s=t.isLoggedIn??Eu,o=t.findBinary??(()=>Ru(r)),n=[],c=Et(e,r);if(!c.ok)return n.push({id:"installed",ok:!1,level:"error",message:c.reason==="not_installed"?`plugin '${e}' is not installed \u2014 run \`kane-cli plugin install ${e}\``:`plugin '${e}' is ${c.reason}${c.detail?`: ${c.detail}`:""}`}),n;n.push({id:"installed",ok:!0,level:"ok",message:`plugin '${e}' v${c.plugin.version} installed`});let i=o();n.push({id:"binary-present",ok:!!i,level:i?"ok":"error",message:i?`hyperexecute binary found (${i})`:`hyperexecute binary not found \u2014 run \`kane-cli plugin install ${e}\` to download it`});let a=s();return n.push({id:"logged-in",ok:a,level:a?"ok":"warn",message:a?"authenticated":"not logged in \u2014 run `kane-cli login`"}),n}function Oc(e,t){let r=o=>o.level==="ok"?"\u2713":o.level==="warn"?"\u26A0":"\u2717",s=[`plugin doctor \u2014 ${e}`];for(let o of t)s.push(` ${r(o)} ${o.message}`);return s.join(`
161
+ `)}function Nc(){let e=new ct("plugin").description("Manage kane-cli plugins (install, list, remove, doctor)"),t=s=>s.base??z,r=()=>!process.stdin.isTTY;return e.command("install").argument("<name>","plugin name (e.g. remote-execution)").option("--version <v>","specific version (defaults to the bundled version)").addOption(new J("--base <dir>","override base dir (test seam)").hideHelp()).action(async(s,o)=>{let n=ki(s,{version:o.version,base:t(o)});if(n.status==="failed"){process.stderr.write(`error: ${n.error}
162
+ `),process.exitCode=/unknown plugin/i.test(n.error??"")?2:1;return}let c=s==="remote-execution"?await xi(t(o)):void 0;r()?process.stdout.write(JSON.stringify({type:"plugin_install_result",status:n.status,name:n.name,version:n.version,dir:n.dir,binary:c})+`
163
163
  `):(process.stderr.write(`${n.status==="already-installed"?"already installed":"installed"} ${n.name}@${n.version} \u2192 ${n.dir}
164
164
  `),c&&(c.status==="failed"?process.stderr.write(`\u26A0 hyperexecute binary download failed (${c.error}) \u2014 re-run \`kane-cli plugin install ${n.name}\`
165
165
  `):process.stderr.write(`\u2713 hyperexecute binary ${c.status} \u2192 ${c.path}
166
166
  `)),process.stderr.write(`run \`kane-cli plugin doctor ${n.name}\` to check readiness for --remote
167
- `)),process.exitCode=0}),e.command("list").addOption(new B("--base <dir>","override base dir (test seam)").hideHelp()).action(i=>{let o=Rc(t(i));if(r())process.stdout.write(JSON.stringify({type:"plugin_list",plugins:o})+`
167
+ `)),process.exitCode=0}),e.command("list").addOption(new J("--base <dir>","override base dir (test seam)").hideHelp()).action(s=>{let o=Dc(t(s));if(r())process.stdout.write(JSON.stringify({type:"plugin_list",plugins:o})+`
168
168
  `);else if(o.length===0)process.stderr.write(`no plugins installed
169
169
  `);else for(let n of o)process.stdout.write(`${n.name}@${n.version} (${n.backendId})
170
- `);process.exitCode=0}),e.command("remove").argument("<name>","plugin name").addOption(new B("--base <dir>","override base dir (test seam)").hideHelp()).action((i,o)=>{let n=Tc(i,t(o));r()?process.stdout.write(JSON.stringify({type:"plugin_remove_result",name:i,removed:n.removed})+`
171
- `):process.stderr.write(n.removed?`removed ${i}
172
- `:`not installed: ${i}
173
- `),process.exitCode=0}),e.command("doctor").argument("[name]","plugin name","remote-execution").addOption(new B("--base <dir>","override base dir (test seam)").hideHelp()).action((i,o)=>{let n=Pc(i,{base:t(o)});r()?process.stdout.write(JSON.stringify({type:"plugin_doctor",name:i,checks:n})+`
174
- `):process.stdout.write(Ac(i,n)+`
175
- `),process.exitCode=n.some(c=>c.id==="installed"&&!c.ok)?2:0}),e}var Ar="pass --target emulator|simulator";function Dr(e){return e===void 0||e===""?{error:Ar}:e==="emulator"||e==="simulator"?{ok:e}:e==="desktop"?{error:`desktop has no devices or uploads to list \u2014 ${Ar}`}:{error:`unknown target "${e}" \u2014 ${Ar}`}}function $c(e){return e.kind==="simulator"||e.id.startsWith("emulator-")?e.id:void 0}function _u(e){let t=e.osVersion;return{name:oo(e),state:e.state,...$c(e)?{id:$c(e)}:{},platform:e.platform,kind:e.kind,...t?{os_version:t}:{}}}function Eu(e,t=r=>process.stdout.write(`${r}
176
- `)){if(e.length===0){t("(no devices found)");return}let r=s=>s.os_version??"-",i=s=>s.id??"-",o=Math.max(6,...e.map(s=>s.name.length)),n=Math.max(10,...e.map(s=>r(s).length)),c=Math.max(5,...e.map(s=>s.state.length));t(`${"DEVICE".padEnd(o)} ${"OS VERSION".padEnd(n)} ${"STATE".padEnd(c)} ID`);for(let s of e)t(`${s.name.padEnd(o)} ${r(s).padEnd(n)} ${s.state.padEnd(c)} ${i(s)}`)}function Ru(){return{host:Xt,depsInstalled:async e=>(await zt().status(e)).installed,discover:e=>so(e),isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:e=>process.stdout.write(`${e}
170
+ `);process.exitCode=0}),e.command("remove").argument("<name>","plugin name").addOption(new J("--base <dir>","override base dir (test seam)").hideHelp()).action((s,o)=>{let n=$c(s,t(o));r()?process.stdout.write(JSON.stringify({type:"plugin_remove_result",name:s,removed:n.removed})+`
171
+ `):process.stderr.write(n.removed?`removed ${s}
172
+ `:`not installed: ${s}
173
+ `),process.exitCode=0}),e.command("doctor").argument("[name]","plugin name","remote-execution").addOption(new J("--base <dir>","override base dir (test seam)").hideHelp()).action((s,o)=>{let n=Mc(s,{base:t(o)});r()?process.stdout.write(JSON.stringify({type:"plugin_doctor",name:s,checks:n})+`
174
+ `):process.stdout.write(Oc(s,n)+`
175
+ `),process.exitCode=n.some(c=>c.id==="installed"&&!c.ok)?2:0}),e}var Or="pass --target emulator|simulator";function Nr(e){return e===void 0||e===""?{error:Or}:e==="emulator"||e==="simulator"?{ok:e}:e==="desktop"?{error:`desktop has no devices or uploads to list \u2014 ${Or}`}:{error:`unknown target "${e}" \u2014 ${Or}`}}function jc(e){return e.kind==="simulator"||e.id.startsWith("emulator-")?e.id:void 0}function Tu(e){let t=e.osVersion;return{name:ao(e),state:e.state,...jc(e)?{id:jc(e)}:{},platform:e.platform,kind:e.kind,...t?{os_version:t}:{}}}function Pu(e,t=r=>process.stdout.write(`${r}
176
+ `)){if(e.length===0){t("(no devices found)");return}let r=i=>i.os_version??"-",s=i=>i.id??"-",o=Math.max(6,...e.map(i=>i.name.length)),n=Math.max(10,...e.map(i=>r(i).length)),c=Math.max(5,...e.map(i=>i.state.length));t(`${"DEVICE".padEnd(o)} ${"OS VERSION".padEnd(n)} ${"STATE".padEnd(c)} ID`);for(let i of e)t(`${i.name.padEnd(o)} ${r(i).padEnd(n)} ${i.state.padEnd(c)} ${s(i)}`)}function Au(){return{host:Qt,depsInstalled:async e=>(await Xt().status(e)).installed,discover:e=>lo(e),isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:e=>process.stdout.write(`${e}
177
177
  `),err:e=>process.stderr.write(`${e}
178
- `),exit:(e,t)=>y(e,t)}}async function Tu(e,t=Ru()){let r=Dr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`devices list: ${r.error}`);return}let i=t.host();if(!i.supported){t.err(`error: ${i.reason}`),t.exit(2,"devices list: unsupported host");return}if(r.ok==="emulator"&&!io()&&!await t.depsInstalled("emulator")){t.err(`error: the managed Android dependencies are not installed, so emulators cannot be discovered.
179
- Install them: kane-cli doctor --target emulator --install`),t.exit(2,"devices list: emulator deps missing");return}let o=Gt(r.ok),n=(await t.discover(o)).filter(c=>c.kind===r.ok).map(_u);if(e.agent||t.isAgent()){for(let c of n)t.out(JSON.stringify(c));t.out(JSON.stringify({total:n.length}))}else Eu(n,t.out);t.exit(0,"devices list complete")}function Pu(e){return{name:e.name,brand:e.brand,...e.configName?{config_name:e.configName}:{},os_versions:e.osVersions,...e.avdIds?{avd_ids:e.avdIds}:{}}}function Au(e,t=r=>process.stdout.write(`${r}
180
- `)){if(e.length===0){t("(no devices found)");return}let r=n=>n.os_versions.join(", "),i=Math.max(5,...e.map(n=>n.brand.length)),o=Math.max(6,...e.map(n=>n.name.length));t(`${"BRAND".padEnd(i)} ${"DEVICE".padEnd(o)} OS VERSIONS`);for(let n of e)t(`${n.brand.padEnd(i)} ${n.name.padEnd(o)} ${r(n)}`)}function Du(){return{resolveCatalogFn:Bt,resolveAuth:sr,isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:e=>process.stdout.write(`${e}
178
+ `),exit:(e,t)=>y(e,t)}}async function Du(e,t=Au()){let r=Nr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`devices list: ${r.error}`);return}let s=t.host();if(!s.supported){t.err(`error: ${s.reason}`),t.exit(2,"devices list: unsupported host");return}if(r.ok==="emulator"&&!co()&&!await t.depsInstalled("emulator")){t.err(`error: the managed Android dependencies are not installed, so emulators cannot be discovered.
179
+ Install them: kane-cli doctor --target emulator --install`),t.exit(2,"devices list: emulator deps missing");return}let o=qt(r.ok),n=(await t.discover(o)).filter(c=>c.kind===r.ok).map(Tu);if(e.agent||t.isAgent()){for(let c of n)t.out(JSON.stringify(c));t.out(JSON.stringify({total:n.length}))}else Pu(n,t.out);t.exit(0,"devices list complete")}function $u(e){return{name:e.name,brand:e.brand,...e.configName?{config_name:e.configName}:{},os_versions:e.osVersions,...e.avdIds?{avd_ids:e.avdIds}:{}}}function Mu(e,t=r=>process.stdout.write(`${r}
180
+ `)){if(e.length===0){t("(no devices found)");return}let r=n=>n.os_versions.join(", "),s=Math.max(5,...e.map(n=>n.brand.length)),o=Math.max(6,...e.map(n=>n.name.length));t(`${"BRAND".padEnd(s)} ${"DEVICE".padEnd(o)} OS VERSIONS`);for(let n of e)t(`${n.brand.padEnd(s)} ${n.name.padEnd(o)} ${r(n)}`)}function Ou(){return{resolveCatalogFn:Bt,resolveAuth:dr,isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:e=>process.stdout.write(`${e}
181
181
  `),err:e=>process.stderr.write(`${e}
182
- `),exit:(e,t)=>y(e,t)}}async function $u(e,t=Du()){let r=Dr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`devices list --remote: ${r.error}`);return}let i=r.ok==="simulator"?"ios":"android",o=i==="ios"?"iOS":"Android",n=new le,c=e.profile??n.getActiveProfile()??"default",s=e.env??n.getDefaultEnv()??"prod",a=await t.resolveAuth(c,s,{...e.username?{username:e.username}:{},...e.accessKey?{accessKey:e.accessKey}:{}});if(!a.ok){let{message:p,exitCode:g}=ar(c,s,a);t.err(p.trimEnd()),t.exit(g,"devices list --remote: auth");return}let d=await t.resolveCatalogFn(s,{username:a.creds.username,accessKey:a.creds.access_key},{platform:i});if(!d.ok){t.err(`error: ${d.reason}`),t.exit(1,"devices list --remote: catalog unavailable");return}d.warning&&t.err(`warning: ${d.warning}`);let l=d.catalog.devices;if(e.osVersion){let p=e.osVersion.trim();if(l=l.filter(g=>g.osVersions.includes(p)),l.length===0){t.err(`error: no ${r.ok} device runs ${o} ${p}.
183
- The grid supports: ${d.catalog.supportedOsVersions.join(", ")}`),t.exit(2,"devices list --remote: no devices on that version");return}}let m=l.map(Pu);if(e.agent||t.isAgent()){for(let p of m)t.out(JSON.stringify(p));t.out(JSON.stringify({total:m.length,platform:d.catalog.platform,supported_os_versions:d.catalog.supportedOsVersions,generated_at:d.catalog.generatedAt,device_config_versions:d.catalog.source.deviceConfigVersions,...d.catalog.runson?{runson:d.catalog.runson}:{},origin:d.origin}))}else Au(m,t.out);t.exit(0,"devices list --remote complete")}function Mu(e){return{app_id:e.appId,name:e.name,...e.packageName?{package:e.packageName}:{},...e.updatedAt?{updated_at:e.updatedAt}:{}}}function Ou(e,t,r=i=>process.stdout.write(`${i}
184
- `)){if(e.length===0){r("(no uploads found)");return}let i=Math.max(4,...e.map(n=>n.name.length)),o=Math.max(6,...e.map(n=>n.app_id.length));r(`${"NAME".padEnd(i)} ${"APP ID".padEnd(o)} UPDATED`);for(let n of e){let c=n.updated_at?n.updated_at.slice(0,10):"";r(`${n.name.padEnd(i)} ${n.app_id.padEnd(o)} ${c}`)}t>e.length&&r(""),t>e.length&&r(`${e.length} of ${t}`)}var Nu=50;function ju(e){return{resolveAuth:async()=>{let t=new le,r=e.profile??t.getActiveProfile()??"default",i=e.env??t.getDefaultEnv(),o=await sr(r,i,e);if(!o.ok){let{message:n,exitCode:c}=ar(r,i,o);return process.stderr.write(n),y(c,`${o.reason} for "${r}" [${i}]`),{ok:!1}}return{ok:!0,username:o.creds.username,accessKey:o.creds.access_key,env:i}},list:async({baseUrl:t,auth:r,type:i})=>new bo(t,r).list({type:i,limit:Nu}),isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:t=>process.stdout.write(`${t}
182
+ `),exit:(e,t)=>y(e,t)}}async function Nu(e,t=Ou()){let r=Nr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`devices list --remote: ${r.error}`);return}let s=r.ok==="simulator"?"ios":"android",o=s==="ios"?"iOS":"Android",n=new me,c=e.profile??n.getActiveProfile()??"default",i=e.env??n.getDefaultEnv()??"prod",a=await t.resolveAuth(c,i,{...e.username?{username:e.username}:{},...e.accessKey?{accessKey:e.accessKey}:{}});if(!a.ok){let{message:p,exitCode:g}=ur(c,i,a);t.err(p.trimEnd()),t.exit(g,"devices list --remote: auth");return}let d=await t.resolveCatalogFn(i,{username:a.creds.username,accessKey:a.creds.access_key},{platform:s});if(!d.ok){t.err(`error: ${d.reason}`),t.exit(1,"devices list --remote: catalog unavailable");return}d.warning&&t.err(`warning: ${d.warning}`);let l=d.catalog.devices;if(e.osVersion){let p=e.osVersion.trim();if(l=l.filter(g=>g.osVersions.includes(p)),l.length===0){t.err(`error: no ${r.ok} device runs ${o} ${p}.
183
+ The grid supports: ${d.catalog.supportedOsVersions.join(", ")}`),t.exit(2,"devices list --remote: no devices on that version");return}}let m=l.map($u);if(e.agent||t.isAgent()){for(let p of m)t.out(JSON.stringify(p));t.out(JSON.stringify({total:m.length,platform:d.catalog.platform,supported_os_versions:d.catalog.supportedOsVersions,generated_at:d.catalog.generatedAt,device_config_versions:d.catalog.source.deviceConfigVersions,...d.catalog.runson?{runson:d.catalog.runson}:{},origin:d.origin}))}else Mu(m,t.out);t.exit(0,"devices list --remote complete")}function ju(e){return{app_id:e.appId,name:e.name,...e.packageName?{package:e.packageName}:{},...e.updatedAt?{updated_at:e.updatedAt}:{}}}function Fu(e,t,r=s=>process.stdout.write(`${s}
184
+ `)){if(e.length===0){r("(no uploads found)");return}let s=Math.max(4,...e.map(n=>n.name.length)),o=Math.max(6,...e.map(n=>n.app_id.length));r(`${"NAME".padEnd(s)} ${"APP ID".padEnd(o)} UPDATED`);for(let n of e){let c=n.updated_at?n.updated_at.slice(0,10):"";r(`${n.name.padEnd(s)} ${n.app_id.padEnd(o)} ${c}`)}t>e.length&&r(""),t>e.length&&r(`${e.length} of ${t}`)}var Lu=50;function Vu(e){return{resolveAuth:async()=>{let t=new me,r=e.profile??t.getActiveProfile()??"default",s=e.env??t.getDefaultEnv(),o=await dr(r,s,e);if(!o.ok){let{message:n,exitCode:c}=ur(r,s,o);return process.stderr.write(n),y(c,`${o.reason} for "${r}" [${s}]`),{ok:!1}}return{ok:!0,username:o.creds.username,accessKey:o.creds.access_key,env:s}},list:async({baseUrl:t,auth:r,type:s})=>new ko(t,r).list({type:s,limit:Lu}),isAgent:()=>!process.stdin.isTTY||!process.stdout.isTTY,out:t=>process.stdout.write(`${t}
185
185
  `),err:t=>process.stderr.write(`${t}
186
- `),exit:(t,r)=>y(t,r)}}async function Fu(e,t=ju(e)){let r=Dr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`apps list: ${r.error}`);return}let i=await t.resolveAuth();if(i.ok)try{let o=await t.list({baseUrl:it(i.env),auth:{username:i.username,accessKey:i.accessKey},type:r.ok}),n=o.apps.map(Mu);if(e.agent||t.isAgent()){for(let c of n)t.out(JSON.stringify(c));t.out(JSON.stringify({total:o.total}))}else Ou(n,o.total,t.out);t.exit(0,"apps list complete")}catch(o){t.err(`error: ${o instanceof Error?o.message:String(o)}`),t.exit(1,"apps list failed")}}function Mc(e){e.command("devices").description("List the emulators or simulators on this machine (TTY = table; non-TTY / --agent = NDJSON). Address a device by DEVICE + OS VERSION: --device-name/--os-version, or `config set-device-name` + `config set-os-version`.").argument("<action>","'list'").option("--target <kind>","emulator | simulator (required)").option("--remote","List what the HyperExecute grid can provision instead of what is attached here. Needs auth, not a mobile host \u2014 DEVICE + OS VERSIONS are what `testrun run --remote` accepts.").option("--os-version <version>","With --remote: list only devices that run this OS version").option("--profile <name>","With --remote: profile name (default: active)").option("--env <name>","With --remote: environment (prod or stage)").option("--username <user>","With --remote: basic auth username (skip stored creds)").option("--access-key <key>","With --remote: basic auth access key").option("--agent","Force NDJSON output (auto-on when stdin is not a TTY)").action(async(t,r)=>{if(t!=="list"){process.stderr.write(`error: unknown action "${t}" (try: list)
187
- `),y(2,`devices: unknown action "${t}"`);return}if(r.remote){await $u(r);return}if(r.osVersion){process.stderr.write(`error: --os-version filters the --remote listing only; a local listing already shows every attached device.
188
- `),y(2,"devices list: --os-version without --remote");return}await Tu(r)}),e.command("apps").description("List this account's uploaded builds for a device class (TTY = table; non-TTY / --agent = NDJSON). The APP ID column is what --app and `config set-app` accept.").argument("<action>","'list'").option("--target <kind>","emulator | simulator (required)").option("--profile <name>","Profile name (default: active)").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip stored creds)").option("--access-key <key>","Basic auth access key").option("--agent","Force NDJSON output (auto-on when stdin is not a TTY)").action(async(t,r)=>{if(t!=="list"){process.stderr.write(`error: unknown action "${t}" (try: list)
189
- `),y(2,`apps: unknown action "${t}"`);return}await Fu(r)})}function Uu(e={}){let t=e.hostSupportsMobile??Qt(),r=new ct;r.name("kane-cli").description("Kane-CLI \u2014 the validation layer for AI coding agents. Natural-language web and mobile-app automation, plus requirements-to-coverage assurance, called from your CLI or IDE.").version(he).enablePositionalOptions().configureHelp({sortSubcommands:!0}).showHelpAfterError("(run `kane-cli --help` to see all commands; `-h` and `help` also work)").addHelpText("after",`
186
+ `),exit:(t,r)=>y(t,r)}}async function Uu(e,t=Vu(e)){let r=Nr(e.target);if("error"in r){t.err(`error: ${r.error}`),t.exit(2,`apps list: ${r.error}`);return}let s=await t.resolveAuth();if(s.ok)try{let o=await t.list({baseUrl:st(s.env),auth:{username:s.username,accessKey:s.accessKey},type:r.ok}),n=o.apps.map(ju);if(e.agent||t.isAgent()){for(let c of n)t.out(JSON.stringify(c));t.out(JSON.stringify({total:o.total}))}else Fu(n,o.total,t.out);t.exit(0,"apps list complete")}catch(o){t.err(`error: ${o instanceof Error?o.message:String(o)}`),t.exit(1,"apps list failed")}}function Fc(e){e.command("devices").description("List the emulators or simulators on this machine (TTY = table; non-TTY / --agent = NDJSON). Address a device by DEVICE + OS VERSION: --device-name/--os-version, or `config set-device-name` + `config set-os-version`.").argument("<action>","'list'").option("--target <kind>","emulator | simulator (required)").option("--remote","List what the HyperExecute grid can provision instead of what is attached here. Needs auth, not a mobile host \u2014 DEVICE + OS VERSIONS are what `testrun run --remote` accepts.").option("--os-version <version>","With --remote: list only devices that run this OS version").option("--profile <name>","With --remote: profile name (default: active)").option("--env <name>","With --remote: environment (prod or stage)").option("--username <user>","With --remote: basic auth username (skip stored creds)").option("--access-key <key>","With --remote: basic auth access key").option("--agent","Force NDJSON output (auto-on when stdin is not a TTY)").action(async(t,r)=>{if(t!=="list"){process.stderr.write(`error: unknown action "${t}" (try: list)
187
+ `),y(2,`devices: unknown action "${t}"`);return}if(r.remote){await Nu(r);return}if(r.osVersion){process.stderr.write(`error: --os-version filters the --remote listing only; a local listing already shows every attached device.
188
+ `),y(2,"devices list: --os-version without --remote");return}await Du(r)}),e.command("apps").description("List this account's uploaded builds for a device class (TTY = table; non-TTY / --agent = NDJSON). The APP ID column is what --app and `config set-app` accept.").argument("<action>","'list'").option("--target <kind>","emulator | simulator (required)").option("--profile <name>","Profile name (default: active)").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip stored creds)").option("--access-key <key>","Basic auth access key").option("--agent","Force NDJSON output (auto-on when stdin is not a TTY)").action(async(t,r)=>{if(t!=="list"){process.stderr.write(`error: unknown action "${t}" (try: list)
189
+ `),y(2,`apps: unknown action "${t}"`);return}await Uu(r)})}function Ju(e={}){let t=e.hostSupportsMobile??Zt(),r=new ct;r.name("kane-cli").description("Kane-CLI \u2014 the validation layer for AI coding agents. Natural-language web and mobile-app automation, plus requirements-to-coverage assurance, called from your CLI or IDE.").version(be).enablePositionalOptions().configureHelp({sortSubcommands:!0}).showHelpAfterError("(run `kane-cli --help` to see all commands; `-h` and `help` also work)").addHelpText("after",`
190
190
  Examples:
191
191
  $ kane-cli run "Search for a laptop"
192
192
  $ kane-cli testmd run smoke_test.md
@@ -200,11 +200,11 @@ Test files:
200
200
 
201
201
  Docs https://www.testmuai.com/support/docs/kane-cli-introduction
202
202
  Bugs https://github.com/LambdaTest/kane-cli/issues
203
- `),r.on("command:*",o=>{r.error(`error: unknown command '${o[0]}'`,{exitCode:2,code:"commander.unknownCommand"})}),r.command("login").description("Authenticate (interactive; --oauth opens the browser, or --username/--access-key for basic auth)").option("--oauth","Login via OAuth (opens browser)").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").addOption(new B("--env <name>","Environment (prod or stage)").default("prod").hideHelp()).option("--profile <name>","Profile name","default").option("--project-id <id>","Project ID (skip picker)").option("--folder-id <id>","Folder ID (skip picker)").addOption(new B("--model <name>","Model").default("v16-alpha").hideHelp()).option("--chrome-profile <path>","Chrome profile path").action(async o=>{let n=new le,c=new Te,s=o.env,a=o.profile;if(!process.stdin.isTTY||o.oauth||o.username){if(n.setDefaultEnv(s),o.oauth)await new $o(a,s,n).login(),console.log(`Logged in as ${a} [${s}] via OAuth`);else if(o.username&&o.accessKey){try{let{validateBasicAuth:S}=await import("./validate-basic-OKLJLDML.js");await S(s,o.username,o.accessKey)}catch{console.error("Credentials not valid. Please use valid credentials."),y(1,"Invalid basic-auth credentials");return}n.saveBasicAuth(a,s,{username:o.username,access_key:o.accessKey}),console.log(`Logged in as ${a} [${s}] via basic auth`)}else console.error("Provide --oauth, or --username and --access-key"),y(1,"Missing --oauth or credentials for login");n.setActiveProfile(a),c.set("model",o.model),o.chromeProfile&&c.set("chrome_profile_path",o.chromeProfile);let R=null;if(o.username&&o.accessKey)R={username:o.username,access_key:o.accessKey};else try{let w=await Ue({creds:n,env:s,log:()=>{}});w.resolvedCreds&&(R={username:w.resolvedCreds.username,access_key:w.resolvedCreds.access_key})}catch{}if(o.projectId&&(st(n,c,a,s,{projectId:o.projectId}),console.log(`Project set to ${o.projectId}`)),o.folderId&&(st(n,c,a,s,{folderId:o.folderId}),console.log(`Folder set to ${o.folderId}`)),R&&(!o.projectId||!o.folderId))try{let S=await To({creds:n,config:c,profile:a,env:s,tmsCreds:R,log:()=>{}});o.projectId||console.log(`Auto-selected project: ${S.projectName} (${S.projectId})`),o.folderId||console.log(`Auto-selected folder: ${S.folderName} (${S.folderId})`)}catch(S){console.warn(`Could not auto-select project/folder: ${S instanceof Error?S.message:S}`)}nn(n,c,a,s),console.log("Setup complete."),y(0,"Setup complete")}let{SingleShotApp:d}=await import("./SingleShotApp-IPNZBFXB.js"),{ScrollbackProvider:l}=await import("./scrollback-JLPJR25X.js"),{render:m}=await import("./build-JIKYOZUH.js"),p=await import("./react-QWOAB3TB.js"),g={current:null},u={current:!1},{waitUntilExit:v,unmount:k}=m(p.default.createElement(l,null,p.default.createElement(d,{resultRef:g,mode:"login",loginCompleteRef:u})),{exitOnCtrlC:!1});Dt(()=>k()),await v();try{process.stdin.setRawMode?.(!1)}catch{}process.stdout.write("\x1B[?25h"),u.current&&console.log("Login setup complete."),process.exit(0)}),r.command("logout").description("Revoke tokens and delete the stored profile credentials").action(async()=>{let o=new le,n=o.getActiveProfile();if(!n){console.log("No active profile to logout");return}let c=o.getDefaultEnv(),s=await Mo(o,n,c),a=new Te;s.switchedTo?(nn(o,a,s.switchedTo.profile,s.switchedTo.env),console.log(`Logged out ${s.profile} [${s.env}]. Switched to ${s.switchedTo.profile} [${s.switchedTo.env}]`)):(a.save({project_id:null,project_name:null,folder_id:null,folder_name:null}),console.log(`Logged out ${s.profile} [${s.env}]. No profiles remaining.`))}),r.command("whoami").description("Show the authenticated identity, active profile, and environment").option("--profile <name>","Profile name").action(async o=>{let n=new le,c=o.profile??n.getActiveProfile()??"default",s=n.getDefaultEnv(),a=n.loadCredentials(c,s),d=n.loadBasicAuth(c,s),l="none",m=d?.username,p,g,u,v;if(d?l="basic":a&&(l="oauth",g=new Date(a.expires_at*1e3).toISOString().slice(0,10)),l==="none")p="missing";else try{let I=await Ue({creds:n,env:s,log:()=>{}});if(I.resolvedCreds)u="verified",p="valid",m=I.resolvedCreds.username??m;else{let{classifyAuthFailure:f}=await import("./resolver-2NUNLK7N.js");f(I.resolver.lastError)==="auth"?(u="rejected",p="expired",v="Credentials rejected by the server \u2014 re-login or rotate your access key"):(u="unreachable",v=I.resolver.lastError?.message)}}catch(I){let f=I;f.code==="refresh_failed"?(u="rejected",p="expired",v="OAuth token refresh failed \u2014 run 'kane-cli login'"):f.code==="not_authenticated"?(l="none",p="missing"):(u="unreachable",v=f.message)}let{WhoamiView:k}=await import("./WhoamiView-TFCHIOW5.js"),{render:R}=await import("./build-JIKYOZUH.js"),S=await import("./react-QWOAB3TB.js"),{waitUntilExit:w}=R(S.default.createElement(k,{profile:c,env:s,authenticated:u==="verified",authMethod:l,username:m,tokenStatus:p,expiresAt:g,serverStatus:u,detail:v}));await w(),l==="none"?y(1,"whoami: not-authenticated"):u&&u!=="verified"&&y(u==="unreachable"?3:1,`whoami: ${u}`)}),r.command("config <action> [value]").description("Show or change settings ("+["show","set-target",...t?[...lr]:[],"set-mode","set-assertion-mode","set-network-ws","set-network-sse","set-bug-detection","set-final-validation","set-url","set-window","chrome-profile","project","folder","reset"].join(", ")+")").option("--agent","Force JSON output for `show` (auto-on when stdin is not a TTY)").action(async(o,n,c)=>{let s=new Te,a=new le,d=Us(o,{hostSupportsMobile:t,mobileMessage:Zt()});if(d){process.stderr.write(d.message),y(d.exitCode,`config ${o} unavailable off a mobile host`);return}if(o==="show"){let l=s.load(),m=a.getActiveProfile()??"default",p=a.getDefaultEnv(),g=a.loadProfileConfig(m,p)??{},u=g.project_id??l.project_id??null,v=g.project_name??l.project_name??null,k=g.folder_id??l.folder_id??null,R=g.folder_name??l.folder_name??null,S=a.loadBasicAuth(m,p),w=a.loadCredentials(m,p),I=S?`basic (${S.username})`:w?"oauth":"not configured",{resolveSessionTarget:f}=await import("./session-target-UWROGOCY.js"),{deviceRefName:x,deviceRefOsVersion:h}=await import("./device-ref-LAZWPRQN.js"),P=f(l.mobile?.tui_target,l.mobile?.default_target?.kind),N=P.kind==="unset"?"desktop":P.kind==="choose-mobile"?"mobile (legacy \u2014 run `kane-cli config set-target emulator|simulator`)":P.kind;if(!!c?.agent||!process.stdin.isTTY||!process.stdout.isTTY){let D=re(p);process.stdout.write(`${JSON.stringify({profile:m,env:p,auth:I,project_id:u,project_name:v,folder_id:k,folder_name:R,model:l.model,mode:l.mode,assertion_mode:l.assertion_mode,network_ws:l.network_ws,network_sse:l.network_sse,bug_detection:l.bug_detection,final_validation:l.final_validation,window_size:`${l.window_size.width}x${l.window_size.height}`,chrome_profile:l.chrome_profile_path,default_url:l.default_url??Jn,target:N,device_name:x(l.mobile?.default_target),os_version:h(l.mobile?.default_target),app:l.mobile?.default_app??null,auto_grant_permissions:l.mobile?.auto_grant_permissions??!0,auto_accept_alerts:l.mobile?.auto_accept_alerts??!0,controller_base_url:D.controllerBaseUrl,tms_base_url:D.tmsBaseUrl})}
204
- `),y(0,"config show complete");return}let{ConfigView:C}=await import("./ConfigView-FDBMJC26.js"),{render:M}=await import("./build-JIKYOZUH.js"),O=await import("./react-QWOAB3TB.js"),{waitUntilExit:W}=M(O.default.createElement(C,{model:l.model,authLabel:I,profile:m,env:p,defaultUrl:l.default_url??Jn,projectId:u,projectName:v,folderId:k,folderName:R,windowSize:`${l.window_size.width}x${l.window_size.height}`,chromeProfile:l.chrome_profile_path,target:N,deviceName:x(l.mobile?.default_target),osVersion:h(l.mobile?.default_target),appLabel:l.mobile?.default_app??null}));await W()}else if(o==="set-window"&&n){let l=n.split("x").map(Number),[m,p]=l;!m||!p||!Number.isInteger(m)||!Number.isInteger(p)?console.error("Invalid format. Use: kane-cli config set-window WIDTHxHEIGHT"):m<800||m>3840?console.error(`Width must be between 800 and 3840 (got ${m})`):p<600||p>2160?console.error(`Height must be between 600 and 2160 (got ${p})`):(s.set("window_size",{width:m,height:p}),console.log(`Window size set to ${m}x${p}`))}else if(o==="set-mode"){if(n!=="action"&&n!=="testing"){console.error("Mode must be 'action' or 'testing'."),y(1,"Invalid mode");return}s.set("mode",n),console.log(`Mode set to ${n}`)}else if(o==="set-assertion-mode"){if(n!=="visual"&&n!=="dom"){console.error("Assertion mode must be 'visual' or 'dom'."),y(1,"Invalid assertion-mode");return}s.set("assertion_mode",n),console.log(`Assertion mode set to ${n}`)}else if(o==="set-network-ws"){if(n!=="on"&&n!=="off"){console.error("WebSocket capture must be 'on' or 'off'."),y(1,"Invalid network-ws value");return}s.set("network_ws",n==="on"),console.log(`WebSocket capture set to ${n}`)}else if(o==="set-network-sse"){if(n!=="on"&&n!=="off"){console.error("SSE capture must be 'on' or 'off'."),y(1,"Invalid network-sse value");return}s.set("network_sse",n==="on"),console.log(`SSE capture set to ${n}`)}else if(o==="set-bug-detection"){if(n!=="off"&&n!=="stop"&&n!=="continue"){console.error("Bug detection must be 'off', 'stop' or 'continue'."),y(1,"Invalid bug-detection value");return}s.set("bug_detection",n),console.log(`Bug detection set to ${n}`)}else if(o==="set-final-validation"){if(n!=="on"&&n!=="off"){console.error("Final validation must be 'on' or 'off'."),y(1,"Invalid final-validation value");return}s.set("final_validation",n==="on"),console.log(`Final validation set to ${n}`)}else if(o==="set-target"){if(n!=="desktop"&&n!=="emulator"&&n!=="simulator"){console.error("Target must be 'desktop', 'emulator' or 'simulator'."),y(1,"Invalid target");return}if(n!=="desktop"){let{mobileHostSupport:l}=await import("./host-7GZPBA74.js"),m=l();if(!m.supported){console.error(m.reason),y(1,"unsupported host for mobile target");return}}s.setMobile(n==="desktop"?{tui_target:n,default_target:void 0,default_app:void 0}:{tui_target:n}),console.log(`Target set to ${n}`)}else if(o==="set-device-name"||o==="set-os-version"){let l=o==="set-device-name"?"device name":"OS version",m=o==="set-device-name"?"set-os-version":"set-device-name";if(!n){console.error(o==="set-device-name"?'Usage: kane-cli config set-device-name "<name>"':"Usage: kane-cli config set-os-version <version>"),y(1,`Missing ${l}`);return}let{resolveSessionTarget:p,platformOf:g}=await import("./session-target-UWROGOCY.js"),u=s.load().mobile,v=p(u?.tui_target,u?.default_target?.kind),k=v.kind==="emulator"||v.kind==="simulator"?v.kind:null;if(!k){console.error("Set a mobile target first: kane-cli config set-target emulator|simulator"),y(1,`no mobile target for ${o}`);return}let R=u?.default_target?.kind===k?u.default_target:void 0,S=o==="set-device-name"?n.trim():R?.name?.trim()??"",w=o==="set-os-version"?n.trim():R?.os_version?.trim()??"";if(!S||!w){s.setMobile({default_target:{platform:g(k),kind:k,...S?{name:S}:{},...w?{os_version:w}:{}}}),console.log(`${l[0].toUpperCase()}${l.slice(1)} saved. Complete the pair: kane-cli config ${m} "<value>" \u2014 see kane-cli devices list --target ${k}`);return}let{resolveTarget:I}=await import("./registry-CPQHW2L2.js"),f;try{f=await I({device:{name:S,osVersion:w},platform:g(k),interactive:!1})}catch(O){console.error(O instanceof Error?O.message:String(O)),console.error(`Run \`kane-cli doctor --target ${k}\` to check the mobile toolchain.`),y(1,"device discovery failed");return}if(!f.ok){console.error(f.message),y(1,"device not found");return}let x=f.target;if(x.kind!==k){console.error(`${x.displayName} is a ${x.kind}, but the session target is ${k}.`),y(1,"device kind mismatch");return}let{toAppSpec:h}=await import("./prepare-target-XZ3FTVBW.js"),{appSuitsTarget:P}=await import("./resolve-run-intent-THC3EPAX.js"),N=u?.default_app,_=N?h(N):null,C=!!N&&(!_||!P(_,k)),{deviceRefOf:M}=await import("./device-ref-LAZWPRQN.js");s.setMobile({default_target:M(x),...C?{default_app:void 0}:{}}),console.log(`Device set to ${S} (${x.osVersion??w}) \u2014 ${x.platform} \xB7 ${x.kind}`),C&&console.log(`Saved app ${N} does not suit a ${k} \u2014 cleared. Set one: kane-cli config set-app`)}else if(o==="set-app"){if(!n){console.error("Usage: kane-cli config set-app </path/to/build | AppId>"),y(1,"Missing app");return}let{resolveSessionTarget:l}=await import("./session-target-UWROGOCY.js"),m=s.load().mobile,p=l(m?.tui_target,m?.default_target?.kind),g=p.kind==="emulator"||p.kind==="simulator"?p.kind:null;if(!g){console.error("Set a mobile target first: kane-cli config set-target emulator|simulator"),y(1,"no mobile target for set-app");return}if(m?.default_target?.kind!==g){console.error('Set a device first: kane-cli config set-device-name "<name>" && kane-cli config set-os-version "<version>"'),y(1,"no device for set-app");return}let{toAppSpec:u,PACKAGE_ID_REJECTED:v}=await import("./prepare-target-XZ3FTVBW.js"),{appSuitsTarget:k}=await import("./resolve-run-intent-THC3EPAX.js"),R=u(n);if(!R){console.error(`${n}: ${v}`),y(1,"not an installable app");return}if(!k(R,g)){console.error(g==="emulator"?`${n} cannot run on an emulator (needs an .apk, or an APP\u2026 id).`:`${n} cannot run on a simulator (needs a .zip of the .app bundle, or an APP\u2026 id).`),y(1,"app does not suit target");return}if(R.kind!=="app_id"){let{access:S}=await import("fs/promises");if(!await S(R.value).then(()=>!0,()=>!1)){console.error(`${R.value} is not there.`),y(1,"app build missing");return}}s.setMobile({default_app:R.value}),console.log(`App set to ${R.value}`)}else if(o==="set-auto-grant-permissions"||o==="set-auto-accept-alerts"){let l=o==="set-auto-grant-permissions"?{label:"Auto grant permissions",kind:"emulator",key:"auto_grant_permissions"}:{label:"Auto accept alerts",kind:"simulator",key:"auto_accept_alerts"};if(n!=="on"&&n!=="off"){console.error(`Usage: kane-cli config ${o} on|off`),y(1,`Invalid ${o} value`);return}let{resolveSessionTarget:m}=await import("./session-target-UWROGOCY.js"),p=s.load().mobile,g=m(p?.tui_target,p?.default_target?.kind);if(g.kind!=="emulator"&&g.kind!=="simulator"){console.error(`Set a mobile target first: kane-cli config set-target ${l.kind}`),y(1,`no mobile target for ${o}`);return}if(g.kind!==l.kind){console.error(`${l.label} applies to ${l.kind} sessions only \u2014 your target is ${g.kind}. Switch with: kane-cli config set-target ${l.kind}`),y(1,`${o} does not apply to ${g.kind}`);return}s.setMobile({[l.key]:n==="on"}),console.log(`${l.label} set to ${n}`)}else if(o==="set-url"){if(!n){console.error("Usage: kane-cli config set-url <url>"),y(1,"Missing URL");return}let l=mi(n);if(!l){console.error(`Invalid URL: ${n}`),y(1,"Invalid URL");return}s.set("default_url",l),console.log(`Default URL set to ${l}`)}else if(o==="chrome-profile"){if(n||!process.stdin.isTTY){n||(console.error("Usage: kane-cli config chrome-profile <path>"),y(1,"Missing chrome-profile path")),s.set("chrome_profile_path",n),console.log(`Chrome profile set to ${n}`);return}let{ChromeProfilePicker:l}=await import("./ChromeProfilePicker-XAZGCJKR.js"),{render:m}=await import("./build-JIKYOZUH.js"),p=await import("./react-QWOAB3TB.js");await new Promise(g=>{let{unmount:u}=m(p.default.createElement(l,{currentPath:s.load().chrome_profile_path,onSelect:v=>{s.set("chrome_profile_path",v),console.log(`Chrome profile set to ${v}`),u(),g()},onCancel:()=>{u(),g()}}))})}else if(o==="project"){if(n||!process.stdin.isTTY){n||(console.error("Usage: kane-cli config project <project-id>"),y(1,"Missing project ID"));let f=a.getActiveProfile()??"default",x=a.getDefaultEnv();st(a,s,f,x,{projectId:n}),console.log(`Project set to ${n}`);return}let l=a.getDefaultEnv(),m=re(l),p=a.getActiveProfile()??"default",{resolveTmsBasicAuth:g,formatAuthResolutionError:u}=await import("./list-commands-VRRCVWKO.js"),v=await g(p,l,{});if(!v.ok){let{message:f}=u(p,l,v);process.stderr.write(f),y(2,`${v.reason} for "${p}" [${l}]`);return}let{ProjectPicker:k}=await import("./ProjectPicker-UCHMCNFV.js"),{AuthResolver:R}=await import("./resolver-2NUNLK7N.js"),{render:S}=await import("./build-JIKYOZUH.js"),w=await import("./react-QWOAB3TB.js"),I=new R(m.controllerBaseUrl,async()=>null,{username:v.creds.username,access_key:v.creds.access_key});await I.resolve(),await new Promise(f=>{let{unmount:x}=S(w.default.createElement(k,{resolver:I,currentProjectId:s.load().project_id,env:l,onSelect:(h,P)=>{let N=a.getActiveProfile()??"default",_=a.getDefaultEnv();st(a,s,N,_,{projectId:h,projectName:P}),console.log(`Project set to ${P} (${h})`),x(),f()},onCancel:()=>{x(),f()}}))})}else if(o==="folder"){if(n||!process.stdin.isTTY){if(n||(console.error("Usage: kane-cli config folder <folder-id>"),y(1,"Missing folder ID")),!s.load().project_id){console.log("Select a project first: kane-cli config project <id>");return}let h=a.getActiveProfile()??"default",P=a.getDefaultEnv();st(a,s,h,P,{folderId:n}),console.log(`Folder set to ${n}`);return}let l=s.load();if(!l.project_id){console.log("Select a project first: kane-cli config project");return}let m=a.getDefaultEnv(),p=re(m),g=a.getActiveProfile()??"default",{resolveTmsBasicAuth:u,formatAuthResolutionError:v}=await import("./list-commands-VRRCVWKO.js"),k=await u(g,m,{});if(!k.ok){let{message:x}=v(g,m,k);process.stderr.write(x),y(2,`${k.reason} for "${g}" [${m}]`);return}let{FolderPicker:R}=await import("./FolderPicker-XCTJ5447.js"),{AuthResolver:S}=await import("./resolver-2NUNLK7N.js"),{render:w}=await import("./build-JIKYOZUH.js"),I=await import("./react-QWOAB3TB.js"),f=new S(p.controllerBaseUrl,async()=>null,{username:k.creds.username,access_key:k.creds.access_key});await f.resolve(),await new Promise(x=>{let{unmount:h}=w(I.default.createElement(R,{resolver:f,projectId:l.project_id,currentFolderId:l.folder_id,env:m,onSelect:(P,N)=>{let _=a.getActiveProfile()??"default",C=a.getDefaultEnv();st(a,s,_,C,{folderId:P,folderName:N}),console.log(`Folder set to ${N} (${P})`),h(),x()},onCancel:()=>{h(),x()}}))})}else console.log(`Usage: kane-cli config show|set-target|${t?"set-device-name|set-os-version|set-app|":""}set-url|set-window|set-mode|set-assertion-mode|set-network-ws|set-network-sse|set-bug-detection|set-final-validation|chrome-profile|project|folder`)});let i=r.command("run").description("Run a browser or mobile objective (inline natural-language string)").argument("[objective]","Test objective (use {{var}} to reference variables); omitted under --analyzer-only").option("--headless","Run Chrome in headless mode").option("--max-steps <n>","Maximum agent steps","50").option("--timeout <seconds>","Kill run after N seconds").option("--url <url>","Start URL for the run").option("--cdp-endpoint <url>","Connect to existing Chrome CDP endpoint").option("--ws-endpoint <url>","Connect via Playwright WebSocket (e.g. LambdaTest wss:// URL)").option("--global-context <file>",`Override global context markdown (default: ${De(q,"global-memory.md")})`).option("--local-context <file>","Override local context markdown (default: .testmuai/context.md in cwd)").addOption(new B("--model <name>","Model override").hideHelp()).option("--variables <json>",`Inline variables JSON, e.g. '{"user": {"value": "alice"}}'`).option("--variables-file <path>","Load variables from a JSON file").option("--dataset-id <id>","Test Manager dataset whose row supplies the ${column} parameters").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (required with a dataset; a missing or unknown id lists the rows)").option("--session-context <json>","Session context JSON (prior runs)").addOption(new B("--cft","Use Playwright Chromium instead of managed Chrome").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key (skip OAuth)").option("--env <name>","Environment (prod or stage)").option("--mode <name>","Run mode: 'action' (strict \u2014 hard-stop on auth/blocked/error) or 'testing' (lenient \u2014 fall through). Overrides config; default: testing.").option("--assertion-mode <mode>","Assertion mode: 'dom' (default \u2014 DOM-based extraction & assertions, vision fallback) or 'visual' (vision model only). Overrides config.").option("--final-validation <on|off>","Final validation: append the system cp_final checkpoint verifying the objective as a whole. Overrides config (default: off).").option("--agent","Agent mode: plain NDJSON output, no colors/UI").option("--task-skills","Enable domain-specific task skills (experimental)").option("--network-ws","Capture WebSocket frames for assertions/extraction (experimental)").option("--network-sse","Capture Server-Sent Events messages (Chromium-only) for assertions/extraction (experimental)").option("--bug-detection <mode>","Detect product bugs while authoring: off|stop|continue (stop halts the run on a confirmed bug; continue records it and keeps going). Overrides `config set-bug-detection`.",o=>{if(o!=="off"&&o!=="stop"&&o!=="continue")throw new Error("--bug-detection must be off, stop or continue");return o}).addOption(new B("--local","Skip TMS integration (no uploads, no variables/secrets push)").hideHelp()).option("--allow-missing-url","Non-TTY only: proceed from the browser's current page instead of failing when no start URL resolves (a provided --url is still used)").option("--analyzer-only","Judge each --condition against the current page and report verdicts on run_end. No objective, no actions, nothing saved. Agent mode only").option("--condition <text>","A condition to judge under --analyzer-only (repeatable; order is preserved in condition_results)",(o,n)=>[...n,o],[]).option("--code-export","Generate code export after upload").option("--code-language <lang>","Code export language: python (default) | javascript").option("--name <name>","Persist the session under this name (validated [a-zA-Z0-9_-]+)").option("--chrome-profile <path>","Chrome user-data-dir for this run (overrides stored config)").option("--target <name>","Where to run: desktop | emulator | simulator (default: the saved session target)");return t&&i.option("--device-name <name>","Which device, when the target is mobile: the name as `kane-cli devices list` shows it. Needs an OS version via --os-version").option("--os-version <version>","The device's OS version (e.g. 17.5, 14). Alone = any device on that version").option("--app <path|AppId>","App under test, when the target is mobile: a build (.apk / .zip of the .app) or an APP\u2026 id from your uploads"),i.addOption(new B("--appium-url <url>","Appium server URL override (default: runner-managed local server)").hideHelp()).addOption(new B("--appium-session-id <id>","Attach to an existing Appium session on --appium-url instead of provisioning a device (needs --target android|ios)").hideHelp()).option("--skip-code-validation","Skip post-codegen worker-side validation").option("--no-skip-code-validation","Force post-codegen worker-side validation").addHelpText("after",`
203
+ `),r.on("command:*",o=>{r.error(`error: unknown command '${o[0]}'`,{exitCode:2,code:"commander.unknownCommand"})}),r.command("login").description("Authenticate (interactive; --oauth opens the browser, or --username/--access-key for basic auth)").option("--oauth","Login via OAuth (opens browser)").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").addOption(new J("--env <name>","Environment (prod or stage)").default("prod").hideHelp()).option("--profile <name>","Profile name","default").option("--project-id <id>","Project ID (skip picker)").option("--folder-id <id>","Folder ID (skip picker)").addOption(new J("--model <name>","Model").default("v16-alpha").hideHelp()).option("--chrome-profile <path>","Chrome profile path").action(async o=>{let n=new me,c=new Ae,i=o.env,a=o.profile;if(!process.stdin.isTTY||o.oauth||o.username){if(n.setDefaultEnv(i),o.oauth)await new No(a,i,n).login(),console.log(`Logged in as ${a} [${i}] via OAuth`);else if(o.username&&o.accessKey){try{let{validateBasicAuth:S}=await import("./validate-basic-MN5NDCT2.js");await S(i,o.username,o.accessKey)}catch{console.error("Credentials not valid. Please use valid credentials."),y(1,"Invalid basic-auth credentials");return}n.saveBasicAuth(a,i,{username:o.username,access_key:o.accessKey}),console.log(`Logged in as ${a} [${i}] via basic auth`)}else console.error("Provide --oauth, or --username and --access-key"),y(1,"Missing --oauth or credentials for login");n.setActiveProfile(a),c.set("model",o.model),o.chromeProfile&&c.set("chrome_profile_path",o.chromeProfile);let T=null;if(o.username&&o.accessKey)T={username:o.username,access_key:o.accessKey};else try{let w=await Be({creds:n,env:i,log:()=>{}});w.resolvedCreds&&(T={username:w.resolvedCreds.username,access_key:w.resolvedCreds.access_key})}catch{}if(o.projectId&&(it(n,c,a,i,{projectId:o.projectId}),console.log(`Project set to ${o.projectId}`)),o.folderId&&(it(n,c,a,i,{folderId:o.folderId}),console.log(`Folder set to ${o.folderId}`)),T&&(!o.projectId||!o.folderId))try{let S=await Do({creds:n,config:c,profile:a,env:i,tmsCreds:T,log:()=>{}});o.projectId||console.log(`Auto-selected project: ${S.projectName} (${S.projectId})`),o.folderId||console.log(`Auto-selected folder: ${S.folderName} (${S.folderId})`)}catch(S){console.warn(`Could not auto-select project/folder: ${S instanceof Error?S.message:S}`)}sn(n,c,a,i),console.log("Setup complete."),y(0,"Setup complete")}let{SingleShotApp:d}=await import("./SingleShotApp-TZZ2J7ZO.js"),{ScrollbackProvider:l}=await import("./scrollback-JLPJR25X.js"),{render:m}=await import("./build-JIKYOZUH.js"),p=await import("./react-QWOAB3TB.js"),g={current:null},u={current:!1},{waitUntilExit:v,unmount:x}=m(p.default.createElement(l,null,p.default.createElement(d,{resultRef:g,mode:"login",loginCompleteRef:u})),{exitOnCtrlC:!1});Dt(()=>x()),await v();try{process.stdin.setRawMode?.(!1)}catch{}process.stdout.write("\x1B[?25h"),u.current&&console.log("Login setup complete."),process.exit(0)}),r.command("logout").description("Revoke tokens and delete the stored profile credentials").action(async()=>{let o=new me,n=o.getActiveProfile();if(!n){console.log("No active profile to logout");return}let c=o.getDefaultEnv(),i=await jo(o,n,c),a=new Ae;i.switchedTo?(sn(o,a,i.switchedTo.profile,i.switchedTo.env),console.log(`Logged out ${i.profile} [${i.env}]. Switched to ${i.switchedTo.profile} [${i.switchedTo.env}]`)):(a.save({project_id:null,project_name:null,folder_id:null,folder_name:null}),console.log(`Logged out ${i.profile} [${i.env}]. No profiles remaining.`))}),r.command("whoami").description("Show the authenticated identity, active profile, and environment").option("--profile <name>","Profile name").action(async o=>{let n=new me,c=o.profile??n.getActiveProfile()??"default",i=n.getDefaultEnv(),a=n.loadCredentials(c,i),d=n.loadBasicAuth(c,i),l="none",m=d?.username,p,g,u,v;if(d?l="basic":a&&(l="oauth",g=new Date(a.expires_at*1e3).toISOString().slice(0,10)),l==="none")p="missing";else try{let C=await Be({creds:n,env:i,log:()=>{}});if(C.resolvedCreds)u="verified",p="valid",m=C.resolvedCreds.username??m;else{let{classifyAuthFailure:f}=await import("./resolver-G7NGWACO.js");f(C.resolver.lastError)==="auth"?(u="rejected",p="expired",v="Credentials rejected by the server \u2014 re-login or rotate your access key"):(u="unreachable",v=C.resolver.lastError?.message)}}catch(C){let f=C;f.code==="refresh_failed"?(u="rejected",p="expired",v="OAuth token refresh failed \u2014 run 'kane-cli login'"):f.code==="not_authenticated"?(l="none",p="missing"):(u="unreachable",v=f.message)}let{WhoamiView:x}=await import("./WhoamiView-F4PPB7SN.js"),{render:T}=await import("./build-JIKYOZUH.js"),S=await import("./react-QWOAB3TB.js"),{waitUntilExit:w}=T(S.default.createElement(x,{profile:c,env:i,authenticated:u==="verified",authMethod:l,username:m,tokenStatus:p,expiresAt:g,serverStatus:u,detail:v}));await w(),l==="none"?y(1,"whoami: not-authenticated"):u&&u!=="verified"&&y(u==="unreachable"?3:1,`whoami: ${u}`)}),r.command("config <action> [value]").description("Show or change settings ("+["show","set-target",...t?[...pr]:[],"set-mode","set-assertion-mode","set-network-ws","set-network-sse","set-bug-detection","set-final-validation","set-url","set-window","chrome-profile","project","folder","reset"].join(", ")+")").option("--agent","Force JSON output for `show` (auto-on when stdin is not a TTY)").action(async(o,n,c)=>{let i=new Ae,a=new me,d=Wi(o,{hostSupportsMobile:t,mobileMessage:en()});if(d){process.stderr.write(d.message),y(d.exitCode,`config ${o} unavailable off a mobile host`);return}if(o==="show"){let l=i.load(),m=a.getActiveProfile()??"default",p=a.getDefaultEnv(),g=a.loadProfileConfig(m,p)??{},u=g.project_id??l.project_id??null,v=g.project_name??l.project_name??null,x=g.folder_id??l.folder_id??null,T=g.folder_name??l.folder_name??null,S=a.loadBasicAuth(m,p),w=a.loadCredentials(m,p),C=S?`basic (${S.username})`:w?"oauth":"not configured",{resolveSessionTarget:f}=await import("./session-target-UWROGOCY.js"),{deviceRefName:k,deviceRefOsVersion:h}=await import("./device-ref-LAZWPRQN.js"),R=f(l.mobile?.tui_target,l.mobile?.default_target?.kind),O=R.kind==="unset"?"desktop":R.kind==="choose-mobile"?"mobile (legacy \u2014 run `kane-cli config set-target emulator|simulator`)":R.kind;if(!!c?.agent||!process.stdin.isTTY||!process.stdout.isTTY){let Q=oe(p);process.stdout.write(`${JSON.stringify({profile:m,env:p,auth:C,project_id:u,project_name:v,folder_id:x,folder_name:T,model:l.model,mode:l.mode,assertion_mode:l.assertion_mode,network_ws:l.network_ws,network_sse:l.network_sse,bug_detection:l.bug_detection,final_validation:l.final_validation,window_size:`${l.window_size.width}x${l.window_size.height}`,chrome_profile:l.chrome_profile_path,default_url:l.default_url??Gn,target:O,device_name:k(l.mobile?.default_target),os_version:h(l.mobile?.default_target),app:l.mobile?.default_app??null,auto_grant_permissions:l.mobile?.auto_grant_permissions??!0,auto_accept_alerts:l.mobile?.auto_accept_alerts??!0,controller_base_url:Q.controllerBaseUrl,tms_base_url:Q.tmsBaseUrl})}
204
+ `),y(0,"config show complete");return}let{ConfigView:V}=await import("./ConfigView-CJY5MB6H.js"),{render:I}=await import("./build-JIKYOZUH.js"),L=await import("./react-QWOAB3TB.js"),{waitUntilExit:$}=I(L.default.createElement(V,{model:l.model,authLabel:C,profile:m,env:p,defaultUrl:l.default_url??Gn,projectId:u,projectName:v,folderId:x,folderName:T,windowSize:`${l.window_size.width}x${l.window_size.height}`,chromeProfile:l.chrome_profile_path,target:O,deviceName:k(l.mobile?.default_target),osVersion:h(l.mobile?.default_target),appLabel:l.mobile?.default_app??null}));await $()}else if(o==="set-window"&&n){let l=n.split("x").map(Number),[m,p]=l;!m||!p||!Number.isInteger(m)||!Number.isInteger(p)?console.error("Invalid format. Use: kane-cli config set-window WIDTHxHEIGHT"):m<800||m>3840?console.error(`Width must be between 800 and 3840 (got ${m})`):p<600||p>2160?console.error(`Height must be between 600 and 2160 (got ${p})`):(i.set("window_size",{width:m,height:p}),console.log(`Window size set to ${m}x${p}`))}else if(o==="set-mode"){if(n!=="action"&&n!=="testing"){console.error("Mode must be 'action' or 'testing'."),y(1,"Invalid mode");return}i.set("mode",n),console.log(`Mode set to ${n}`)}else if(o==="set-assertion-mode"){if(n!=="visual"&&n!=="dom"){console.error("Assertion mode must be 'visual' or 'dom'."),y(1,"Invalid assertion-mode");return}i.set("assertion_mode",n),console.log(`Assertion mode set to ${n}`)}else if(o==="set-network-ws"){if(n!=="on"&&n!=="off"){console.error("WebSocket capture must be 'on' or 'off'."),y(1,"Invalid network-ws value");return}i.set("network_ws",n==="on"),console.log(`WebSocket capture set to ${n}`)}else if(o==="set-network-sse"){if(n!=="on"&&n!=="off"){console.error("SSE capture must be 'on' or 'off'."),y(1,"Invalid network-sse value");return}i.set("network_sse",n==="on"),console.log(`SSE capture set to ${n}`)}else if(o==="set-bug-detection"){if(n!=="off"&&n!=="stop"&&n!=="continue"){console.error("Bug detection must be 'off', 'stop' or 'continue'."),y(1,"Invalid bug-detection value");return}i.set("bug_detection",n),console.log(`Bug detection set to ${n}`)}else if(o==="set-final-validation"){if(n!=="on"&&n!=="off"){console.error("Final validation must be 'on' or 'off'."),y(1,"Invalid final-validation value");return}i.set("final_validation",n==="on"),console.log(`Final validation set to ${n}`)}else if(o==="set-target"){if(n!=="desktop"&&n!=="emulator"&&n!=="simulator"){console.error("Target must be 'desktop', 'emulator' or 'simulator'."),y(1,"Invalid target");return}if(n!=="desktop"){let{mobileHostSupport:l}=await import("./host-7GZPBA74.js"),m=l();if(!m.supported){console.error(m.reason),y(1,"unsupported host for mobile target");return}}i.setMobile(n==="desktop"?{tui_target:n,default_target:void 0,default_app:void 0}:{tui_target:n}),console.log(`Target set to ${n}`)}else if(o==="set-device-name"||o==="set-os-version"){let l=o==="set-device-name"?"device name":"OS version",m=o==="set-device-name"?"set-os-version":"set-device-name";if(!n){console.error(o==="set-device-name"?'Usage: kane-cli config set-device-name "<name>"':"Usage: kane-cli config set-os-version <version>"),y(1,`Missing ${l}`);return}let{resolveSessionTarget:p,platformOf:g}=await import("./session-target-UWROGOCY.js"),u=i.load().mobile,v=p(u?.tui_target,u?.default_target?.kind),x=v.kind==="emulator"||v.kind==="simulator"?v.kind:null;if(!x){console.error("Set a mobile target first: kane-cli config set-target emulator|simulator"),y(1,`no mobile target for ${o}`);return}let T=u?.default_target?.kind===x?u.default_target:void 0,S=o==="set-device-name"?n.trim():T?.name?.trim()??"",w=o==="set-os-version"?n.trim():T?.os_version?.trim()??"";if(!S||!w){i.setMobile({default_target:{platform:g(x),kind:x,...S?{name:S}:{},...w?{os_version:w}:{}}}),console.log(`${l[0].toUpperCase()}${l.slice(1)} saved. Complete the pair: kane-cli config ${m} "<value>" \u2014 see kane-cli devices list --target ${x}`);return}let{resolveTarget:C}=await import("./registry-3XMA4FOC.js"),f;try{f=await C({device:{name:S,osVersion:w},platform:g(x),interactive:!1})}catch(L){console.error(L instanceof Error?L.message:String(L)),console.error(`Run \`kane-cli doctor --target ${x}\` to check the mobile toolchain.`),y(1,"device discovery failed");return}if(!f.ok){console.error(f.message),y(1,"device not found");return}let k=f.target;if(k.kind!==x){console.error(`${k.displayName} is a ${k.kind}, but the session target is ${x}.`),y(1,"device kind mismatch");return}let{toAppSpec:h}=await import("./prepare-target-NR3MTLLI.js"),{appSuitsTarget:R}=await import("./resolve-run-intent-3SXUS676.js"),O=u?.default_app,_=O?h(O):null,V=!!O&&(!_||!R(_,x)),{deviceRefOf:I}=await import("./device-ref-LAZWPRQN.js");i.setMobile({default_target:I(k),...V?{default_app:void 0}:{}}),console.log(`Device set to ${S} (${k.osVersion??w}) \u2014 ${k.platform} \xB7 ${k.kind}`),V&&console.log(`Saved app ${O} does not suit a ${x} \u2014 cleared. Set one: kane-cli config set-app`)}else if(o==="set-app"){if(!n){console.error("Usage: kane-cli config set-app </path/to/build | AppId>"),y(1,"Missing app");return}let{resolveSessionTarget:l}=await import("./session-target-UWROGOCY.js"),m=i.load().mobile,p=l(m?.tui_target,m?.default_target?.kind),g=p.kind==="emulator"||p.kind==="simulator"?p.kind:null;if(!g){console.error("Set a mobile target first: kane-cli config set-target emulator|simulator"),y(1,"no mobile target for set-app");return}if(m?.default_target?.kind!==g){console.error('Set a device first: kane-cli config set-device-name "<name>" && kane-cli config set-os-version "<version>"'),y(1,"no device for set-app");return}let{toAppSpec:u,PACKAGE_ID_REJECTED:v}=await import("./prepare-target-NR3MTLLI.js"),{appSuitsTarget:x}=await import("./resolve-run-intent-3SXUS676.js"),T=u(n);if(!T){console.error(`${n}: ${v}`),y(1,"not an installable app");return}if(!x(T,g)){console.error(g==="emulator"?`${n} cannot run on an emulator (needs an .apk, or an APP\u2026 id).`:`${n} cannot run on a simulator (needs a .zip of the .app bundle, or an APP\u2026 id).`),y(1,"app does not suit target");return}if(T.kind!=="app_id"){let{access:S}=await import("fs/promises");if(!await S(T.value).then(()=>!0,()=>!1)){console.error(`${T.value} is not there.`),y(1,"app build missing");return}}i.setMobile({default_app:T.value}),console.log(`App set to ${T.value}`)}else if(o==="set-auto-grant-permissions"||o==="set-auto-accept-alerts"){let l=o==="set-auto-grant-permissions"?{label:"Auto grant permissions",kind:"emulator",key:"auto_grant_permissions"}:{label:"Auto accept alerts",kind:"simulator",key:"auto_accept_alerts"};if(n!=="on"&&n!=="off"){console.error(`Usage: kane-cli config ${o} on|off`),y(1,`Invalid ${o} value`);return}let{resolveSessionTarget:m}=await import("./session-target-UWROGOCY.js"),p=i.load().mobile,g=m(p?.tui_target,p?.default_target?.kind);if(g.kind!=="emulator"&&g.kind!=="simulator"){console.error(`Set a mobile target first: kane-cli config set-target ${l.kind}`),y(1,`no mobile target for ${o}`);return}if(g.kind!==l.kind){console.error(`${l.label} applies to ${l.kind} sessions only \u2014 your target is ${g.kind}. Switch with: kane-cli config set-target ${l.kind}`),y(1,`${o} does not apply to ${g.kind}`);return}i.setMobile({[l.key]:n==="on"}),console.log(`${l.label} set to ${n}`)}else if(o==="set-url"){if(!n){console.error("Usage: kane-cli config set-url <url>"),y(1,"Missing URL");return}let l=gs(n);if(!l){console.error(`Invalid URL: ${n}`),y(1,"Invalid URL");return}i.set("default_url",l),console.log(`Default URL set to ${l}`)}else if(o==="chrome-profile"){if(n||!process.stdin.isTTY){n||(console.error("Usage: kane-cli config chrome-profile <path>"),y(1,"Missing chrome-profile path")),i.set("chrome_profile_path",n),console.log(`Chrome profile set to ${n}`);return}let{ChromeProfilePicker:l}=await import("./ChromeProfilePicker-6IVAYCWJ.js"),{render:m}=await import("./build-JIKYOZUH.js"),p=await import("./react-QWOAB3TB.js");await new Promise(g=>{let{unmount:u}=m(p.default.createElement(l,{currentPath:i.load().chrome_profile_path,onSelect:v=>{i.set("chrome_profile_path",v),console.log(`Chrome profile set to ${v}`),u(),g()},onCancel:()=>{u(),g()}}))})}else if(o==="project"){if(n||!process.stdin.isTTY){n||(console.error("Usage: kane-cli config project <project-id>"),y(1,"Missing project ID"));let f=a.getActiveProfile()??"default",k=a.getDefaultEnv();it(a,i,f,k,{projectId:n}),console.log(`Project set to ${n}`);return}let l=a.getDefaultEnv(),m=oe(l),p=a.getActiveProfile()??"default",{resolveTmsBasicAuth:g,formatAuthResolutionError:u}=await import("./list-commands-Q77CAQJ2.js"),v=await g(p,l,{});if(!v.ok){let{message:f}=u(p,l,v);process.stderr.write(f),y(2,`${v.reason} for "${p}" [${l}]`);return}let{ProjectPicker:x}=await import("./ProjectPicker-J42MEJRQ.js"),{AuthResolver:T}=await import("./resolver-G7NGWACO.js"),{render:S}=await import("./build-JIKYOZUH.js"),w=await import("./react-QWOAB3TB.js"),C=new T(m.controllerBaseUrl,async()=>null,{username:v.creds.username,access_key:v.creds.access_key});await C.resolve(),await new Promise(f=>{let{unmount:k}=S(w.default.createElement(x,{resolver:C,currentProjectId:i.load().project_id,env:l,onSelect:(h,R)=>{let O=a.getActiveProfile()??"default",_=a.getDefaultEnv();it(a,i,O,_,{projectId:h,projectName:R}),console.log(`Project set to ${R} (${h})`),k(),f()},onCancel:()=>{k(),f()}}))})}else if(o==="folder"){if(n||!process.stdin.isTTY){if(n||(console.error("Usage: kane-cli config folder <folder-id>"),y(1,"Missing folder ID")),!i.load().project_id){console.log("Select a project first: kane-cli config project <id>");return}let h=a.getActiveProfile()??"default",R=a.getDefaultEnv();it(a,i,h,R,{folderId:n}),console.log(`Folder set to ${n}`);return}let l=i.load();if(!l.project_id){console.log("Select a project first: kane-cli config project");return}let m=a.getDefaultEnv(),p=oe(m),g=a.getActiveProfile()??"default",{resolveTmsBasicAuth:u,formatAuthResolutionError:v}=await import("./list-commands-Q77CAQJ2.js"),x=await u(g,m,{});if(!x.ok){let{message:k}=v(g,m,x);process.stderr.write(k),y(2,`${x.reason} for "${g}" [${m}]`);return}let{FolderPicker:T}=await import("./FolderPicker-RQIVS7ZR.js"),{AuthResolver:S}=await import("./resolver-G7NGWACO.js"),{render:w}=await import("./build-JIKYOZUH.js"),C=await import("./react-QWOAB3TB.js"),f=new S(p.controllerBaseUrl,async()=>null,{username:x.creds.username,access_key:x.creds.access_key});await f.resolve(),await new Promise(k=>{let{unmount:h}=w(C.default.createElement(T,{resolver:f,projectId:l.project_id,currentFolderId:l.folder_id,env:m,onSelect:(R,O)=>{let _=a.getActiveProfile()??"default",V=a.getDefaultEnv();it(a,i,_,V,{folderId:R,folderName:O}),console.log(`Folder set to ${O} (${R})`),h(),k()},onCancel:()=>{h(),k()}}))})}else console.log(`Usage: kane-cli config show|set-target|${t?"set-device-name|set-os-version|set-app|":""}set-url|set-window|set-mode|set-assertion-mode|set-network-ws|set-network-sse|set-bug-detection|set-final-validation|chrome-profile|project|folder`)});let s=r.command("run").description("Run a browser or mobile objective (inline natural-language string)").argument("[objective]","Test objective (use {{var}} to reference variables); omitted under --analyzer-only").option("--headless","Run Chrome in headless mode").option("--max-steps <n>","Maximum agent steps","50").option("--timeout <seconds>","Kill run after N seconds").option("--url <url>","Start URL for the run").option("--cdp-endpoint <url>","Connect to existing Chrome CDP endpoint").option("--ws-endpoint <url>","Connect via Playwright WebSocket (e.g. LambdaTest wss:// URL)").option("--global-context <file>",`Override global context markdown (default: ${Me(z,"global-memory.md")})`).option("--local-context <file>","Override local context markdown (default: .testmuai/context.md in cwd)").addOption(new J("--model <name>","Model override").hideHelp()).option("--variables <json>",`Inline variables JSON, e.g. '{"user": {"value": "alice"}}'`).option("--variables-file <path>","Load variables from a JSON file").option("--dataset-id <id>","Test Manager dataset whose row supplies the ${column} parameters").option("--dataset-row <_id>","The row to use, by its _id as Test Manager shows it (required with a dataset; a missing or unknown id lists the rows)").option("--session-context <json>","Session context JSON (prior runs)").addOption(new J("--cft","Use Playwright Chromium instead of managed Chrome").hideHelp()).option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key (skip OAuth)").option("--env <name>","Environment (prod or stage)").option("--mode <name>","Run mode: 'action' (strict \u2014 hard-stop on auth/blocked/error) or 'testing' (lenient \u2014 fall through). Overrides config; default: testing.").option("--assertion-mode <mode>","Assertion mode: 'dom' (default \u2014 DOM-based extraction & assertions, vision fallback) or 'visual' (vision model only). Overrides config.").option("--final-validation <on|off>","Final validation: append the system cp_final checkpoint verifying the objective as a whole. Overrides config (default: off).").option("--agent","Agent mode: plain NDJSON output, no colors/UI").option("--task-skills","Enable domain-specific task skills (experimental)").option("--network-ws","Capture WebSocket frames for assertions/extraction (experimental)").option("--network-sse","Capture Server-Sent Events messages (Chromium-only) for assertions/extraction (experimental)").option("--bug-detection <mode>","Detect product bugs while authoring: off|stop|continue (stop halts the run on a confirmed bug; continue records it and keeps going). Overrides `config set-bug-detection`.",o=>{if(o!=="off"&&o!=="stop"&&o!=="continue")throw new Error("--bug-detection must be off, stop or continue");return o}).addOption(new J("--local","Skip TMS integration (no uploads, no variables/secrets push)").hideHelp()).option("--allow-missing-url","Non-TTY only: proceed from the browser's current page instead of failing when no start URL resolves (a provided --url is still used)").option("--analyzer-only","Judge each --condition against the current page and report verdicts on run_end. No objective, no actions, nothing saved. Agent mode only").option("--condition <text>","A condition to judge under --analyzer-only (repeatable; order is preserved in condition_results)",(o,n)=>[...n,o],[]).option("--code-export","Generate code export after upload").option("--code-language <lang>","Code export language: python (default) | javascript").option("--name <name>","Persist the session under this name (validated [a-zA-Z0-9_-]+)").option("--chrome-profile <path>","Chrome user-data-dir for this run (overrides stored config)").option("--target <name>","Where to run: desktop | emulator | simulator (default: the saved session target)");return t&&s.option("--device-name <name>","Which device, when the target is mobile: the name as `kane-cli devices list` shows it. Needs an OS version via --os-version").option("--os-version <version>","The device's OS version (e.g. 17.5, 14). Alone = any device on that version").option("--app <path|AppId>","App under test, when the target is mobile: a build (.apk / .zip of the .app) or an APP\u2026 id from your uploads"),s.addOption(new J("--appium-url <url>","Appium server URL override (default: runner-managed local server)").hideHelp()).addOption(new J("--appium-session-id <id>","Attach to an existing Appium session on --appium-url instead of provisioning a device (needs --target android|ios)").hideHelp()).option("--skip-code-validation","Skip post-codegen worker-side validation").option("--no-skip-code-validation","Force post-codegen worker-side validation").addHelpText("after",`
205
205
  Variables:
206
206
  Variables are loaded in order (later wins):
207
- 1. Global: ${De(q,"variables")}/*.json
207
+ 1. Global: ${Me(z,"variables")}/*.json
208
208
  2. Local: {cwd}/.testmuai/variables/*.json
209
209
  3. File: --variables-file <path>
210
210
  4. Inline: --variables '{"key": {"value": "...", "secret": false}}'
@@ -219,42 +219,42 @@ Variables:
219
219
 
220
220
  Context Files:
221
221
  Context files provide additional instructions to the agent.
222
- Global: ${De(q,"global-memory.md")}
222
+ Global: ${Me(z,"global-memory.md")}
223
223
  Local: {cwd}/.testmuai/context.md
224
224
 
225
225
  Override with --global-context / --local-context flags.
226
- `).action(async(o,n)=>{try{if(n.name){let{validateNameOrThrow:b}=await import("./name-validator-5YGJXLZ7.js");try{b(n.name)}catch(T){console.error(`error: ${T.message}`),y(2,"Invalid --name");return}}if(o&&o.endsWith(".md")&&!o.startsWith("-")){process.stderr.write(`error: '.md' files are no longer accepted by 'kane-cli run'.
226
+ `).action(async(o,n)=>{try{if(n.name){let{validateNameOrThrow:b}=await import("./name-validator-5YGJXLZ7.js");try{b(n.name)}catch(P){console.error(`error: ${P.message}`),y(2,"Invalid --name");return}}if(o&&o.endsWith(".md")&&!o.startsWith("-")){process.stderr.write(`error: '.md' files are no longer accepted by 'kane-cli run'.
227
227
  Use 'kane-cli testmd run <path>' instead.
228
- `),process.exit(2);return}let c=!!n.analyzerOnly,s=n.condition??[];{let b=_s({analyzerOnly:c,objective:o,conditions:s,agent:!!n.agent,isTTY:!!process.stdin.isTTY,codeExport:n.codeExport,name:n.name,target:n.target,app:n.app,deviceName:n.deviceName,osVersion:n.osVersion});if(b){process.stderr.write(`error: ${b}
229
- `),process.exit(2);return}}if(c){let b=Rs(n);b.length&&process.stderr.write(`info: --analyzer-only ignores ${b.join(", ")}
230
- `),Object.assign(n,Es()),o=Ps(s)}o=o??"";{let{objectiveVariableGate:b}=await import("./objective-variable-gate-EEYJ6B3X.js"),{formatUnresolvedReceipt:T,unresolvedVariablesEvent:A}=await import("./variable-receipt-CMCDUJI2.js"),j=b({objective:o,cwd:process.cwd(),globalDir:De(q,"variables"),opts:{variables:n.variables,variablesFile:n.variablesFile,sessionContext:n.sessionContext}});j.length>0&&(!!n.agent||!process.stdin.isTTY?process.stdout.write(JSON.stringify(A(j,{cwd:process.cwd()}))+`
231
- `):process.stderr.write(T(j,{cwd:process.cwd()})))}let a=new le,d=new Te,l=d.load();n.chromeProfile&&(l.chrome_profile_path=n.chromeProfile);let m;if(n.mode===void 0)m=l.mode==="action"?"action":"testing";else if(n.mode==="action"||n.mode==="testing")m=n.mode;else{console.error("Invalid --mode. Must be 'action' or 'testing'."),y(2,"Invalid --mode");return}let p;if(n.assertionMode===void 0)p=l.assertion_mode==="dom"?"dom":"visual";else if(n.assertionMode==="visual"||n.assertionMode==="dom")p=n.assertionMode;else{console.error("Invalid --assertion-mode. Must be 'visual' or 'dom'."),y(2,"Invalid --assertion-mode");return}let g;if(n.finalValidation!==void 0){if(n.finalValidation!=="on"&&n.finalValidation!=="off"){console.error("Invalid --final-validation. Must be 'on' or 'off'."),y(2,"Invalid --final-validation");return}g=n.finalValidation==="on"}let u=new Mt,{printRecordingBanner:v}=await import("./recording-banner-SRLPSTFP.js");await v({isAgent:!!n.agent||!process.stdin.isTTY,sessionId:u.sessionId,sessionName:n.name??null,testPath:n.name?De(process.cwd(),".testmuai","tests",`${n.name}_test.md`):null,outputPath:n.name?De(process.cwd(),".testmuai","tests",`output-${n.name}`):null});let k=!!(n.username&&n.accessKey);if(await bi({isInteractive:!!process.stdin.isTTY&&!n.agent&&!k,creds:a,config:d}),!k){let b=a.getActiveProfile(),T=a.getDefaultEnv();b&&(a.loadBasicAuth(b,T)||a.loadCredentials(b,T))||(console.error("Not authenticated. Run: kane-cli login --oauth, or kane-cli login --username <user> --access-key <key>"),y(1,"Not authenticated"))}let R=`${a.getActiveProfile()??"no profile"}/${a.getDefaultEnv()}`,S=[],w=n.env??a.getDefaultEnv(),I=null,f=[],x=(b,T,A,j)=>{I?I(b,T,A,j):f.push([b,T,A,j])},h;try{h=await Ue({creds:a,env:w,usernameFlag:n.username,accessKeyFlag:n.accessKey,log:x})}catch(b){throw b instanceof Ot&&(console.error(b.code==="not_authenticated"?"Not authenticated. Run: kane-cli login":"Token refresh failed. Run: kane-cli login"),y(2,b.code==="not_authenticated"?"Not authenticated":"Token refresh failed")),b}let P=!!h.basicAuth,N=h.basicAuth?.username,_=h.basicAuth?.access_key,C=h.token,M=h.resolver,O=h.resolvedCreds;h.basicAuth&&S.push(`Auth: ${h.basicAuth.username}`);let W=null;{let b=null;try{b=_o({datasetId:n.datasetId,datasetRow:n.datasetRow},void 0)}catch(T){console.error(`error: ${T.message}`),y(2,T.message)}if(b){h.basicAuth||(console.error("error: --dataset-id needs Test Manager credentials \u2014 run 'kane-cli login' or pass --username/--access-key"),y(2,"dataset needs Test Manager credentials"));try{W=await Ni({selection:b,tmsBaseUrl:re(w).tmsBaseUrl,auth:h.basicAuth,saveDir:u.sessionDir,log:(A,j,Z,xe)=>u.log(A,j,Z,xe)})}catch(A){console.error(`error: ${A.message}`),y(2,A.message)}let T=Ji([{text:o,usedBy:{file:Ki,step:1}}],W.columns,b.id);T.length>0&&(!!n.agent||!process.stdin.isTTY?process.stdout.write(JSON.stringify(mn(T,{cwd:process.cwd()}))+`
232
- `):process.stderr.write(Nt(T,{cwd:process.cwd()})))}}let D=a.getActiveProfile()??"default",X=a.getDefaultEnv();Ro(a,d,D,X);let F=d.load(),we=h.basicAuth??(h.resolvedCreds?{username:h.resolvedCreds.username,access_key:h.resolvedCreds.access_key}:null);if(we){let b=!!n.agent||!process.stdin.isTTY,T=await rn({creds:a,config:d,profile:D,env:X,tmsCreds:we,isLocal:!!n.local,log:x});T.status==="cancelled"&&(console.error("error: project/folder configuration failed. See remediation above, or use --local."),y(2,"project/folder gate failed")),T.status==="ok"&&T.autoDefaulted&&b&&process.stdout.write(Ao(T.autoDefaulted)),F=d.load()}else n.local||(console.error("Project and folder must be configured. Run `kane-cli login` to set up auth, or pass --username/--access-key, then `kane-cli config project <id>` / `kane-cli config folder <id>`."),y(2,"no TMS credentials for project/folder gate"));let{resolveRunIntent:ve,formatRunningOn:Ze,missingPieceMessage:et,staleAppMessage:fe,CHOOSE_MOBILE_KIND_MESSAGE:ye}=await import("./resolve-run-intent-THC3EPAX.js"),{mobileHostSupport:tt}=await import("./host-7GZPBA74.js"),{platformOf:Wt}=await import("./session-target-UWROGOCY.js"),ke=Hi()&&!n.agent,{attachTargetFromFlags:$,formatAttachBanner:be}=await import("./attach-target-V6LECVES.js"),Q=$({appiumUrl:n.appiumUrl,appiumSessionId:n.appiumSessionId,target:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app});if(Q.kind==="invalid"){console.error(`error: ${Q.message}`),y(2,"attach run not fully specified");return}let Y=Q.kind==="attach"?Q.device:null,_e=ve({flags:{target:Y?void 0:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app},saved:Y?void 0:l.mobile,host:tt()});if(_e.kind==="choose-mobile-kind")if(ke){let{promptMobileKind:b}=await import("./mobile-prompts-CMIVWDHQ.js"),T=await b();if(!T){y(2,"target selection cancelled");return}d.setMobile({tui_target:T}),_e=ve({flags:{target:T,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app},saved:d.load().mobile,host:tt()})}else{console.error(`error: ${ye}`),y(2,"ambiguous legacy session target");return}if(_e.kind==="invalid"){console.error(`error: ${_e.message}`),y(2,"invalid run target");return}if(_e.kind==="choose-mobile-kind"){y(2,"ambiguous legacy session target");return}for(let b of _e.warnings)console.error(`warning: ${b}`);let $e=_e.kind==="mobile"?_e:null;if($e&&n.codeLanguage?.toLowerCase()==="javascript"){console.error("error: --code-language javascript is not supported on a mobile target \u2014 mobile code export is Appium + Python only. Drop the flag, or pass --code-language python."),y(2,"javascript code export on a mobile target");return}let Re=$e||Y?"device":"web";if(Y?console.error(be(Y)):$e||console.error(Ze({target:"desktop"})),!c&&!$s({target:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app,cdpEndpoint:n.cdpEndpoint,wsEndpoint:n.wsEndpoint,cft:n.cft,url:n.url})){let b=Re==="device"?"mobile":"web",T=await Io({objective:o,sessionTarget:b,controllerBaseUrl:re(w).controllerBaseUrl,authHeader:h.basicAuth?Yn(h.basicAuth.username,h.basicAuth.access_key):`Bearer ${h.token}`}),A=Ms(Co(T,b));A&&console.error(A),x("info","CLASSIFY_VERDICT","Objective classified",{session_target:b,target:T?.target??null,confidence:T?.confidence??null,warned:!!A})}let We=Re==="device"?null:pi({flag:n.url,configDefault:l.default_url}),K=Re==="device"?!1:fi({resolvedUrl:We,local:n.local,allowMissingUrl:n.allowMissingUrl,isTTY:!!process.stdin.isTTY}),ge=Mi({objective:o,globalDir:De(q,"variables"),localDir:De(process.cwd(),".testmuai","variables"),file:n.variablesFile,inline:n.variables,parameters:W?.parameters,onLoadError:b=>console.error(b)}),Vr;if(n.sessionContext)try{Vr=JSON.parse(n.sessionContext)}catch{console.error("Invalid --session-context JSON"),y(2,"Invalid --session-context JSON")}let Bc=n.globalContext??De(q,"global-memory.md"),Kc=n.localContext??De(process.cwd(),".testmuai","context.md"),Ur=tr(Bc),Br=tr(Kc),Me={},oe=await _i(Re,{prepareDevice:async()=>{if(Y)return{device:Y};let b=$e,{isAppId:T}=await import("./app-download-N7MLJQ42.js"),{access:A}=await import("fs/promises"),j=b.app?.value,Z=!1,xe=!1,ee=b.app?.source==="saved"&&!T(b.app.value)?await A(b.app.value).then(()=>!1,()=>!0):!1;if(ke){if(b.missing.includes("app")||ee){ee&&console.error(`${b.app.value} is no longer there \u2014 choose the app under test.`);let{promptApp:V}=await import("./mobile-prompts-CMIVWDHQ.js"),{AppClient:me}=await import("./app-client-ZCCNE3RV.js"),Ve=N&&_?pt=>new me(it(w),{username:N,accessKey:_}).list({type:b.target,...pt}):void 0,ie=await V({kind:b.target,...Ve?{listApps:Ve}:{}});if(!ie)throw y(2,"app selection cancelled"),new Error("app selection cancelled");j=ie,Z=!0}}else{let V=b.missing.map(me=>et(b.target,me));if(ee&&V.push(fe(b.app.value,b.target)),V.length>0){for(let me of V)console.error(`error: ${me}`);y(2,"mobile run not fully specified")}}let U,Se=vn();try{U=await So({device:b.deviceSelector,platform:Wt(b.target),app:j,defaults:l.mobile,interactive:ke,agent:!!n.agent,appiumUrl:n.appiumUrl,...ke?{pickTarget:async V=>{let{promptDevice:me}=await import("./mobile-prompts-CMIVWDHQ.js"),Ve=V.filter(pt=>pt.kind===b.target),ie=await me(Ve.length>0?Ve:V,b.target,l.mobile?.default_target);return ie&&(xe=!0),ie}}:{},...!n.local&&N&&_&&O?.org_id?{cloudUpload:{env:w,orgId:String(O.org_id),userId:String(O.user_id??""),baseUrl:it(w),auth:{username:N,accessKey:_}}}:{},onProgress:Se.onProgress})}catch(V){Se.done(),V instanceof xo?(console.error(V.doctorText),console.error(`
233
- ${V.message}`)):console.error(V instanceof Error?V.message:String(V)),y(2,"mobile target preparation failed")}Se.done(),U.device.app_package||(console.error(`error: ${et(b.target,"app")}`),y(2,"mobile run missing app binding"));let L=b.device?.source==="flag";if(Z||xe||!L){let{deviceRefOf:V}=await import("./device-ref-LAZWPRQN.js");d.setMobile({...n.target===void 0?{tui_target:b.target}:{},...L?{}:{default_target:V(U.target)},...Z&&j?{default_app:j}:{}})}Me.current=U;let te=j??U.appRef??U.device.app_package??"";return Me.appLabel=T(te)?te:Lu(te),{device:U.device,...U.appRef?{appRef:U.appRef}:{},...U.appId?{appId:U.appId}:{}}},prepareWeb:async()=>{try{return await Ci({config:l,startUrl:We??void 0,headless:n.headless,cft:n.cft,wsEndpoint:n.wsEndpoint,cdpEndpoint:n.cdpEndpoint})}catch(b){console.error(jo(b));let T=b instanceof No?"Chrome not found at standard paths":`Chrome failed: ${b instanceof Error?b.message:b}`;y(2,T)}}}),qe=oe.kind==="web"?oe.chrome:{instance:null,tempDir:null};qe.instance&&ht("chrome",()=>{qe.instance.kill()});let Oe=null,Kr=qe.cdpEndpoint??n.cdpEndpoint;if(Kr&&!n.cft&&!n.wsEndpoint&&(Oe=Ko({headless:n.headless,cdpEndpoint:Kr,chromePid:qe.instance?.process.pid}),Oe&&ht("marker-overlay",()=>Oe.kill())),oe.kind==="device"&&Me.current&&$e){let b=Ze({target:$e.target,deviceLabel:Me.current.target.displayName,appLabel:Me.appLabel??""});ke||console.error(b),S.push(b)}else n.cft?S.push("CfT mode: Playwright will manage its own browser"):n.wsEndpoint?S.push(`Playwright WS endpoint (${n.wsEndpoint.slice(0,60)}...)`):n.cdpEndpoint?S.push(`CDP connected (${n.cdpEndpoint})`):qe.cdpEndpoint&&S.push(`Chrome ready (${qe.cdpEndpoint})`);let E=u;E.start({model:n.model??l.model,environment:w,profile:a.getActiveProfile()}),n.name&&E.setSessionName(n.name),h.resolvedCreds?.org_id!==void 0&&E.setOrgId(String(h.resolvedCreds.org_id)),h.resolvedCreds?.plan!==void 0&&E.setPlan(h.resolvedCreds.plan??null),E.setUserIdentity(h.resolvedCreds?.username??null,h.resolvedCreds?.email??null),I=(b,T,A,j)=>E.log(b,T,A,j);for(let b of f)E.log(...b);f.length=0;let Jr=P&&N&&_?{username:N,accessKey:_}:C??null,Le=null;if(Jr!==null){let b=await Vi({env:w,tmsCreds:h.resolvedCreds??null,resolver:h.resolver,auth:Jr,getToken:async()=>h.token??null,session:E,log:(T,A,j,Z)=>E.log(T,A,j,Z),skipScreenshotQueue:n.local,invocationMode:n.agent||!process.stdin.isTTY?"agent":"cli"});Le=b.screenshotQueue,b.remoteLogger&&(ht("remote-logger",()=>b.remoteLogger.shutdownSync()),mo(b.remoteLogger),uo(Zr))}let Wr=h.basicAuth&&!n.local?await Oi({variables:ge,auth:h.basicAuth,orgId:String(h.resolvedCreds?.org_id??""),env:w,localMode:!!n.local,log:(b,T,A,j)=>E.log(b,T,A,j)}):{};E.setAuteurVariables(ge.auteur),E.setFirstRun(ge.auteurObjective,We??"");let{startInlineEvidence:Jc,noteInlineSpawn:Yr,inlineEvidenceBlock:Wc,finalizeInlineEvidence:Yc,createCdpBrowserCapture:Hc}=await import("./evidence-XJGXVLO5.js"),On=Hc(qe.cdpEndpoint),ne=c?null:await Jc({objectiveOrName:n.name??o,sessionId:E.sessionId,title:n.name??o,producerVersion:he,pid:process.pid,surfaces:We?[We]:void 0,packRootDir:De(E.sessionDir,"evidence")}),Yt=async(b={})=>(E.flushRecorder(),await Yc(ne,{saved:!!E.sessionName,local:!!n.local,deviceName:Me.current?.target.displayName,deviceModel:Me.current?.target.modelIdentifier,recordedTestPath:E.recorder?.lastWrittenPath??null,externalIdInput:{session_id:E.sessionId,commit_id:E.sessionId,test_id:E.testId??void 0,testcase_id:b.testcaseId??E.testcaseId??void 0,project_id:F.project_id??void 0,folder_id:F.folder_id??void 0,org_id:E.orgId??void 0,session_name:E.sessionName??void 0,user_name:E.userName??void 0,user_email:E.userEmail??void 0,sharable_link:Si(re(w).testManagerUiUrl,F.project_id,b.testcaseId??E.testcaseId,b.shareId)},cdpBrowserCapture:On,model:n.model??l.model,tuiLogPath:De(E.sessionDir,"tui.log"),log:(T,A,j,Z)=>E.log(T,A,j,Z)}));if(!n.local&&h.basicAuth&&F.project_id){let b=re(w),T=await Fi({tmsBaseUrl:b.tmsBaseUrl,auth:h.basicAuth,objective:ge.auteurObjective,url:We??"",projectId:F.project_id,folderId:F.folder_id??"",hasCustomProfile:!!l.chrome_profile_path,...oe.kind==="device"?{mobile:ji({platform:oe.device.platform,appId:oe.appId,deviceName:Me.current?.target.displayName,osVersion:Me.current?.target.osVersion,udid:oe.device.udid})}:{},log:(A,j,Z,xe)=>E.log(A,j,Z,xe)});T&&E.setTestId(T)}E.setResolvedGlobal({mode:m,max_steps:parseInt(n.maxSteps,10),timeout:n.timeout?parseInt(n.timeout,10):void 0,target:Ei(oe,{cdpEndpoint:n.cdpEndpoint,wsEndpoint:n.wsEndpoint}),app:Ti(oe),os_version:oe.kind==="device"?Me.current?.target.osVersion:void 0,device_name:Ri(oe,Me.current?.target),chrome_profile:l.chrome_profile_path||void 0,cdp_endpoint:n.cdpEndpoint||void 0,ws_endpoint:n.wsEndpoint||void 0,headless:n.headless,global_context:Ur??void 0,local_context:Br??void 0,variables:Object.keys(zn(ge.auteur)).length>0?zn(ge.auteur):void 0,dataset:W?Eo(W.selection.id,W.rowId):void 0});let Hr=$i(ge.auteur,ge.auteurObjective),Gr=Ai({objective:ge.auteurObjective,conditions:c?As(ge.auteurObjective,s.length):void 0,url:We??void 0,requireStartUrl:K,model:n.model??l.model,chrome:qe,auth:h,sessionId:E.sessionId,runIndex:0,windowSize:l.window_size,maxSteps:parseInt(n.maxSteps,10),headless:n.headless,disableAskUser:!process.stdin.isTTY,enableTaskSkills:n.taskSkills,networkWs:n.networkWs,networkSse:n.networkSse,bugDetection:n.bugDetection??l.bug_detection,variables:Object.keys(Hr).length>0?Hr:void 0,globalContext:Ur??void 0,localContext:Br??void 0,sessionContext:Vr,device:oe.kind==="device"?oe.device:void 0,evidence:Wc(ne)}),Nn=li(),qr=Le?(b,T,A,j)=>{if(ne&&j){Nn.track(di(ne.packTestDir,j,Le,(Z,xe,ee,U)=>E.log(Z,xe,ee,U)));return}ui(E.sessionDir,T,b,Le,(Z,xe,ee,U)=>E.log(Z,xe,ee,U),A)}:void 0;if(!process.stdin.isTTY&&!n.agent&&(n.agent=!0),n.agent){let b=L=>{process.stdout.write(JSON.stringify(L)+`
234
- `)};Oe?.setRunActive(!0);let T;try{T=await Cs(Gr,{environment:w,mode:m,assertionMode:p,finalValidation:g,log:(L,te,V,me)=>E.log(L,te,V,me)},{onStepEnd:qr,onStepLog:(L,te,V)=>E.logStep(L,te,V),onReasoning:L=>Oe?.setStepText(L),onStepComplete:()=>Oe?.setStepComplete(),kind:c?"evaluate":"author",timeoutSeconds:c&&n.timeout?parseInt(n.timeout,10):void 0,onTimeout:()=>process.stderr.write(`Timeout: ${n.timeout}s exceeded \u2014 stopping the analyzer run
235
- `)})}finally{Oe?.setRunActive(!1)}let{lastRunEnd:A,stepsTotal:j,hadError:Z,bifurcationFlows:xe}=T;if(c&&T.timedOut&&(b({type:"run_end",status:"failed",run_id:"run-0",reason:`Timeout: ${n.timeout}s exceeded`,condition_results:s.map(()=>null),condition_reasons:s.map(()=>"timed out before a verdict"),condition_sub_checks:s.map(()=>null)}),await E.finish("complete"),y(3,`Analyzer run: Timeout after ${n.timeout}s`)),Yr(ne,T.evidence,A),Z&&E.escalateRun(0),A){let L=Xn(A,0,xe);E.addRunResult(Qn(A,ge.auteurObjective,0,L),A.total_runs);let te=A.status==="passed"?"passed":Z?"error":"failed";E.addFlow({runIndex:0,objective:ge.auteurObjective,status:te,summary:A.summary??"",duration:A.duration??0,steps:j,stepsPassed:te==="passed"?j:0,stepsFailed:te==="passed"?0:j,reason:A.reason,creditsConsumed:A.credits_consumed})}ne&&await On(),Hn("chrome","Agent run completed");let ee;if(E.log("info","DIRECT_UPLOAD_START","Starting direct upload (agent mode)",{agent_mode:!0,last_run_end:!!A,local:!!n.local,mobile:oe.kind==="device"}),A&&!n.local)try{let L=re(w),te=F.project_id;if(h.basicAuth){let{UploadPipeline:V}=await import("./pipeline-RSCRNNPW.js");Le&&(await Nn.settle(),await Le.drain());let me=nr({mobile:oe.kind==="device",session:E,env:w,auth:h,variables:ge,variableIds:Wr,testParams:W?.testParams,projectId:te,folderId:F.folder_id,totalSteps:j,totalDuration:A.duration??0,screenshotExtMap:Le?.getExtMap(),codeExport:rr({codeExport:n.codeExport,codeLanguage:n.codeLanguage,skipCodeValidation:n.skipCodeValidation},l.code_export),onProgress:()=>{},log:(nt,Vn,Un,Bn)=>E.log(nt,Vn,Un,Bn),shouldUploadArtifacts:!n.local,shouldReplaceLocalOutput:!1,shouldCommit:!1,isFirstRun:!0,evidence:ne?{executionId:ne.executionId,packTestDir:ne.packTestDir,sealedPackPath:ne.packDir,sealFn:Yt}:void 0}),ie=await new V(me).execute();ie.success&&(ie.testcaseId&&E.setTestcaseId(ie.testcaseId),ie.testcaseId&&ie.shareId&&te&&(ee=un(L.testManagerUiUrl,te,ie.testcaseId,ie.shareId)));let pt=null;try{let{persistRecordedSession:nt}=await import("./persist-recorded-session-JXL5E53A.js");pt=await nt(E,{testcaseId:E.testcaseId??void 0,projectId:F.project_id??void 0,folderId:F.folder_id??void 0,codeExportDir:ie.codeExportDir,mobile:oe.kind==="device",packTestDir:ne?.packTestDir})}catch(nt){E.log("error","DIRECT_PERSIST_ERROR","Persist failed in agent mode",{error:String(nt)})}let{syncPersistedBundle:Xc}=await import("./testmd-sync-HYZI6NRM.js");await Xc({recordedTestPath:pt?.recordedTestPath,uploadSucceeded:ie.success,local:!!n.local,sessionId:E.sessionId,basicAuth:h.basicAuth,controllerBaseUrl:L.controllerBaseUrl,log:(nt,Vn,Un,Bn)=>E.log(nt,Vn,Un,Bn),onAgentEvent:b})}}catch(L){E.log("error","DIRECT_UPLOAD_ERROR","Upload failed in agent mode",{error:L instanceof Error?L.message:String(L)})}let U=await Yt({});if(ne&&U?.sealed){let{offerEvidenceView:L}=await import("./evidence-XJGXVLO5.js");await L({packPath:ne.packDir,env:w,isTTY:!1,log:te=>process.stderr.write(te+`
236
- `)})}if(A){let L={...A};ee&&(L.test_url=ee),b(L)}if(await E.finish("complete"),A||y(Z?2:1,"Agent run ended with no result"),c){let L=Ds(A,s.length);y(L,L===0?"Analyzer run: every condition judged":L===3?`Analyzer run: ${A.reason??""}`:"Analyzer run: some conditions could not be judged")}let Se=A.reason??"";(Se.includes("Cancel")||Se.includes("Timeout"))&&y(3,`Agent run: ${Se}`),A.status==="passed"&&y(0,"Agent run passed"),y(1,"Agent run failed")}let ue=null,Pt=0,jn=!1,zr=null,Xr=0,Qr={current:null},Gc=we?{authHeader:Yn(we.username,we.access_key),sessionId:E.sessionId,controllerBaseUrl:re(w).controllerBaseUrl}:null,{waitUntilExit:qc}=rt($r.default.createElement(ot,null,$r.default.createElement(Is,{config:Gr,describeContext:Gc,spawnOpts:{environment:w,mode:m,assertionMode:p,finalValidation:g,log:(b,T,A,j)=>E.log(b,T,A,j)},cancelRef:Qr,banner:{model:n.model??l.model,auth:R,status:S},onComplete:b=>{ue=b.lastRunEnd,Pt=b.stepsTotal,jn=b.hadError,zr=b.bifurcationFlows,Xr=b.describeCredits,Yr(ne,b.evidence,b.lastRunEnd)},onStepEnd:qr,onReasoning:b=>Oe?.setStepText(b),onStepComplete:()=>Oe?.setStepComplete()})),{stdout:process.stderr,exitOnCtrlC:!1}),Fn;if(n.timeout){let b=parseInt(n.timeout,10)*1e3;Fn=setTimeout(()=>{console.error(`
237
- Timeout: ${n.timeout}s exceeded \u2014 cancelling...`),Qr.current?.()},b)}Oe?.setRunActive(!0);try{await qc()}finally{Oe?.setRunActive(!1)}if(Fn&&clearTimeout(Fn),ue){let b=Xn(ue,0,zr);E.addRunResult(Qn(ue,ge.auteurObjective,0,b),ue.total_runs);let T=ue.status==="passed"?"passed":jn?"error":"failed";E.addFlow({runIndex:0,objective:ge.auteurObjective,status:T,summary:ue.summary??"",duration:ue.duration??0,steps:Pt,stepsPassed:T==="passed"?Pt:0,stepsFailed:T==="passed"?0:Pt,reason:ue.reason,creditsConsumed:(ue.credits_consumed??0)+Xr})}ne&&await On(),Hn("chrome","Ink run completed");{let b=m==="testing",T=E.nextRunIndex()>0;if(b&&!n.name&&T&&process.stdin.isTTY)try{let{renderSavePrompt:A,defaultSessionTimestamp:j}=await import("./SaveSessionPrompt-ATVHKAHN.js"),Z=await A(j());Z&&E.setSessionName(Z)}catch(A){E.log("warn","DIRECT_SAVE_PROMPT_FAILED","Save prompt failed",{error:String(A)})}}if(E.log("info","DIRECT_UPLOAD_START","Starting direct upload (ink mode)",{ink_mode:!0,last_event:!!ue,local:!!n.local,mobile:oe.kind==="device"}),ue&&!n.local)try{let b=re(w),T=F.project_id;if(h.basicAuth){let{UploadPipeline:A}=await import("./pipeline-RSCRNNPW.js");Le&&(E.log("info","SCREENSHOT_UPLOAD_DRAIN","Draining screenshot upload queue before pipeline"),await Nn.settle(),await Le.drain(),E.log("info","SCREENSHOT_UPLOAD_DRAINED","Screenshot upload queue drained"));let j=nr({mobile:oe.kind==="device",session:E,env:w,auth:h,variables:ge,variableIds:Wr,testParams:W?.testParams,projectId:F.project_id,folderId:F.folder_id,totalSteps:Pt,totalDuration:ue.duration??0,screenshotExtMap:Le?.getExtMap(),codeExport:rr({codeExport:n.codeExport,codeLanguage:n.codeLanguage,skipCodeValidation:n.skipCodeValidation},l.code_export),onProgress:()=>{},log:(U,Se,L,te)=>E.log(U,Se,L,te),shouldUploadArtifacts:!n.local,shouldReplaceLocalOutput:!1,shouldCommit:!1,isFirstRun:!0,evidence:ne?{executionId:ne.executionId,packTestDir:ne.packTestDir,sealedPackPath:ne.packDir,sealFn:Yt}:void 0}),Z=new A(j),{renderUploadProgress:xe}=await import("./CliUploadProgress-OAQBY55Y.js"),ee=await xe(Z,U=>{if(U.testcaseId&&U.shareId&&T)return un(b.testManagerUiUrl,T,U.testcaseId,U.shareId)});if(ee.success){ee.testcaseId&&E.setTestcaseId(ee.testcaseId);let U=null;try{let{persistRecordedSession:V}=await import("./persist-recorded-session-JXL5E53A.js");U=await V(E,{testcaseId:E.testcaseId??void 0,projectId:F.project_id??void 0,folderId:F.folder_id??void 0,codeExportDir:ee.codeExportDir,mobile:oe.kind==="device",packTestDir:ne?.packTestDir})}catch(V){E.log("error","DIRECT_PERSIST_ERROR","Persist failed in ink mode",{error:String(V)})}let{syncPersistedBundle:Se}=await import("./testmd-sync-HYZI6NRM.js");await Se({recordedTestPath:U?.recordedTestPath,uploadSucceeded:ee.success,local:!!n.local,sessionId:E.sessionId,basicAuth:h.basicAuth,controllerBaseUrl:b.controllerBaseUrl,log:(V,me,Ve,ie)=>E.log(V,me,Ve,ie)});let L=ee.testcaseId&&ee.shareId&&T?un(b.testManagerUiUrl,T,ee.testcaseId,ee.shareId):void 0,te=ee.testcaseId&&T?Ii(b.testManagerUiUrl,T,ee.testcaseId):void 0;if(L||te||ee.codeExportDir||U){let{LinksBox:V}=await import("./LinksBox-MNNNOH23.js"),{render:me}=await import("./build-JIKYOZUH.js"),Ve=await import("./react-QWOAB3TB.js"),{waitUntilExit:ie}=me(Ve.default.createElement(V,{recordedTestPath:U?.recordedTestPath,outputDir:U?.outputDir,shareableLink:L,testCaseLink:te,codeExportDir:ee.codeExportDir}),{stdout:process.stderr});await ie()}}if(E.testId){let{renderFeedbackPrompt:U}=await import("./CliFeedbackPrompt-4SILDU7S.js"),Se=await U();if(Se)try{await Xi({tmsBaseUrl:b.tmsBaseUrl,username:h.basicAuth.username,accessKey:h.basicAuth.access_key,testId:E.testId,feedbackType:Se,log:(L,te,V,me)=>E.log(L,te,V,me)})}catch(L){E.log("warn","FEEDBACK_FAILED","Feedback submission failed",{error:String(L)})}}}}catch(b){E.log("error","DIRECT_UPLOAD_FAILED","Direct upload failed (ink mode)",{error:b instanceof Error?b.stack??b.message:String(b)}),console.error(`Upload failed: ${b}`)}let zc=await Yt({});if(ne&&zc?.sealed){let{offerEvidenceView:b}=await import("./evidence-XJGXVLO5.js"),T=ue?.reason??"",A=T.includes("Cancel")||T.includes("Timeout");await b({packPath:ne.packDir,env:w,isTTY:!!process.stdin.isTTY&&!!process.stderr.isTTY&&!A,log:j=>process.stderr.write(j+`
238
- `)})}await E.finish("complete"),ue||y(jn?2:1,"Run ended with no result");let Ln=ue.reason??"";(Ln.includes("Cancel")||Ln.includes("Timeout"))&&y(3,`Run: ${Ln}`),ue.status==="passed"&&y(0,"Run passed"),y(1,"Run failed")}catch(c){await go(),y(2,`CLI error: ${c instanceof Error?c.message:String(c)}`)}}),Js(r),Ws(r),Ys(r),Hs(r),Gs(r),r.addCommand(Ec()),r.addCommand(Dc()),ws(r),t&&js(r),Mc(r),r.command("install <target> [version]").description("Install kane-cli agent skill into Claude Code / Codex CLI / Gemini CLI (version defaults to latest compatible)").action(async(o,n)=>{if(o==="plugin"){let l=n;if(!l){console.error("error: usage: kane-cli install plugin <name>"),y(2,"install plugin: missing name");return}let{installPlugin:m}=await import("./install-W3VPVPAQ.js"),p=m(l,{});if(p.status==="failed"){console.error(`error: ${p.error}`),y(/unknown plugin/i.test(p.error??"")?2:1,`install plugin: ${p.status}`);return}let{ensureHyperexecuteBinary:g}=await import("./binary-VML7EGV4.js"),u=l==="remote-execution"?await g(q):void 0;process.stdin.isTTY?(process.stderr.write(`${p.status==="already-installed"?"already installed":"installed"} ${p.name}@${p.version} \u2192 ${p.dir}
228
+ `),process.exit(2);return}let c=!!n.analyzerOnly,i=n.condition??[];{let b=Pi({analyzerOnly:c,objective:o,conditions:i,agent:!!n.agent,isTTY:!!process.stdin.isTTY,codeExport:n.codeExport,name:n.name,target:n.target,app:n.app,deviceName:n.deviceName,osVersion:n.osVersion});if(b){process.stderr.write(`error: ${b}
229
+ `),process.exit(2);return}}if(c){let b=Di(n);b.length&&process.stderr.write(`info: --analyzer-only ignores ${b.join(", ")}
230
+ `),Object.assign(n,Ai()),o=Mi(i)}o=o??"";{let{objectiveVariableGate:b}=await import("./objective-variable-gate-BCKULIFQ.js"),{formatUnresolvedReceipt:P,unresolvedVariablesEvent:A}=await import("./variable-receipt-SIABUC74.js"),N=b({objective:o,cwd:process.cwd(),globalDir:Me(z,"variables"),opts:{variables:n.variables,variablesFile:n.variablesFile,sessionContext:n.sessionContext}});N.length>0&&(!!n.agent||!process.stdin.isTTY?process.stdout.write(JSON.stringify(A(N,{cwd:process.cwd()}))+`
231
+ `):process.stderr.write(P(N,{cwd:process.cwd()})))}let a=new me,d=new Ae,l=d.load();n.chromeProfile&&(l.chrome_profile_path=n.chromeProfile);let m;if(n.mode===void 0)m=l.mode==="action"?"action":"testing";else if(n.mode==="action"||n.mode==="testing")m=n.mode;else{console.error("Invalid --mode. Must be 'action' or 'testing'."),y(2,"Invalid --mode");return}let p;if(n.assertionMode===void 0)p=l.assertion_mode==="dom"?"dom":"visual";else if(n.assertionMode==="visual"||n.assertionMode==="dom")p=n.assertionMode;else{console.error("Invalid --assertion-mode. Must be 'visual' or 'dom'."),y(2,"Invalid --assertion-mode");return}let g;if(n.finalValidation!==void 0){if(n.finalValidation!=="on"&&n.finalValidation!=="off"){console.error("Invalid --final-validation. Must be 'on' or 'off'."),y(2,"Invalid --final-validation");return}g=n.finalValidation==="on"}let u=new Mt,{printRecordingBanner:v}=await import("./recording-banner-3ET3PMSV.js");await v({isAgent:!!n.agent||!process.stdin.isTTY,sessionId:u.sessionId,sessionName:n.name??null,testPath:n.name?Me(process.cwd(),".testmuai","tests",`${n.name}_test.md`):null,outputPath:n.name?Me(process.cwd(),".testmuai","tests",`output-${n.name}`):null});let x=!!(n.username&&n.accessKey);if(await ks({isInteractive:!!process.stdin.isTTY&&!n.agent&&!x,creds:a,config:d}),!x){let b=a.getActiveProfile(),P=a.getDefaultEnv();b&&(a.loadBasicAuth(b,P)||a.loadCredentials(b,P))||(console.error("Not authenticated. Run: kane-cli login --oauth, or kane-cli login --username <user> --access-key <key>"),y(1,"Not authenticated"))}let T=`${a.getActiveProfile()??"no profile"}/${a.getDefaultEnv()}`,S=[],w=n.env??a.getDefaultEnv(),C=null,f=[],k=(b,P,A,N)=>{C?C(b,P,A,N):f.push([b,P,A,N])},h;try{h=await Be({creds:a,env:w,usernameFlag:n.username,accessKeyFlag:n.accessKey,log:k})}catch(b){throw b instanceof Ot&&(console.error(b.code==="not_authenticated"?"Not authenticated. Run: kane-cli login":"Token refresh failed. Run: kane-cli login"),y(2,b.code==="not_authenticated"?"Not authenticated":"Token refresh failed")),b}let R=!!h.basicAuth,O=h.basicAuth?.username,_=h.basicAuth?.access_key,V=h.token,I=h.resolver,L=h.resolvedCreds;h.basicAuth&&S.push(`Auth: ${h.basicAuth.username}`);let $=null;{let b=null;try{b=To({datasetId:n.datasetId,datasetRow:n.datasetRow},void 0)}catch(P){console.error(`error: ${P.message}`),y(2,P.message)}if(b){h.basicAuth||(console.error("error: --dataset-id needs Test Manager credentials \u2014 run 'kane-cli login' or pass --username/--access-key"),y(2,"dataset needs Test Manager credentials"));try{$=await Vs({selection:b,tmsBaseUrl:oe(w).tmsBaseUrl,auth:h.basicAuth,saveDir:u.sessionDir,log:(A,N,ee,Se)=>u.log(A,N,ee,Se)})}catch(A){console.error(`error: ${A.message}`),y(2,A.message)}let P=Gs([{text:o,usedBy:{file:Hs,step:1}}],$.columns,b.id);P.length>0&&(!!n.agent||!process.stdin.isTTY?process.stdout.write(JSON.stringify(gn(P,{cwd:process.cwd()}))+`
232
+ `):process.stderr.write(Nt(P,{cwd:process.cwd()})))}}let Q=a.getActiveProfile()??"default",M=a.getDefaultEnv();Ao(a,d,Q,M);let j=d.load(),H=h.basicAuth??(h.resolvedCreds?{username:h.resolvedCreds.username,access_key:h.resolvedCreds.access_key}:null);if(H){let b=!!n.agent||!process.stdin.isTTY,P=await an({creds:a,config:d,profile:Q,env:M,tmsCreds:H,isLocal:!!n.local,log:k});P.status==="cancelled"&&(console.error("error: project/folder configuration failed. See remediation above, or use --local."),y(2,"project/folder gate failed")),P.status==="ok"&&P.autoDefaulted&&b&&process.stdout.write(Mo(P.autoDefaulted)),j=d.load()}else n.local||(console.error("Project and folder must be configured. Run `kane-cli login` to set up auth, or pass --username/--access-key, then `kane-cli config project <id>` / `kane-cli config folder <id>`."),y(2,"no TMS credentials for project/folder gate"));let{resolveRunIntent:Te,formatRunningOn:Ee,missingPieceMessage:ze,staleAppMessage:se,CHOOSE_MOBILE_KIND_MESSAGE:fe}=await import("./resolve-run-intent-3SXUS676.js"),{mobileHostSupport:tt}=await import("./host-7GZPBA74.js"),{platformOf:Wt}=await import("./session-target-UWROGOCY.js"),ke=Xs()&&!n.agent,{attachTargetFromFlags:D,formatAttachBanner:we}=await import("./attach-target-V6LECVES.js"),Z=D({appiumUrl:n.appiumUrl,appiumSessionId:n.appiumSessionId,target:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app});if(Z.kind==="invalid"){console.error(`error: ${Z.message}`),y(2,"attach run not fully specified");return}let W=Z.kind==="attach"?Z.device:null,xe=Te({flags:{target:W?void 0:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app},saved:W?void 0:l.mobile,host:tt()});if(xe.kind==="choose-mobile-kind")if(ke){let{promptMobileKind:b}=await import("./mobile-prompts-PPPPKRS2.js"),P=await b();if(!P){y(2,"target selection cancelled");return}d.setMobile({tui_target:P}),xe=Te({flags:{target:P,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app},saved:d.load().mobile,host:tt()})}else{console.error(`error: ${fe}`),y(2,"ambiguous legacy session target");return}if(xe.kind==="invalid"){console.error(`error: ${xe.message}`),y(2,"invalid run target");return}if(xe.kind==="choose-mobile-kind"){y(2,"ambiguous legacy session target");return}for(let b of xe.warnings)console.error(`warning: ${b}`);let Pe=xe.kind==="mobile"?xe:null;if(Pe&&n.codeLanguage?.toLowerCase()==="javascript"){console.error("error: --code-language javascript is not supported on a mobile target \u2014 mobile code export is Appium + Python only. Drop the flag, or pass --code-language python."),y(2,"javascript code export on a mobile target");return}let ye=Pe||W?"device":"web";if(u.setCompletionMetadata({runType:"run",target:W?W.platform==="ios"?"simulator":"emulator":Pe?.target??"desktop"}),W?console.error(we(W)):Pe||console.error(Ee({target:"desktop"})),!c&&!ji({target:n.target,deviceName:n.deviceName,osVersion:n.osVersion,app:n.app,cdpEndpoint:n.cdpEndpoint,wsEndpoint:n.wsEndpoint,cft:n.cft,url:n.url})){let b=ye==="device"?"mobile":"web",P=await Eo({objective:o,sessionTarget:b,controllerBaseUrl:oe(w).controllerBaseUrl,authHeader:h.basicAuth?zn(h.basicAuth.username,h.basicAuth.access_key):`Bearer ${h.token}`}),A=Fi(Ro(P,b));A&&console.error(A),k("info","CLASSIFY_VERDICT","Objective classified",{session_target:b,target:P?.target??null,confidence:P?.confidence??null,warned:!!A})}let Ye=ye==="device"?null:hs({flag:n.url,configDefault:l.default_url}),K=ye==="device"?!1:vs({resolvedUrl:Ye,local:n.local,allowMissingUrl:n.allowMissingUrl,isTTY:!!process.stdin.isTTY}),ue=Fs({objective:o,globalDir:Me(z,"variables"),localDir:Me(process.cwd(),".testmuai","variables"),file:n.variablesFile,inline:n.variables,parameters:$?.parameters,onLoadError:b=>console.error(b)}),Yt;if(n.sessionContext)try{Yt=JSON.parse(n.sessionContext)}catch{console.error("Invalid --session-context JSON"),y(2,"Invalid --session-context JSON")}let Fn=n.globalContext??Me(z,"global-memory.md"),Yc=n.localContext??Me(process.cwd(),".testmuai","context.md"),Jr=sr(Fn),Wr=sr(Yc),Oe={},ie=await Ps(ye,{prepareDevice:async()=>{if(W)return{device:W};let b=Pe,{isAppId:P}=await import("./app-download-RA4CGTC5.js"),{access:A}=await import("fs/promises"),N=b.app?.value,ee=!1,Se=!1,te=b.app?.source==="saved"&&!P(b.app.value)?await A(b.app.value).then(()=>!1,()=>!0):!1;if(ke){if(b.missing.includes("app")||te){te&&console.error(`${b.app.value} is no longer there \u2014 choose the app under test.`);let{promptApp:U}=await import("./mobile-prompts-PPPPKRS2.js"),{AppClient:he}=await import("./app-client-ZCCNE3RV.js"),Ue=O&&_?pt=>new he(st(w),{username:O,accessKey:_}).list({type:b.target,...pt}):void 0,ae=await U({kind:b.target,...Ue?{listApps:Ue}:{}});if(!ae)throw y(2,"app selection cancelled"),new Error("app selection cancelled");N=ae,ee=!0}}else{let U=b.missing.map(he=>ze(b.target,he));if(te&&U.push(se(b.app.value,b.target)),U.length>0){for(let he of U)console.error(`error: ${he}`);y(2,"mobile run not fully specified")}}let B,Ce=yn();try{B=await _o({device:b.deviceSelector,platform:Wt(b.target),app:N,defaults:l.mobile,interactive:ke,agent:!!n.agent,appiumUrl:n.appiumUrl,...ke?{pickTarget:async U=>{let{promptDevice:he}=await import("./mobile-prompts-PPPPKRS2.js"),Ue=U.filter(pt=>pt.kind===b.target),ae=await he(Ue.length>0?Ue:U,b.target,l.mobile?.default_target);return ae&&(Se=!0),ae}}:{},...!n.local&&O&&_&&L?.org_id?{cloudUpload:{env:w,orgId:String(L.org_id),userId:String(L.user_id??""),baseUrl:st(w),auth:{username:O,accessKey:_}}}:{},onProgress:Ce.onProgress})}catch(U){Ce.done(),U instanceof Io?(console.error(U.doctorText),console.error(`
233
+ ${U.message}`)):console.error(U instanceof Error?U.message:String(U)),y(2,"mobile target preparation failed")}Ce.done(),B.device.app_package||(console.error(`error: ${ze(b.target,"app")}`),y(2,"mobile run missing app binding"));let F=b.device?.source==="flag";if(ee||Se||!F){let{deviceRefOf:U}=await import("./device-ref-LAZWPRQN.js");d.setMobile({...n.target===void 0?{tui_target:b.target}:{},...F?{}:{default_target:U(B.target)},...ee&&N?{default_app:N}:{}})}Oe.current=B;let ne=N??B.appRef??B.device.app_package??"";return Oe.appLabel=P(ne)?ne:Bu(ne),{device:B.device,...B.appRef?{appRef:B.appRef}:{},...B.appId?{appId:B.appId}:{}}},prepareWeb:async()=>{try{return await Ts({config:l,startUrl:Ye??void 0,headless:n.headless,cft:n.cft,wsEndpoint:n.wsEndpoint,cdpEndpoint:n.cdpEndpoint})}catch(b){console.error(Vo(b));let P=b instanceof Lo?"Chrome not found at standard paths":`Chrome failed: ${b instanceof Error?b.message:b}`;y(2,P)}}}),Xe=ie.kind==="web"?ie.chrome:{instance:null,tempDir:null};Xe.instance&&ht("chrome",()=>{Xe.instance.kill()});let Ne=null,Yr=Xe.cdpEndpoint??n.cdpEndpoint;if(Yr&&!n.cft&&!n.wsEndpoint&&(Ne=Yo({headless:n.headless,cdpEndpoint:Yr,chromePid:Xe.instance?.process.pid}),Ne&&ht("marker-overlay",()=>Ne.kill())),ie.kind==="device"&&Oe.current&&Pe){let b=Ee({target:Pe.target,deviceLabel:Oe.current.target.displayName,appLabel:Oe.appLabel??""});ke||console.error(b),S.push(b)}else n.cft?S.push("CfT mode: Playwright will manage its own browser"):n.wsEndpoint?S.push(`Playwright WS endpoint (${n.wsEndpoint.slice(0,60)}...)`):n.cdpEndpoint?S.push(`CDP connected (${n.cdpEndpoint})`):Xe.cdpEndpoint&&S.push(`Chrome ready (${Xe.cdpEndpoint})`);let E=u;E.start({model:n.model??l.model,environment:w,profile:a.getActiveProfile()}),!n.local&&h.resolvedCreds?.user_id!==void 0&&E.setCompletionIdentity(Number(h.resolvedCreds.user_id)),n.name&&E.setSessionName(n.name),h.resolvedCreds?.org_id!==void 0&&E.setOrgId(String(h.resolvedCreds.org_id)),h.resolvedCreds?.plan!==void 0&&E.setPlan(h.resolvedCreds.plan??null),E.setUserIdentity(h.resolvedCreds?.username??null,h.resolvedCreds?.email??null),C=(b,P,A,N)=>E.log(b,P,A,N);for(let b of f)E.log(...b);f.length=0;let Hr=R&&O&&_?{username:O,accessKey:_}:V??null,Ve=null;if(Hr!==null){let b=await Js({env:w,tmsCreds:h.resolvedCreds??null,resolver:h.resolver,auth:Hr,getToken:async()=>h.token??null,session:E,log:(P,A,N,ee)=>E.log(P,A,N,ee),skipScreenshotQueue:n.local,invocationMode:n.agent||!process.stdin.isTTY?"agent":"cli"});Ve=b.screenshotQueue,b.remoteLogger&&(ht("remote-logger",()=>b.remoteLogger.shutdownSync()),go(b.remoteLogger),fo(no))}let Gr=h.basicAuth&&!n.local?await Ls({variables:ue,auth:h.basicAuth,orgId:String(h.resolvedCreds?.org_id??""),env:w,localMode:!!n.local,log:(b,P,A,N)=>E.log(b,P,A,N)}):{};E.setAuteurVariables(ue.auteur),E.setFirstRun(ue.auteurObjective,Ye??"");let{startInlineEvidence:Hc,noteInlineSpawn:qr,inlineEvidenceBlock:Gc,finalizeInlineEvidence:qc,createCdpBrowserCapture:zc}=await import("./evidence-KRNDKDCT.js"),Ln=zc(Xe.cdpEndpoint),re=c?null:await Hc({objectiveOrName:n.name??o,sessionId:E.sessionId,title:n.name??o,producerVersion:be,pid:process.pid,surfaces:Ye?[Ye]:void 0,packRootDir:Me(E.sessionDir,"evidence")}),Ht=async(b={})=>(E.flushRecorder(),await qc(re,{saved:!!E.sessionName,local:!!n.local,deviceName:Oe.current?.target.displayName,deviceModel:Oe.current?.target.modelIdentifier,recordedTestPath:E.recorder?.lastWrittenPath??null,externalIdInput:{...$?$.externalId:{},session_id:E.sessionId,commit_id:E.sessionId,test_id:E.testId??void 0,testcase_id:b.testcaseId??E.testcaseId??void 0,project_id:j.project_id??void 0,folder_id:j.folder_id??void 0,org_id:E.orgId??void 0,session_name:E.sessionName??void 0,user_name:E.userName??void 0,user_email:E.userEmail??void 0,sharable_link:Es(oe(w).testManagerUiUrl,j.project_id,b.testcaseId??E.testcaseId,b.shareId)},cdpBrowserCapture:Ln,model:n.model??l.model,tuiLogPath:Me(E.sessionDir,"tui.log"),log:(P,A,N,ee)=>E.log(P,A,N,ee)}));if(!n.local&&h.basicAuth&&j.project_id){let b=oe(w),P=await Bs({tmsBaseUrl:b.tmsBaseUrl,auth:h.basicAuth,objective:ue.auteurObjective,url:Ye??"",projectId:j.project_id,folderId:j.folder_id??"",hasCustomProfile:!!l.chrome_profile_path,...ie.kind==="device"?{mobile:Us({platform:ie.device.platform,appId:ie.appId,deviceName:Oe.current?.target.displayName,osVersion:Oe.current?.target.osVersion,udid:ie.device.udid})}:{},log:(A,N,ee,Se)=>E.log(A,N,ee,Se)});P&&E.setTestId(P)}E.setResolvedGlobal({mode:m,max_steps:parseInt(n.maxSteps,10),timeout:n.timeout?parseInt(n.timeout,10):void 0,target:As(ie,{cdpEndpoint:n.cdpEndpoint,wsEndpoint:n.wsEndpoint}),app:$s(ie),os_version:ie.kind==="device"?Oe.current?.target.osVersion:void 0,device_name:Ds(ie,Oe.current?.target),chrome_profile:l.chrome_profile_path||void 0,cdp_endpoint:n.cdpEndpoint||void 0,ws_endpoint:n.wsEndpoint||void 0,headless:n.headless,global_context:Jr??void 0,local_context:Wr??void 0,variables:Object.keys(er(ue.auteur)).length>0?er(ue.auteur):void 0,dataset:$?Po($.selection.id,$.rowId):void 0});let zr=js(ue.auteur,ue.auteurObjective),Xr=Os({objective:ue.auteurObjective,conditions:c?Oi(ue.auteurObjective,i.length):void 0,url:Ye??void 0,requireStartUrl:K,model:n.model??l.model,chrome:Xe,auth:h,sessionId:E.sessionId,runIndex:0,windowSize:l.window_size,maxSteps:parseInt(n.maxSteps,10),headless:n.headless,disableAskUser:!process.stdin.isTTY,enableTaskSkills:n.taskSkills,networkWs:n.networkWs,networkSse:n.networkSse,bugDetection:n.bugDetection??l.bug_detection,variables:Object.keys(zr).length>0?zr:void 0,globalContext:Jr??void 0,localContext:Wr??void 0,sessionContext:Yt,device:ie.kind==="device"?ie.device:void 0,evidence:Gc(re)}),Vn=ms(),Qr=Ve?(b,P,A,N)=>{if(re&&N){Vn.track(ps(re.packTestDir,N,Ve,(ee,Se,te,B)=>E.log(ee,Se,te,B)));return}fs(E.sessionDir,P,b,Ve,(ee,Se,te,B)=>E.log(ee,Se,te,B),A)}:void 0;if(!process.stdin.isTTY&&!n.agent&&(n.agent=!0),n.agent){let b=F=>{process.stdout.write(JSON.stringify(F)+`
234
+ `)};Ne?.setRunActive(!0);let P;try{P=await Ti(Xr,{environment:w,mode:m,assertionMode:p,finalValidation:g,log:(F,ne,U,he)=>E.log(F,ne,U,he)},{onStepEnd:Qr,onStepLog:(F,ne,U)=>E.logStep(F,ne,U),onReasoning:F=>Ne?.setStepText(F),onStepComplete:()=>Ne?.setStepComplete(),kind:c?"evaluate":"author",timeoutSeconds:c&&n.timeout?parseInt(n.timeout,10):void 0,onTimeout:()=>process.stderr.write(`Timeout: ${n.timeout}s exceeded \u2014 stopping the analyzer run
235
+ `)})}finally{Ne?.setRunActive(!1)}let{lastRunEnd:A,stepsTotal:N,hadError:ee,bifurcationFlows:Se}=P;if(c&&P.timedOut&&(b({type:"run_end",status:"failed",run_id:"run-0",reason:`Timeout: ${n.timeout}s exceeded`,condition_results:i.map(()=>null),condition_reasons:i.map(()=>"timed out before a verdict"),condition_sub_checks:i.map(()=>null)}),await E.finish("complete"),y(3,`Analyzer run: Timeout after ${n.timeout}s`)),qr(re,P.evidence,A),ee&&E.escalateRun(0),A){let F=tr(A,0,Se);E.addRunResult(nr(A,ue.auteurObjective,0,F),A.total_runs);let ne=A.status==="passed"?"passed":ee?"error":"failed";E.addFlow({runIndex:0,objective:ue.auteurObjective,status:ne,summary:A.summary??"",duration:A.duration??0,steps:N,stepsPassed:ne==="passed"?N:0,stepsFailed:ne==="passed"?0:N,reason:A.reason,creditsConsumed:A.credits_consumed})}re&&await Ln(),Xn("chrome","Agent run completed");let te;if(E.log("info","DIRECT_UPLOAD_START","Starting direct upload (agent mode)",{agent_mode:!0,last_run_end:!!A,local:!!n.local,mobile:ie.kind==="device"}),A&&!n.local)try{let F=oe(w),ne=j.project_id;if(h.basicAuth){let{UploadPipeline:U}=await import("./pipeline-XDWHEZ5S.js");Ve&&(await Vn.settle(),await Ve.drain());let he=ir({mobile:ie.kind==="device",session:E,env:w,auth:h,variables:ue,variableIds:Gr,testParams:$?.testParams,projectId:ne,folderId:j.folder_id,totalSteps:N,totalDuration:A.duration??0,screenshotExtMap:Ve?.getExtMap(),codeExport:ar({codeExport:n.codeExport,codeLanguage:n.codeLanguage,skipCodeValidation:n.skipCodeValidation},l.code_export),onProgress:()=>{},log:(nt,Jn,Wn,Yn)=>E.log(nt,Jn,Wn,Yn),shouldUploadArtifacts:!n.local,shouldReplaceLocalOutput:!1,shouldCommit:!1,isFirstRun:!0,evidence:re?{executionId:re.executionId,packTestDir:re.packTestDir,sealedPackPath:re.packDir,sealFn:Ht}:void 0}),ae=await new U(he).execute();ae.success&&(ae.testcaseId&&E.setTestcaseId(ae.testcaseId),ae.testcaseId&&ae.shareId&&ne&&(te=fn(F.testManagerUiUrl,ne,ae.testcaseId,ae.shareId)));let pt=null;try{let{persistRecordedSession:nt}=await import("./persist-recorded-session-MK4HCDOY.js");pt=await nt(E,{testcaseId:E.testcaseId??void 0,projectId:j.project_id??void 0,folderId:j.folder_id??void 0,codeExportDir:ae.codeExportDir,mobile:ie.kind==="device",packTestDir:re?.packTestDir})}catch(nt){E.log("error","DIRECT_PERSIST_ERROR","Persist failed in agent mode",{error:String(nt)})}let{syncPersistedBundle:el}=await import("./testmd-sync-2CXNIPJ7.js");await el({recordedTestPath:pt?.recordedTestPath,uploadSucceeded:ae.success,local:!!n.local,sessionId:E.sessionId,basicAuth:h.basicAuth,controllerBaseUrl:F.controllerBaseUrl,log:(nt,Jn,Wn,Yn)=>E.log(nt,Jn,Wn,Yn),onAgentEvent:b})}}catch(F){E.log("error","DIRECT_UPLOAD_ERROR","Upload failed in agent mode",{error:F instanceof Error?F.message:String(F)})}let B=await Ht({});if(re&&B?.sealed){let{offerEvidenceView:F}=await import("./evidence-KRNDKDCT.js");await F({packPath:re.packDir,env:w,isTTY:!1,log:ne=>process.stderr.write(ne+`
236
+ `)})}if(A){let F={...A};te&&(F.test_url=te),b(F)}if(await E.finish("complete"),A||y(ee?2:1,"Agent run ended with no result"),c){let F=Ni(A,i.length);y(F,F===0?"Analyzer run: every condition judged":F===3?`Analyzer run: ${A.reason??""}`:"Analyzer run: some conditions could not be judged")}let Ce=A.reason??"";(Ce.includes("Cancel")||Ce.includes("Timeout"))&&y(3,`Agent run: ${Ce}`),A.status==="passed"&&y(0,"Agent run passed"),y(1,"Agent run failed")}let ge=null,Pt=0,Un=!1,Zr=null,eo=0,to={current:null},Xc=H?{authHeader:zn(H.username,H.access_key),sessionId:E.sessionId,controllerBaseUrl:oe(w).controllerBaseUrl}:null,{waitUntilExit:Qc}=rt(jr.default.createElement(ot,null,jr.default.createElement(Ri,{config:Xr,describeContext:Xc,spawnOpts:{environment:w,mode:m,assertionMode:p,finalValidation:g,log:(b,P,A,N)=>E.log(b,P,A,N)},cancelRef:to,banner:{model:n.model??l.model,auth:T,status:S},onComplete:b=>{ge=b.lastRunEnd,Pt=b.stepsTotal,Un=b.hadError,Zr=b.bifurcationFlows,eo=b.describeCredits,qr(re,b.evidence,b.lastRunEnd)},onStepEnd:Qr,onReasoning:b=>Ne?.setStepText(b),onStepComplete:()=>Ne?.setStepComplete()})),{stdout:process.stderr,exitOnCtrlC:!1}),Bn;if(n.timeout){let b=parseInt(n.timeout,10)*1e3;Bn=setTimeout(()=>{console.error(`
237
+ Timeout: ${n.timeout}s exceeded \u2014 cancelling...`),to.current?.()},b)}Ne?.setRunActive(!0);try{await Qc()}finally{Ne?.setRunActive(!1)}if(Bn&&clearTimeout(Bn),ge){let b=tr(ge,0,Zr);E.addRunResult(nr(ge,ue.auteurObjective,0,b),ge.total_runs);let P=ge.status==="passed"?"passed":Un?"error":"failed";E.addFlow({runIndex:0,objective:ue.auteurObjective,status:P,summary:ge.summary??"",duration:ge.duration??0,steps:Pt,stepsPassed:P==="passed"?Pt:0,stepsFailed:P==="passed"?0:Pt,reason:ge.reason,creditsConsumed:(ge.credits_consumed??0)+eo})}re&&await Ln(),Xn("chrome","Ink run completed");{let b=m==="testing",P=E.nextRunIndex()>0;if(b&&!n.name&&P&&process.stdin.isTTY)try{let{renderSavePrompt:A,defaultSessionTimestamp:N}=await import("./SaveSessionPrompt-MKAIUVX7.js"),ee=await A(N());ee&&E.setSessionName(ee)}catch(A){E.log("warn","DIRECT_SAVE_PROMPT_FAILED","Save prompt failed",{error:String(A)})}}if(E.log("info","DIRECT_UPLOAD_START","Starting direct upload (ink mode)",{ink_mode:!0,last_event:!!ge,local:!!n.local,mobile:ie.kind==="device"}),ge&&!n.local)try{let b=oe(w),P=j.project_id;if(h.basicAuth){let{UploadPipeline:A}=await import("./pipeline-XDWHEZ5S.js");Ve&&(E.log("info","SCREENSHOT_UPLOAD_DRAIN","Draining screenshot upload queue before pipeline"),await Vn.settle(),await Ve.drain(),E.log("info","SCREENSHOT_UPLOAD_DRAINED","Screenshot upload queue drained"));let N=ir({mobile:ie.kind==="device",session:E,env:w,auth:h,variables:ue,variableIds:Gr,testParams:$?.testParams,projectId:j.project_id,folderId:j.folder_id,totalSteps:Pt,totalDuration:ge.duration??0,screenshotExtMap:Ve?.getExtMap(),codeExport:ar({codeExport:n.codeExport,codeLanguage:n.codeLanguage,skipCodeValidation:n.skipCodeValidation},l.code_export),onProgress:()=>{},log:(B,Ce,F,ne)=>E.log(B,Ce,F,ne),shouldUploadArtifacts:!n.local,shouldReplaceLocalOutput:!1,shouldCommit:!1,isFirstRun:!0,evidence:re?{executionId:re.executionId,packTestDir:re.packTestDir,sealedPackPath:re.packDir,sealFn:Ht}:void 0}),ee=new A(N),{renderUploadProgress:Se}=await import("./CliUploadProgress-MI4H4LKT.js"),te=await Se(ee,B=>{if(B.testcaseId&&B.shareId&&P)return fn(b.testManagerUiUrl,P,B.testcaseId,B.shareId)});if(te.success){te.testcaseId&&E.setTestcaseId(te.testcaseId);let B=null;try{let{persistRecordedSession:U}=await import("./persist-recorded-session-MK4HCDOY.js");B=await U(E,{testcaseId:E.testcaseId??void 0,projectId:j.project_id??void 0,folderId:j.folder_id??void 0,codeExportDir:te.codeExportDir,mobile:ie.kind==="device",packTestDir:re?.packTestDir})}catch(U){E.log("error","DIRECT_PERSIST_ERROR","Persist failed in ink mode",{error:String(U)})}let{syncPersistedBundle:Ce}=await import("./testmd-sync-2CXNIPJ7.js");await Ce({recordedTestPath:B?.recordedTestPath,uploadSucceeded:te.success,local:!!n.local,sessionId:E.sessionId,basicAuth:h.basicAuth,controllerBaseUrl:b.controllerBaseUrl,log:(U,he,Ue,ae)=>E.log(U,he,Ue,ae)});let F=te.testcaseId&&te.shareId&&P?fn(b.testManagerUiUrl,P,te.testcaseId,te.shareId):void 0,ne=te.testcaseId&&P?Rs(b.testManagerUiUrl,P,te.testcaseId):void 0;if(F||ne||te.codeExportDir||B){let{LinksBox:U}=await import("./LinksBox-QOQJ3S2I.js"),{render:he}=await import("./build-JIKYOZUH.js"),Ue=await import("./react-QWOAB3TB.js"),{waitUntilExit:ae}=he(Ue.default.createElement(U,{recordedTestPath:B?.recordedTestPath,outputDir:B?.outputDir,shareableLink:F,testCaseLink:ne,codeExportDir:te.codeExportDir}),{stdout:process.stderr});await ae()}}if(E.testId){let{renderFeedbackPrompt:B}=await import("./CliFeedbackPrompt-K4IN7S6J.js"),Ce=await B();if(Ce)try{await ti({tmsBaseUrl:b.tmsBaseUrl,username:h.basicAuth.username,accessKey:h.basicAuth.access_key,testId:E.testId,feedbackType:Ce,log:(F,ne,U,he)=>E.log(F,ne,U,he)})}catch(F){E.log("warn","FEEDBACK_FAILED","Feedback submission failed",{error:String(F)})}}}}catch(b){E.log("error","DIRECT_UPLOAD_FAILED","Direct upload failed (ink mode)",{error:b instanceof Error?b.stack??b.message:String(b)}),console.error(`Upload failed: ${b}`)}let Zc=await Ht({});if(re&&Zc?.sealed){let{offerEvidenceView:b}=await import("./evidence-KRNDKDCT.js"),P=ge?.reason??"",A=P.includes("Cancel")||P.includes("Timeout");await b({packPath:re.packDir,env:w,isTTY:!!process.stdin.isTTY&&!!process.stderr.isTTY&&!A,log:N=>process.stderr.write(N+`
238
+ `)})}await E.finish("complete"),ge||y(Un?2:1,"Run ended with no result");let Kn=ge.reason??"";(Kn.includes("Cancel")||Kn.includes("Timeout"))&&y(3,`Run: ${Kn}`),ge.status==="passed"&&y(0,"Run passed"),y(1,"Run failed")}catch(c){await bo(),y(2,`CLI error: ${c instanceof Error?c.message:String(c)}`)}}),Gi(r),qi(r),zi(r),Xi(r),Qi(r),r.addCommand(Ac()),r.addCommand(Nc()),Si(r),t&&Ui(r),Fc(r),r.command("install <target> [version]").description("Install kane-cli agent skill into Claude Code / Codex CLI / Gemini CLI (version defaults to latest compatible)").action(async(o,n)=>{if(o==="plugin"){let l=n;if(!l){console.error("error: usage: kane-cli install plugin <name>"),y(2,"install plugin: missing name");return}let{installPlugin:m}=await import("./install-47CRHVU6.js"),p=m(l,{});if(p.status==="failed"){console.error(`error: ${p.error}`),y(/unknown plugin/i.test(p.error??"")?2:1,`install plugin: ${p.status}`);return}let{ensureHyperexecuteBinary:g}=await import("./binary-OFPMBJ34.js"),u=l==="remote-execution"?await g(z):void 0;process.stdin.isTTY?(process.stderr.write(`${p.status==="already-installed"?"already installed":"installed"} ${p.name}@${p.version} \u2192 ${p.dir}
239
239
  `),u&&(u.status==="failed"?process.stderr.write(`\u26A0 hyperexecute binary download failed (${u.error}) \u2014 re-run \`kane-cli install plugin ${p.name}\`
240
240
  `):process.stderr.write(`\u2713 hyperexecute binary ${u.status} \u2192 ${u.path}
241
241
  `)),process.stderr.write(`run \`kane-cli plugin doctor ${p.name}\` to check readiness for --remote
242
242
  `)):process.stdout.write(JSON.stringify({type:"plugin_install_result",status:p.status,name:p.name,version:p.version,dir:p.dir,error:p.error,binary:u})+`
243
- `),y(0,`install plugin: ${p.status}`);return}if(o!=="skill"){console.error(`error: unknown install target '${o}'. Supported: skill, plugin`),y(2,`unknown install target '${o}'`);return}let{installSkill:c,formatInstallResult:s}=await import("./skill-installer-CVJ5VTEJ.js"),a=await c(n);!process.stdin.isTTY?process.stdout.write(JSON.stringify({type:"skill_install_result",status:a.status,version:a.version,installed_targets:a.installedTargets,error:a.error})+`
244
- `):process.stderr.write(s(a)+`
245
- `),y(a.status==="failed"?1:0,`install skill: ${a.status}`)}),r.command("profiles [action] [name]").description("Manage auth profiles (list | switch | delete)").option("--env <name>","Environment for switch/delete").action(async(o,n,c)=>{let s=new le;if(o==="list"||!o&&!process.stdin.isTTY){let m=s.listProfiles();if(m.length===0){console.log("No profiles configured. Run: kane-cli login");return}let p=s.getActiveProfile(),g=s.getDefaultEnv();for(let u of m){let v=u.profile===p&&u.env===g?" (active)":"";console.log(`${u.profile} [${u.env}]${v}`)}return}if(o==="switch"&&n){let m=c?.env??s.getDefaultEnv();s.setActiveProfile(n),s.setDefaultEnv(m),nn(s,new Te,n,m),console.log(`Switched to ${n} [${m}]`);return}if(o==="delete"&&n){let m=c?.env??s.getDefaultEnv();s.deleteProfileFull(n,m),console.log(`Deleted profile ${n} [${m}]`);return}process.stdin.isTTY||(console.error("Usage: kane-cli profiles list|switch|delete <name> [--env <env>]"),y(1,"Invalid profiles usage"));let{ProfilesView:a}=await import("./ProfilesView-GY5QCIT3.js"),{render:d}=await import("./build-JIKYOZUH.js"),l=await import("./react-QWOAB3TB.js");await new Promise(m=>{let{unmount:p}=d(l.default.createElement(a,{creds:s,onSwitch:(g,u)=>{s.setActiveProfile(g),s.setDefaultEnv(u),console.log(`Switched to ${g} [${u}]`)},onCancel:()=>{p(),m()}}))})}),r.command("feedback").description("Send thumbs-up/down feedback for a completed test run").requiredOption("--test-id <id>","Test ID").requiredOption("--feedback-type <type>","Feedback type: positive or negative").option("--details <text>","Feedback details (max 500 characters)").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").action(async o=>{o.feedbackType!=="positive"&&o.feedbackType!=="negative"&&(console.error('Error: --feedback-type must be "positive" or "negative"'),y(1,'Invalid --feedback-type (must be "positive" or "negative")')),o.details&&o.details.length>500&&(console.error("Error: --details must be 500 characters or fewer"),y(1,"--details exceeds 500 character limit"));let n=new le,c=o.env??n.getDefaultEnv(),s=re(c),a,d;try{let l=await Ue({creds:n,env:c,usernameFlag:o.username,accessKeyFlag:o.accessKey,log:()=>{}});a=l.resolvedCreds?.username??l.basicAuth?.username,d=l.resolvedCreds?.access_key??l.basicAuth?.access_key}catch{console.error("Not authenticated. Run: kane-cli login"),y(2,"Not authenticated for feedback")}(!a||!d)&&(console.error(JSON.stringify({error:"Could not resolve TMS credentials"})),y(1,"Could not resolve TMS credentials for feedback"));try{let{TmsClient:l}=await import("./tms-client-V3TR4QW3.js"),p=await new l(s.tmsBaseUrl,a,d).submitFeedback({instruction_id:"",test_id:o.testId,feedback_type:o.feedbackType,details:o.details,mode:"agent"});console.log(JSON.stringify(p)),y(0,"Feedback submitted")}catch(l){console.error(JSON.stringify({error:l instanceof Error?l.message:String(l)})),y(1,`Feedback failed: ${l instanceof Error?l.message:String(l)}`)}}),r.command("balance").description("Check credit balance").option("--profile <name>","Profile name").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").action(async o=>{let n=new le,c=o.env??n.getDefaultEnv(),s=re(c),a=null;try{let d=await Ue({creds:n,env:c,usernameFlag:o.username,accessKeyFlag:o.accessKey,log:()=>{}}),l=d.resolvedCreds??(d.basicAuth?{username:d.basicAuth.username,access_key:d.basicAuth.access_key}:null);l&&(a={username:l.username,accessKey:l.access_key})}catch{console.error(`Not authenticated [${c}]. Run "kane-cli login" first.`),y(2,`Not authenticated for balance [${c}]`)}a||(console.error(`Could not resolve credentials [${c}]. Run "kane-cli login" again.`),y(2,`Could not resolve credentials for balance [${c}]`));try{let{ControllerClient:d}=await import("./controller-client-ZF5IXRUV.js"),m=await new d(s.controllerBaseUrl,a).getCreditBalance();console.log(`Available credits: ${m.available_credits}`),console.log(`Total credits: ${m.total_credits}`),y(0,"Balance retrieved")}catch(d){console.error(`Error: ${d instanceof Error?d.message:String(d)}`),y(1,`Balance check failed: ${d instanceof Error?d.message:String(d)}`)}}),r.command("generate").description("Generate TCG test cases (TUI when interactive; NDJSON/plain when piped, --agent, --refine, or --save)").argument("[objective]",'Generation prompt (e.g. "checkout flow on staging"). Required for new + --refine; omit for --save.').option("--refine","Refine an existing request with <objective>. Requires --req.").option("--save","Save an existing request to disk. Requires --req; --out optional (defaults to <cwd>/.testmuai/tests). Takes no objective.").option("--req <id>","The request id to --refine or --save.").option("--out <dir>","Save target dir (only with --save; default <cwd>/.testmuai/tests).").option("--agent","Emit typed NDJSON on stdout (auto-on when stdin is not a TTY)").option("--name <name>","Name for this generation: sets the session name (like run/testmd) AND the --save suite folder (overrides the auto-derived name)").option("--scenario-limit <n>","Max number of scenarios to generate (1-20)").option("--per-scenario-limit <n>","Max test cases per scenario (1-20)").option("--memory","Enable memory enhancement for generation").option("--project <id>","TMS project id (default: org/config default)").option("--folder <id>","TMS folder id").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").option("--files <paths>","Comma-separated local files to attach (allowlisted types, \u226450MB each, \u226410; new/refine only)").action(async(o,n)=>{let c=n.scenarioLimit?parseInt(n.scenarioLimit,10):void 0,s=n.perScenarioLimit?parseInt(n.perScenarioLimit,10):void 0,{decideGenerateMode:a,resolveGenerateOp:d,defaultOutDir:l,buildHeadlessDeps:m,runGenerateHeadless:p,parseFilesFlag:g}=await import("./generate-headless-XGRIDD6O.js"),u=d({objective:o,refine:n.refine,save:n.save,req:n.req,out:n.out});if("error"in u){process.stderr.write(`error: ${u.error}
246
- `),y(2,`generate: ${u.error}`);return}let v=u.op,k=g(n.files);if(v==="save"&&k){process.stderr.write(`error: --files is not valid with --save
247
- `),y(2,"generate: --files not valid with --save");return}let{headless:R,mode:S}=a(n,!!process.stdin.isTTY);if(!R){let{runGenerate:f}=await import("./tcg-generate-2BOPGRM6.js");await f({objective:o,scenarioLimit:c,perScenarioLimit:s});return}let w=await m({mode:S,env:n.env,projectId:n.project,folderId:n.folder,username:n.username,accessKey:n.accessKey,name:n.name}),I=await p({op:v,objective:o,reqId:n.req,outDir:v==="save"?n.out?Vu(process.cwd(),n.out):l():void 0,suiteName:n.name,scenarioLimit:c,perScenarioLimit:s,memory:n.memory,files:k},w);y(I,"generate complete")}),r.command("changelog").description("Show recent release notes").option("--all","Show all releases instead of latest 5").action(async o=>{let{fetchChangelog:n,formatChangelog:c}=await import("./changelog-CJFWGRIL.js"),s=await n({all:o.all});console.log(c(s))}),r.addCommand(Bu()),r}async function Kt(e){let t=Uu(),r=["node","kane-cli",...e];if(!bn(e)){t.parse(r);return}let{parseAsAgent:i,streamVerbFor:o}=await import("./agent-parse-XMWVKCRD.js"),n=await i(t,r,o(e));n!==null&&process.exit(n)}function Bu(){let e=new ct("evidence").description("Evidence pack operations");return e.command("validate").argument("<target>","execution id, pack dir, or sealed .evidence").option("--profile <profile>","L0 | L1","L1").option("--json","machine-readable",!1).action(async(t,r)=>{let{runEvidenceValidate:i}=await import("./evidence-XJGXVLO5.js");process.exitCode=await i(t,{profile:r.profile,json:r.json})}),e.command("serve").argument("<paths...>","sealed .evidence file(s) to serve to the hosted viewer").option("--port <n>","pin the local port (default: ephemeral)",t=>parseInt(t,10)).option("--viewer-url <base>","override the hosted viewer base URL").option("--env <name>","environment (prod or stage)").action(async(t,r)=>{let{runEvidenceServe:i}=await import("./evidence-XJGXVLO5.js"),{CredentialsManager:o}=await import("./credentials-GWLYYRTL.js"),n=r.env??new o().getDefaultEnv()??"prod";process.exitCode=await i(t,{port:r.port,viewerUrl:r.viewerUrl,env:n})}),e.command("merge").argument("<targets...>","execution ids or pack paths (order-significant)").option("--run-id <id>","run_id for the merged pack (required \u2014 identity is the caller's fact)").option("-o, --out <path>","output path (default: .testmuai/evidence/<run-id>.evidence)").option("--rules <path>","merge-rules.yaml (replaces the kane defaults wholesale)").option("--on-collision <action>","error | prefer-first | prefer-latest | discard").option("--title <title>","merged run title (default: first eligible pack's)").option("--no-finalize","keep the merged pack live instead of sealing it").option("--json","machine-readable MergeReport",!1).option("--env <name>","environment (prod or stage)").action(async(t,r)=>{let{runEvidenceMerge:i}=await import("./evidence-XJGXVLO5.js"),{CredentialsManager:o}=await import("./credentials-GWLYYRTL.js"),n=r.env??new o().getDefaultEnv()??"prod";process.exitCode=await i(t,{runId:r.runId,out:r.out,rules:r.rules,onCollision:r.onCollision,title:r.title,finalize:r.finalize,json:r.json,env:n})}),e}function Oc(e){let t,r,i,o=[];for(let n=0;n<e.length;n++){let c=e[n];if(c==="--code-export")t=!0;else if(c==="--skip-code-validation"){let s=e[n+1]?.toLowerCase();s==="true"||s==="false"?(i=s==="true",n++):i=!0}else if(c==="--skip-code-validation=true"||c==="--skip-code-validation=false")i=c.endsWith("=true");else if(c==="--no-skip-code-validation")i=!1;else if(c==="--code-language"){let s=e[n+1];s!==void 0&&(r=s,n++)}else c.startsWith("--code-language=")?r=c.slice(16):o.push(c)}return{codeExport:t,codeLanguage:r,skipCodeValidation:i,filteredArgs:o}}function Nc(e){return e[0]==="run"?!0:(e[0]==="testmd"||e[0]==="testrun")&&e[1]==="run"}function Mr(e,t){let r=e[0];if(r!=="run"&&!(r==="testmd"&&e[1]==="run"))return e;let i=[...e];return t.codeExport&&i.push("--code-export"),t.codeLanguage&&i.push("--code-language",t.codeLanguage),t.skipCodeValidation===!0&&i.push("--skip-code-validation"),t.skipCodeValidation===!1&&i.push("--no-skip-code-validation"),i}function Pn(e,t){let r=e.split(".").map(o=>Number(o)||0),i=t.split(".").map(o=>Number(o)||0);for(let o=0;o<3;o++){let n=r[o]??0,c=i[o]??0;if(n<c)return-1;if(n>c)return 1}return 0}var Ku=[{version:"0.2.11",description:"Code export is now enabled by default (Python remains the default language; JavaScript is also available). Default run mode is now 'testing'.",apply:e=>{let t=[];return e.code_export.enabled===!1&&t.push({field:"code_export.enabled",from:!1,to:!0,description:"Code export is now enabled by default."}),e.mode==="action"&&t.push({field:"mode",from:"action",to:"testing",description:"Default run mode is now 'testing'."}),{cfg:{...e,code_export:{...e.code_export,enabled:!0},mode:"testing"},changes:t}}},{version:"0.5.1",description:"Assertions now read the DOM first (falling back to vision when the value isn't in the DOM). Default assertion mode is now 'dom'.",apply:e=>{let t=[];return e.assertion_mode==="visual"&&t.push({field:"assertion_mode",from:"visual",to:"dom",description:"Default assertion mode is now 'dom' (DOM-first, vision fallback)."}),{cfg:{...e,assertion_mode:"dom"},changes:t}}}];function jc(e,t=he,r=Ku){let i=e.exists(),o=e.load();if(!i)return e.set("last_seen_version",t),{changes:[],fromVersion:t,toVersion:t,appliedVersions:[]};let n=o.last_seen_version||"0.0.0";if(Pn(n,t)>=0)return{changes:[],fromVersion:n,toVersion:n,appliedVersions:[]};let c=r.filter(m=>Pn(n,m.version)<0&&Pn(m.version,t)<=0).sort((m,p)=>Pn(m.version,p.version)),s=o,a=[],d=[];for(let m of c){let{cfg:p,changes:g}=m.apply(s);s=p,a.push(...g),d.push(m.version)}let l={...s,last_seen_version:t};return e.writeRaw(l),{changes:a,fromVersion:n,toVersion:t,appliedVersions:d}}function Fc(e){return e.changes.length===0?"":[`kane-cli updated to ${e.toVersion}. Default settings changed:`,...e.changes.map(r=>` \u2022 ${r.description} (${r.field}: ${JSON.stringify(r.from)} \u2192 ${JSON.stringify(r.to)})`),"","Use /config to review or revert any of these."].join(`
248
- `)}vo();ii(he);xs();ys();var Uc=fn().catch(()=>null),Ju=gn().catch(()=>null);ci(void 0,po);var An=null,Lr=()=>An||(An=jc(new Te),An),$n=de.argv.slice(2),Wu=$n.includes("--dev"),Or=$n.includes("--local"),Yu=$n.includes("--tui");Wu&&(de.env.KANE_DEV_MODE="1");var Hu=$n.filter(e=>!["--dev","--local","--tui"].includes(e));function Gu(e){let t=[],r;for(let i=0;i<e.length;i++){let o=e[i];if(o==="--name"&&i+1<e.length){r=e[i+1],i++;continue}if(o.startsWith("--name=")){r=o.slice(7);continue}t.push(o)}return{name:r,rest:t}}var Mn=Oc(Hu),Je=Mn.filteredArgs,Nr=Mn.codeExport,jr=Mn.codeLanguage,Fr=Mn.skipCodeValidation,Dn=Bs([{promise:Uc,line:e=>{let t=e;return`
249
- Update available: ${t.current} \u2192 ${t.latest} \u2014 run \`${Qi()}\` to update
243
+ `),y(0,`install plugin: ${p.status}`);return}if(o!=="skill"){console.error(`error: unknown install target '${o}'. Supported: skill, plugin`),y(2,`unknown install target '${o}'`);return}let{installSkill:c,formatInstallResult:i}=await import("./skill-installer-CAO2NJZP.js"),a=await c(n);!process.stdin.isTTY?process.stdout.write(JSON.stringify({type:"skill_install_result",status:a.status,version:a.version,installed_targets:a.installedTargets,error:a.error})+`
244
+ `):process.stderr.write(i(a)+`
245
+ `),y(a.status==="failed"?1:0,`install skill: ${a.status}`)}),r.command("profiles [action] [name]").description("Manage auth profiles (list | switch | delete)").option("--env <name>","Environment for switch/delete").action(async(o,n,c)=>{let i=new me;if(o==="list"||!o&&!process.stdin.isTTY){let m=i.listProfiles();if(m.length===0){console.log("No profiles configured. Run: kane-cli login");return}let p=i.getActiveProfile(),g=i.getDefaultEnv();for(let u of m){let v=u.profile===p&&u.env===g?" (active)":"";console.log(`${u.profile} [${u.env}]${v}`)}return}if(o==="switch"&&n){let m=c?.env??i.getDefaultEnv();i.setActiveProfile(n),i.setDefaultEnv(m),sn(i,new Ae,n,m),console.log(`Switched to ${n} [${m}]`);return}if(o==="delete"&&n){let m=c?.env??i.getDefaultEnv();i.deleteProfileFull(n,m),console.log(`Deleted profile ${n} [${m}]`);return}process.stdin.isTTY||(console.error("Usage: kane-cli profiles list|switch|delete <name> [--env <env>]"),y(1,"Invalid profiles usage"));let{ProfilesView:a}=await import("./ProfilesView-BZEBT6R5.js"),{render:d}=await import("./build-JIKYOZUH.js"),l=await import("./react-QWOAB3TB.js");await new Promise(m=>{let{unmount:p}=d(l.default.createElement(a,{creds:i,onSwitch:(g,u)=>{i.setActiveProfile(g),i.setDefaultEnv(u),console.log(`Switched to ${g} [${u}]`)},onCancel:()=>{p(),m()}}))})}),r.command("feedback").description("Send thumbs-up/down feedback for a completed test run").requiredOption("--test-id <id>","Test ID").requiredOption("--feedback-type <type>","Feedback type: positive or negative").option("--details <text>","Feedback details (max 500 characters)").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").action(async o=>{o.feedbackType!=="positive"&&o.feedbackType!=="negative"&&(console.error('Error: --feedback-type must be "positive" or "negative"'),y(1,'Invalid --feedback-type (must be "positive" or "negative")')),o.details&&o.details.length>500&&(console.error("Error: --details must be 500 characters or fewer"),y(1,"--details exceeds 500 character limit"));let n=new me,c=o.env??n.getDefaultEnv(),i=oe(c),a,d;try{let l=await Be({creds:n,env:c,usernameFlag:o.username,accessKeyFlag:o.accessKey,log:()=>{}});a=l.resolvedCreds?.username??l.basicAuth?.username,d=l.resolvedCreds?.access_key??l.basicAuth?.access_key}catch{console.error("Not authenticated. Run: kane-cli login"),y(2,"Not authenticated for feedback")}(!a||!d)&&(console.error(JSON.stringify({error:"Could not resolve TMS credentials"})),y(1,"Could not resolve TMS credentials for feedback"));try{let{TmsClient:l}=await import("./tms-client-V3TR4QW3.js"),p=await new l(i.tmsBaseUrl,a,d).submitFeedback({instruction_id:"",test_id:o.testId,feedback_type:o.feedbackType,details:o.details,mode:"agent"});console.log(JSON.stringify(p)),y(0,"Feedback submitted")}catch(l){console.error(JSON.stringify({error:l instanceof Error?l.message:String(l)})),y(1,`Feedback failed: ${l instanceof Error?l.message:String(l)}`)}}),r.command("balance").description("Check credit balance").option("--profile <name>","Profile name").option("--username <user>","Basic auth username").option("--access-key <key>","Basic auth access key").option("--env <name>","Environment (prod or stage)").action(async o=>{let n=new me,c=o.env??n.getDefaultEnv(),i=oe(c),a=null;try{let d=await Be({creds:n,env:c,usernameFlag:o.username,accessKeyFlag:o.accessKey,log:()=>{}}),l=d.resolvedCreds??(d.basicAuth?{username:d.basicAuth.username,access_key:d.basicAuth.access_key}:null);l&&(a={username:l.username,accessKey:l.access_key})}catch{console.error(`Not authenticated [${c}]. Run "kane-cli login" first.`),y(2,`Not authenticated for balance [${c}]`)}a||(console.error(`Could not resolve credentials [${c}]. Run "kane-cli login" again.`),y(2,`Could not resolve credentials for balance [${c}]`));try{let{ControllerClient:d}=await import("./controller-client-ZF5IXRUV.js"),m=await new d(i.controllerBaseUrl,a).getCreditBalance();console.log(`Available credits: ${m.available_credits}`),console.log(`Total credits: ${m.total_credits}`),y(0,"Balance retrieved")}catch(d){console.error(`Error: ${d instanceof Error?d.message:String(d)}`),y(1,`Balance check failed: ${d instanceof Error?d.message:String(d)}`)}}),r.command("generate").description("Generate TCG test cases (TUI when interactive; NDJSON/plain when piped, --agent, --refine, or --save)").argument("[objective]",'Generation prompt (e.g. "checkout flow on staging"). Required for new + --refine; omit for --save.').option("--refine","Refine an existing request with <objective>. Requires --req.").option("--save","Save an existing request to disk. Requires --req; --out optional (defaults to <cwd>/.testmuai/tests). Takes no objective.").option("--req <id>","The request id to --refine or --save.").option("--out <dir>","Save target dir (only with --save; default <cwd>/.testmuai/tests).").option("--agent","Emit typed NDJSON on stdout (auto-on when stdin is not a TTY)").option("--name <name>","Name for this generation: sets the session name (like run/testmd) AND the --save suite folder (overrides the auto-derived name)").option("--scenario-limit <n>","Max number of scenarios to generate (1-20)").option("--per-scenario-limit <n>","Max test cases per scenario (1-20)").option("--memory","Enable memory enhancement for generation").option("--project <id>","TMS project id (default: org/config default)").option("--folder <id>","TMS folder id").option("--env <name>","Environment (prod or stage)").option("--username <user>","Basic auth username (skip OAuth)").option("--access-key <key>","Basic auth access key").option("--files <paths>","Comma-separated local files to attach (allowlisted types, \u226450MB each, \u226410; new/refine only)").action(async(o,n)=>{let c=n.scenarioLimit?parseInt(n.scenarioLimit,10):void 0,i=n.perScenarioLimit?parseInt(n.perScenarioLimit,10):void 0,{decideGenerateMode:a,resolveGenerateOp:d,defaultOutDir:l,buildHeadlessDeps:m,runGenerateHeadless:p,parseFilesFlag:g}=await import("./generate-headless-LSQHOR3G.js"),u=d({objective:o,refine:n.refine,save:n.save,req:n.req,out:n.out});if("error"in u){process.stderr.write(`error: ${u.error}
246
+ `),y(2,`generate: ${u.error}`);return}let v=u.op,x=g(n.files);if(v==="save"&&x){process.stderr.write(`error: --files is not valid with --save
247
+ `),y(2,"generate: --files not valid with --save");return}let{headless:T,mode:S}=a(n,!!process.stdin.isTTY);if(!T){let{runGenerate:f}=await import("./tcg-generate-QADJKNYZ.js");await f({objective:o,scenarioLimit:c,perScenarioLimit:i});return}let w=await m({mode:S,env:n.env,projectId:n.project,folderId:n.folder,username:n.username,accessKey:n.accessKey,name:n.name}),C=await p({op:v,objective:o,reqId:n.req,outDir:v==="save"?n.out?Ku(process.cwd(),n.out):l():void 0,suiteName:n.name,scenarioLimit:c,perScenarioLimit:i,memory:n.memory,files:x},w);y(C,"generate complete")}),r.command("changelog").description("Show recent release notes").option("--all","Show all releases instead of latest 5").action(async o=>{let{fetchChangelog:n,formatChangelog:c}=await import("./changelog-ZC3LHV2Z.js"),i=await n({all:o.all});console.log(c(i))}),r.addCommand(Wu()),r}async function Kt(e){let t=Ju(),r=["node","kane-cli",...e];if(!kn(e)){t.parse(r);return}let{parseAsAgent:s,streamVerbFor:o}=await import("./agent-parse-XMWVKCRD.js"),n=await s(t,r,o(e));n!==null&&process.exit(n)}function Wu(){let e=new ct("evidence").description("Evidence pack operations");return e.command("validate").argument("<target>","execution id, pack dir, or sealed .evidence").option("--profile <profile>","L0 | L1","L1").option("--json","machine-readable",!1).action(async(t,r)=>{let{runEvidenceValidate:s}=await import("./evidence-KRNDKDCT.js");process.exitCode=await s(t,{profile:r.profile,json:r.json})}),e.command("serve").argument("<paths...>","sealed .evidence file(s) to serve to the hosted viewer").option("--port <n>","pin the local port (default: ephemeral)",t=>parseInt(t,10)).option("--viewer-url <base>","override the hosted viewer base URL").option("--env <name>","environment (prod or stage)").action(async(t,r)=>{let{runEvidenceServe:s}=await import("./evidence-KRNDKDCT.js"),{CredentialsManager:o}=await import("./credentials-RQPAP5KY.js"),n=r.env??new o().getDefaultEnv()??"prod";process.exitCode=await s(t,{port:r.port,viewerUrl:r.viewerUrl,env:n})}),e.command("merge").argument("<targets...>","execution ids or pack paths (order-significant)").option("--run-id <id>","run_id for the merged pack (required \u2014 identity is the caller's fact)").option("-o, --out <path>","output path (default: .testmuai/evidence/<run-id>.evidence)").option("--rules <path>","merge-rules.yaml (replaces the kane defaults wholesale)").option("--on-collision <action>","error | prefer-first | prefer-latest | discard").option("--title <title>","merged run title (default: first eligible pack's)").option("--no-finalize","keep the merged pack live instead of sealing it").option("--json","machine-readable MergeReport",!1).option("--env <name>","environment (prod or stage)").action(async(t,r)=>{let{runEvidenceMerge:s}=await import("./evidence-KRNDKDCT.js"),{CredentialsManager:o}=await import("./credentials-RQPAP5KY.js"),n=r.env??new o().getDefaultEnv()??"prod";process.exitCode=await s(t,{runId:r.runId,out:r.out,rules:r.rules,onCollision:r.onCollision,title:r.title,finalize:r.finalize,json:r.json,env:n})}),e}function Lc(e){let t,r,s,o=[];for(let n=0;n<e.length;n++){let c=e[n];if(c==="--code-export")t=!0;else if(c==="--skip-code-validation"){let i=e[n+1]?.toLowerCase();i==="true"||i==="false"?(s=i==="true",n++):s=!0}else if(c==="--skip-code-validation=true"||c==="--skip-code-validation=false")s=c.endsWith("=true");else if(c==="--no-skip-code-validation")s=!1;else if(c==="--code-language"){let i=e[n+1];i!==void 0&&(r=i,n++)}else c.startsWith("--code-language=")?r=c.slice(16):o.push(c)}return{codeExport:t,codeLanguage:r,skipCodeValidation:s,filteredArgs:o}}function Vc(e){return e[0]==="run"?!0:(e[0]==="testmd"||e[0]==="testrun")&&e[1]==="run"}function Fr(e,t){let r=e[0];if(r!=="run"&&!(r==="testmd"&&e[1]==="run"))return e;let s=[...e];return t.codeExport&&s.push("--code-export"),t.codeLanguage&&s.push("--code-language",t.codeLanguage),t.skipCodeValidation===!0&&s.push("--skip-code-validation"),t.skipCodeValidation===!1&&s.push("--no-skip-code-validation"),s}function $n(e,t){let r=e.split(".").map(o=>Number(o)||0),s=t.split(".").map(o=>Number(o)||0);for(let o=0;o<3;o++){let n=r[o]??0,c=s[o]??0;if(n<c)return-1;if(n>c)return 1}return 0}var Yu=[{version:"0.2.11",description:"Code export is now enabled by default (Python remains the default language; JavaScript is also available). Default run mode is now 'testing'.",apply:e=>{let t=[];return e.code_export.enabled===!1&&t.push({field:"code_export.enabled",from:!1,to:!0,description:"Code export is now enabled by default."}),e.mode==="action"&&t.push({field:"mode",from:"action",to:"testing",description:"Default run mode is now 'testing'."}),{cfg:{...e,code_export:{...e.code_export,enabled:!0},mode:"testing"},changes:t}}},{version:"0.5.1",description:"Assertions now read the DOM first (falling back to vision when the value isn't in the DOM). Default assertion mode is now 'dom'.",apply:e=>{let t=[];return e.assertion_mode==="visual"&&t.push({field:"assertion_mode",from:"visual",to:"dom",description:"Default assertion mode is now 'dom' (DOM-first, vision fallback)."}),{cfg:{...e,assertion_mode:"dom"},changes:t}}}];function Uc(e,t=be,r=Yu){let s=e.exists(),o=e.load();if(!s)return e.set("last_seen_version",t),{changes:[],fromVersion:t,toVersion:t,appliedVersions:[]};let n=o.last_seen_version||"0.0.0";if($n(n,t)>=0)return{changes:[],fromVersion:n,toVersion:n,appliedVersions:[]};let c=r.filter(m=>$n(n,m.version)<0&&$n(m.version,t)<=0).sort((m,p)=>$n(m.version,p.version)),i=o,a=[],d=[];for(let m of c){let{cfg:p,changes:g}=m.apply(i);i=p,a.push(...g),d.push(m.version)}let l={...i,last_seen_version:t};return e.writeRaw(l),{changes:a,fromVersion:n,toVersion:t,appliedVersions:d}}function Bc(e){return e.changes.length===0?"":[`kane-cli updated to ${e.toVersion}. Default settings changed:`,...e.changes.map(r=>` \u2022 ${r.description} (${r.field}: ${JSON.stringify(r.from)} \u2192 ${JSON.stringify(r.to)})`),"","Use /config to review or revert any of these."].join(`
248
+ `)}yo();cs(be);_i();Ci();var Wc=vn().catch(()=>null),Hu=bn().catch(()=>null);us(void 0,ho);var Mn=null,Kr=()=>Mn||(Mn=Uc(new Ae),Mn),Nn=pe.argv.slice(2),Gu=Nn.includes("--dev"),Lr=Nn.includes("--local"),qu=Nn.includes("--tui");Gu&&(pe.env.KANE_DEV_MODE="1");var zu=Nn.filter(e=>!["--dev","--local","--tui"].includes(e));function Xu(e){let t=[],r;for(let s=0;s<e.length;s++){let o=e[s];if(o==="--name"&&s+1<e.length){r=e[s+1],s++;continue}if(o.startsWith("--name=")){r=o.slice(7);continue}t.push(o)}return{name:r,rest:t}}var jn=Lc(zu),We=jn.filteredArgs,Vr=jn.codeExport,Ur=jn.codeLanguage,Br=jn.skipCodeValidation,On=Yi([{promise:Wc,line:e=>{let t=e;return`
249
+ Update available: ${t.current} \u2192 ${t.latest} \u2014 run \`${ni()}\` to update
250
250
 
251
- `}},{promise:Ju,line:e=>{let t=e;return`Skill update available: ${t.current??"not installed"} \u2192 ${t.latestCompatible} \u2014 run \`kane-cli install skill\`
251
+ `}},{promise:Hu,line:e=>{let t=e;return`Skill update available: ${t.current??"not installed"} \u2192 ${t.latestCompatible} \u2014 run \`kane-cli install skill\`
252
252
 
253
- `}}],e=>de.stderr.write(e)),Lc=()=>Dn.eager(),Vc=()=>{let e=Fc(Lr());e&&de.stderr.write(`
253
+ `}}],e=>pe.stderr.write(e)),Kc=()=>On.eager(),Jc=()=>{let e=Bc(Kr());e&&pe.stderr.write(`
254
254
  ${e}
255
255
 
256
- `)},qu=new Set(["--help","-h","--version","-V"]),zu=Je[0]==="help"||Je.some(e=>qu.has(e));if(zu)Kt(Je);else if(Yu){de.stdin.isTTY||(de.stderr.write(`Error: --tui mode requires an interactive terminal (TTY).
257
- `),de.exit(1)),Lc();let{name:e}=Gu(Je);if(e){let{validateNameOrThrow:i}=await import("./name-validator-5YGJXLZ7.js");try{i(e)}catch(o){de.stderr.write(`error: ${o.message}
258
- `),de.exit(2)}}let{waitUntilExit:t,unmount:r}=rt(Jt.default.createElement(ot,null,Jt.default.createElement(Zi,{localMode:Or,codeExport:Nr,codeLanguage:jr,skipCodeValidation:Fr,updatePromise:Uc,migrationResult:Lr(),sessionName:e})),{exitOnCtrlC:!1});Dt(()=>r()),Gn(()=>{try{de.stdin.setRawMode?.(!1)}catch{}de.stdout.write("\x1B[?25h")}),t().then(()=>{y(0,"TUI session ended")})}else if(Je.length>0){let e=Je[0],t=Qt(),r=cr(t).has(e),i=e.startsWith("-");if(!r&&!i){let{message:a,exitCode:d}=Vs(e,{hostSupportsMobile:t,mobileMessage:Zt()});de.stderr.write(a),de.exit(d)}if(bn(Je))Dn.silence(),Lr();else{let a=Ks(e,!1);a==="silence"?Dn.silence():a==="bounded"?await Dn.bounded():Lc(),Vc()}let c=Or&&Nc(Je)?[...Je,"--local"]:Je,s=Mr(c,{codeExport:Nr,codeLanguage:jr,skipCodeValidation:Fr});await Kt(s)}else{de.stdin.isTTY||(de.stderr.write(`Error: kane-cli requires an interactive terminal (TTY) when run without arguments.
256
+ `)},Qu=new Set(["--help","-h","--version","-V"]),Zu=We[0]==="help"||We.some(e=>Qu.has(e));if(Zu)Kt(We);else if(qu){pe.stdin.isTTY||(pe.stderr.write(`Error: --tui mode requires an interactive terminal (TTY).
257
+ `),pe.exit(1)),Kc();let{name:e}=Xu(We);if(e){let{validateNameOrThrow:s}=await import("./name-validator-5YGJXLZ7.js");try{s(e)}catch(o){pe.stderr.write(`error: ${o.message}
258
+ `),pe.exit(2)}}let{waitUntilExit:t,unmount:r}=rt(Jt.default.createElement(ot,null,Jt.default.createElement(ri,{localMode:Lr,codeExport:Vr,codeLanguage:Ur,skipCodeValidation:Br,updatePromise:Wc,migrationResult:Kr(),sessionName:e})),{exitOnCtrlC:!1});Dt(()=>r()),Qn(()=>{try{pe.stdin.setRawMode?.(!1)}catch{}pe.stdout.write("\x1B[?25h")}),t().then(()=>{y(0,"TUI session ended")})}else if(We.length>0){let e=We[0],t=Zt(),r=mr(t).has(e),s=e.startsWith("-");if(!r&&!s){let{message:a,exitCode:d}=Ji(e,{hostSupportsMobile:t,mobileMessage:en()});pe.stderr.write(a),pe.exit(d)}if(kn(We))On.silence(),Kr();else{let a=Hi(e,!1);a==="silence"?On.silence():a==="bounded"?await On.bounded():Kc(),Jc()}let c=Lr&&Vc(We)?[...We,"--local"]:We,i=Fr(c,{codeExport:Vr,codeLanguage:Ur,skipCodeValidation:Br});await Kt(i)}else{pe.stdin.isTTY||(pe.stderr.write(`Error: kane-cli requires an interactive terminal (TTY) when run without arguments.
259
259
  Usage: kane-cli "objective" for non-interactive mode.
260
- `),de.exit(1));let e={current:null},{waitUntilExit:t,unmount:r}=rt(Jt.default.createElement(ot,null,Jt.default.createElement(vi,{resultRef:e})),{exitOnCtrlC:!1});Dt(()=>r()),Gn(()=>{try{de.stdin.setRawMode?.(!1)}catch{}de.stdout.write("\x1B[?25h")}),t().then(()=>{ho();let i=e.current;if(!i){y(0,"Single-shot session ended (no objective)");return}let o=i.objective.trim();if(o==="--help"||o==="-h"||o==="help"){Kt(["--help"]);return}Vc();let n=["run",i.objective];Or&&n.push("--local"),Kt(Mr(n,{codeExport:Nr,codeLanguage:jr,skipCodeValidation:Fr}))})}
260
+ `),pe.exit(1));let e={current:null},{waitUntilExit:t,unmount:r}=rt(Jt.default.createElement(ot,null,Jt.default.createElement(ys,{resultRef:e})),{exitOnCtrlC:!1});Dt(()=>r()),Qn(()=>{try{pe.stdin.setRawMode?.(!1)}catch{}pe.stdout.write("\x1B[?25h")}),t().then(()=>{wo();let s=e.current;if(!s){y(0,"Single-shot session ended (no objective)");return}let o=s.objective.trim();if(o==="--help"||o==="-h"||o==="help"){Kt(["--help"]);return}Jc();let n=["run",s.objective];Lr&&n.push("--local"),Kt(Fr(n,{codeExport:Vr,codeLanguage:Ur,skipCodeValidation:Br}))})}