@runcofactor/cli 0.54.0 → 0.56.0
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.
- package/README.md +2 -1
- package/dist/{account-6YJAU53I.js → account-CZYZD2JS.js} +5 -5
- package/dist/{alert-Z7V2ZUEW.js → alert-JQ4SDEB7.js} +8 -8
- package/dist/{api-catalog-UEDTRM6E.js → api-catalog-IWQC35P2.js} +5 -5
- package/dist/{api-key-V5GEPRRG.js → api-key-GUDXIIEA.js} +5 -5
- package/dist/{attachment-M7VZ6GSE.js → attachment-CPZYOBUB.js} +5 -5
- package/dist/{auth-DVTMWJKF.js → auth-DS6MBVEI.js} +3 -3
- package/dist/{benchmark-KZJZYUTQ.js → benchmark-6HPCIQHD.js} +5 -5
- package/dist/{blackcat-QJXYDE66.js → blackcat-V3L63WFE.js} +3 -3
- package/dist/{chunk-FLDIN6VX.js → chunk-2E3STBHS.js} +2 -2
- package/dist/{chunk-KNWKOKM7.js → chunk-2OHYMT3A.js} +20 -11
- package/dist/chunk-2OHYMT3A.js.map +1 -0
- package/dist/{chunk-L4Y5PZUE.js → chunk-3LGCHNBC.js} +2 -2
- package/dist/{chunk-ZFN5FWN2.js → chunk-4MFMPC5P.js} +46 -2
- package/dist/chunk-4MFMPC5P.js.map +1 -0
- package/dist/{chunk-2M4PZK6Q.js → chunk-56HFZHQM.js} +8 -8
- package/dist/{chunk-AQOHNAEN.js → chunk-5OYWNS6D.js} +20 -9
- package/dist/chunk-5OYWNS6D.js.map +1 -0
- package/dist/{chunk-RA2NRAWU.js → chunk-62EXS76C.js} +6 -6
- package/dist/{chunk-HGEJHS45.js → chunk-6ILWJFKY.js} +368 -6
- package/dist/chunk-6ILWJFKY.js.map +1 -0
- package/dist/{chunk-4EWSONHO.js → chunk-BDOL622T.js} +4 -4
- package/dist/{chunk-T6EQFICG.js → chunk-C3CXVX2B.js} +4 -4
- package/dist/{chunk-33U56YGD.js → chunk-CWICLBLU.js} +2 -1
- package/dist/{chunk-33U56YGD.js.map → chunk-CWICLBLU.js.map} +1 -1
- package/dist/{chunk-MQQCUU5S.js → chunk-DEVD2WD2.js} +2 -2
- package/dist/{chunk-TRC63RSK.js → chunk-EWK44F6V.js} +3 -3
- package/dist/chunk-EWK44F6V.js.map +1 -0
- package/dist/{chunk-Q7UAEFW5.js → chunk-FNHPTTRF.js} +7 -5
- package/dist/chunk-FNHPTTRF.js.map +1 -0
- package/dist/{chunk-JAIMLQOU.js → chunk-GCD4EHCD.js} +6 -6
- package/dist/{chunk-7MRZWPVC.js → chunk-H6ZMKNP7.js} +3 -3
- package/dist/{chunk-ZOPVBINJ.js → chunk-IEWAH7W3.js} +5 -5
- package/dist/{chunk-74TU6PGO.js → chunk-IV4HRGKX.js} +77 -12
- package/dist/chunk-IV4HRGKX.js.map +1 -0
- package/dist/{chunk-ZO5MSM4Q.js → chunk-J2ZQULU3.js} +2 -2
- package/dist/{chunk-IVWWYKAM.js → chunk-K2IDR6FR.js} +3 -3
- package/dist/{chunk-QGP67JOK.js → chunk-KTZRI27M.js} +4 -4
- package/dist/{chunk-HESV3F6U.js → chunk-L644NMDI.js} +3 -3
- package/dist/{chunk-HESV3F6U.js.map → chunk-L644NMDI.js.map} +1 -1
- package/dist/{chunk-LPQTXBJF.js → chunk-LFT7GUWS.js} +63 -17
- package/dist/chunk-LFT7GUWS.js.map +1 -0
- package/dist/{chunk-O7MBDOMO.js → chunk-O7B2IYCZ.js} +30 -14
- package/dist/chunk-O7B2IYCZ.js.map +1 -0
- package/dist/{chunk-R2CVV7QT.js → chunk-RHWPZKRV.js} +28 -1
- package/dist/chunk-RHWPZKRV.js.map +1 -0
- package/dist/{chunk-3YNR6U6Q.js → chunk-UJSW72LG.js} +3 -3
- package/dist/{chunk-G2SCV2CY.js → chunk-VACACCD6.js} +3 -3
- package/dist/{chunk-CV22445U.js → chunk-VMAR67FF.js} +2 -2
- package/dist/{chunk-QYHJUHL7.js → chunk-VMJ7TBVM.js} +2 -2
- package/dist/chunk-WRRA4ATV.js +332 -0
- package/dist/chunk-WRRA4ATV.js.map +1 -0
- package/dist/{chunk-YACDH6MJ.js → chunk-XHEVDABB.js} +2 -2
- package/dist/{chunk-7VBX2M4F.js → chunk-XHGF6VC6.js} +4 -4
- package/dist/{credential-546ER7WQ.js → credential-GJW7LGYP.js} +5 -5
- package/dist/{credential-template-BWMEBGBN.js → credential-template-UWBYKKWD.js} +5 -5
- package/dist/dev-PBW7BSOD.js +605 -0
- package/dist/dev-PBW7BSOD.js.map +1 -0
- package/dist/{digest-NIVBDDI2.js → digest-XEHGCJM4.js} +8 -8
- package/dist/{docs-AK4MDP6K.js → docs-KH4BCEQF.js} +5 -5
- package/dist/{doctor-NCLA47EL.js → doctor-FOXXE5SK.js} +3 -3
- package/dist/{environment-X3PV5IN2.js → environment-EBDPQTIS.js} +7 -7
- package/dist/{eval-5FZKYZ6O.js → eval-QZSSEICV.js} +67 -27
- package/dist/eval-QZSSEICV.js.map +1 -0
- package/dist/{exploration-2RVGIUKT.js → exploration-LCGKRGOQ.js} +5 -5
- package/dist/{exploratory-test-SJ5HFI3L.js → exploratory-test-SGECQGIX.js} +13 -5
- package/dist/exploratory-test-SGECQGIX.js.map +1 -0
- package/dist/{external-run-4NDVAHQB.js → external-run-2AJAI5O7.js} +9 -9
- package/dist/{feature-flag-C4IRE724.js → feature-flag-P7N4WQIH.js} +5 -5
- package/dist/{feedback-337OZCKC.js → feedback-LAT7TQ2T.js} +6 -6
- package/dist/{flow-D7ZLBKCH.js → flow-NH2DC6AP.js} +5 -5
- package/dist/{github-LKXYIALH.js → github-FCEKBLXI.js} +6 -6
- package/dist/index.js +106 -408
- package/dist/index.js.map +1 -1
- package/dist/{init-GKEC6LPH.js → init-5U5EZOAW.js} +5 -5
- package/dist/{install-K45SAT2V.js → install-X3UNVXKY.js} +5 -5
- package/dist/{issues-2HMTQYWR.js → issues-4P6I3YQW.js} +8 -8
- package/dist/{knobs-KUCGLO5Z.js → knobs-JKTWJ6ZG.js} +5 -5
- package/dist/{landing-KAET2I73.js → landing-6AGLKI66.js} +7 -7
- package/dist/{list-GDV4UYWV.js → list-TWP2RP33.js} +5 -5
- package/dist/{local-NFOSJLLV.js → local-D75QE5TB.js} +7 -7
- package/dist/{login-Y77HWROY.js → login-RBET4TIP.js} +5 -5
- package/dist/{mcp-CPCFMU6B.js → mcp-562SUUMK.js} +11 -11
- package/dist/{metrics-Y245ST63.js → metrics-4WF2GEPA.js} +5 -5
- package/dist/{monitor-BUDWSC3S.js → monitor-WJXH54H2.js} +5 -5
- package/dist/{perf-3JOAXPHP.js → perf-C6N6P7YG.js} +12 -361
- package/dist/perf-C6N6P7YG.js.map +1 -0
- package/dist/{product-CXL3YTMD.js → product-CYEQ7HOB.js} +5 -5
- package/dist/{product-map-656BTU74.js → product-map-MSDLIFZY.js} +7 -7
- package/dist/{prompts-3SZ7O5E6.js → prompts-ME53WPN4.js} +5 -5
- package/dist/{proofs-4CSCCSNL.js → proofs-D3G6ZUFP.js} +11 -9
- package/dist/{property-IEKBXRVY.js → property-5GLJNAVB.js} +29 -10
- package/dist/property-5GLJNAVB.js.map +1 -0
- package/dist/{psql-M4CM6TSI.js → psql-EXAUDU3W.js} +5 -5
- package/dist/{record-QP4TYZBS.js → record-EE7NGNKY.js} +6 -6
- package/dist/{redis-KG47IGJV.js → redis-M4EYWKOJ.js} +5 -5
- package/dist/{release-QHPSQULK.js → release-4KUWVWWC.js} +5 -5
- package/dist/{runbook-YVBG2QK3.js → runbook-AHU77ANQ.js} +5 -5
- package/dist/{sandbox-ZXDZTCCN.js → sandbox-FBLJEYA2.js} +1917 -1633
- package/dist/sandbox-FBLJEYA2.js.map +1 -0
- package/dist/{scenarios-2SX2NUCD.js → scenarios-TU656T2B.js} +5 -5
- package/dist/{schedule-P6F7MLXX.js → schedule-DXJI6SYO.js} +8 -8
- package/dist/{session-SZMCZTPE.js → session-RUFTJHF4.js} +10 -10
- package/dist/{skill-D4XFW6QI.js → skill-ZK76GQ47.js} +111 -13
- package/dist/skill-ZK76GQ47.js.map +1 -0
- package/dist/skills/cofactor-debug-run/SKILL.md +6 -1
- package/dist/skills/cofactor-debug-run/history/2.0.10.md +320 -0
- package/dist/skills/cofactor-debug-run/history/2.0.9.md +319 -0
- package/dist/skills/cofactor-debug-run/version.json +1 -1
- package/dist/{slack-UDXTPOSW.js → slack-M3OKDVMY.js} +6 -6
- package/dist/{spec-YCBBIV27.js → spec-5MXEBLYR.js} +5 -5
- package/dist/{src-DY7GLRO2.js → src-2X5OQRPJ.js} +4 -4
- package/dist/{src-NG7DRE5A.js → src-72EFBA2R.js} +3 -3
- package/dist/{src-DEGBASCD.js → src-KH6WSBJV.js} +5 -5
- package/dist/{src-ZKVNVLXY.js → src-VLV36QYH.js} +127 -20
- package/dist/src-VLV36QYH.js.map +1 -0
- package/dist/{start-ZYZSORPY.js → start-PDYBRB5T.js} +5 -5
- package/dist/{status-ESIG6A7W.js → status-VMVPVCDA.js} +5 -5
- package/dist/{tag-3K5Y25AR.js → tag-7KTDLPVU.js} +6 -6
- package/dist/{task-JLNX7O3M.js → task-QLFYZNKR.js} +6 -6
- package/dist/{teams-F4IU3EXE.js → teams-Y7BXCY6P.js} +7 -7
- package/dist/{test-suite-QHDUW5W5.js → test-suite-6U22AYFG.js} +15 -14
- package/dist/test-suite-6U22AYFG.js.map +1 -0
- package/dist/{tickets-NBL5WACL.js → tickets-CQDJDNPY.js} +5 -5
- package/dist/{trace-ZKYAI5JF.js → trace-QDORWXYX.js} +8 -8
- package/dist/{triage-5NWCREUM.js → triage-GY7M3UGG.js} +6 -6
- package/dist/{trigger-KXYYY5IR.js → trigger-DLFAORX4.js} +9 -9
- package/dist/{update-check-Q2URVJLC.js → update-check-ES6XQ7OF.js} +4 -4
- package/dist/{upgrade-4XSASC7U.js → upgrade-WKEOW5GS.js} +5 -5
- package/dist/{usage-UY7VZYVY.js → usage-E6FDTR3W.js} +7 -7
- package/dist/{utilities-53NXNLA7.js → utilities-4Z6YX3L5.js} +6 -6
- package/dist/{visual-IJAT7X7D.js → visual-TA6LPVDJ.js} +5 -5
- package/dist/{workflow-OQNH2FIS.js → workflow-B5FXS2CJ.js} +92 -36
- package/dist/workflow-B5FXS2CJ.js.map +1 -0
- package/dist/{workflow-cache-FP6MKLVR.js → workflow-cache-MNLEMRMM.js} +16 -16
- package/dist/{workflow-cache-convergence-resolve-HS5KO7US.js → workflow-cache-convergence-resolve-G5HJM6MF.js} +5 -5
- package/dist/{workflow-debug-EM55H2QE.js → workflow-debug-TNBUGSBK.js} +11 -11
- package/dist/{workflow-feedback-GNWNWVHH.js → workflow-feedback-G2ZXAUGI.js} +5 -5
- package/dist/{workflow-fork-M5AQWST7.js → workflow-fork-6HHOMC2D.js} +5 -5
- package/dist/{workflow-promotion-HYULZDYL.js → workflow-promotion-RG7L6JZT.js} +5 -5
- package/dist/{workflow-proposals-EN327FSE.js → workflow-proposals-ZNF2F3UE.js} +5 -5
- package/dist/{workflow-revisions-ZMTVNWRW.js → workflow-revisions-TP64Z6FO.js} +5 -5
- package/dist/{workflow-status-FNAJG34W.js → workflow-status-5RG3JX56.js} +5 -5
- package/package.json +3 -2
- package/dist/chunk-74TU6PGO.js.map +0 -1
- package/dist/chunk-AQOHNAEN.js.map +0 -1
- package/dist/chunk-HGEJHS45.js.map +0 -1
- package/dist/chunk-KNWKOKM7.js.map +0 -1
- package/dist/chunk-LPQTXBJF.js.map +0 -1
- package/dist/chunk-O7MBDOMO.js.map +0 -1
- package/dist/chunk-Q7UAEFW5.js.map +0 -1
- package/dist/chunk-R2CVV7QT.js.map +0 -1
- package/dist/chunk-TRC63RSK.js.map +0 -1
- package/dist/chunk-ZFN5FWN2.js.map +0 -1
- package/dist/eval-5FZKYZ6O.js.map +0 -1
- package/dist/exploratory-test-SJ5HFI3L.js.map +0 -1
- package/dist/perf-3JOAXPHP.js.map +0 -1
- package/dist/property-IEKBXRVY.js.map +0 -1
- package/dist/sandbox-ZXDZTCCN.js.map +0 -1
- package/dist/skill-D4XFW6QI.js.map +0 -1
- package/dist/src-ZKVNVLXY.js.map +0 -1
- package/dist/test-suite-QHDUW5W5.js.map +0 -1
- package/dist/workflow-OQNH2FIS.js.map +0 -1
- /package/dist/{account-6YJAU53I.js.map → account-CZYZD2JS.js.map} +0 -0
- /package/dist/{alert-Z7V2ZUEW.js.map → alert-JQ4SDEB7.js.map} +0 -0
- /package/dist/{api-catalog-UEDTRM6E.js.map → api-catalog-IWQC35P2.js.map} +0 -0
- /package/dist/{api-key-V5GEPRRG.js.map → api-key-GUDXIIEA.js.map} +0 -0
- /package/dist/{attachment-M7VZ6GSE.js.map → attachment-CPZYOBUB.js.map} +0 -0
- /package/dist/{auth-DVTMWJKF.js.map → auth-DS6MBVEI.js.map} +0 -0
- /package/dist/{benchmark-KZJZYUTQ.js.map → benchmark-6HPCIQHD.js.map} +0 -0
- /package/dist/{blackcat-QJXYDE66.js.map → blackcat-V3L63WFE.js.map} +0 -0
- /package/dist/{chunk-FLDIN6VX.js.map → chunk-2E3STBHS.js.map} +0 -0
- /package/dist/{chunk-L4Y5PZUE.js.map → chunk-3LGCHNBC.js.map} +0 -0
- /package/dist/{chunk-2M4PZK6Q.js.map → chunk-56HFZHQM.js.map} +0 -0
- /package/dist/{chunk-RA2NRAWU.js.map → chunk-62EXS76C.js.map} +0 -0
- /package/dist/{chunk-4EWSONHO.js.map → chunk-BDOL622T.js.map} +0 -0
- /package/dist/{chunk-T6EQFICG.js.map → chunk-C3CXVX2B.js.map} +0 -0
- /package/dist/{chunk-MQQCUU5S.js.map → chunk-DEVD2WD2.js.map} +0 -0
- /package/dist/{chunk-JAIMLQOU.js.map → chunk-GCD4EHCD.js.map} +0 -0
- /package/dist/{chunk-7MRZWPVC.js.map → chunk-H6ZMKNP7.js.map} +0 -0
- /package/dist/{chunk-ZOPVBINJ.js.map → chunk-IEWAH7W3.js.map} +0 -0
- /package/dist/{chunk-ZO5MSM4Q.js.map → chunk-J2ZQULU3.js.map} +0 -0
- /package/dist/{chunk-IVWWYKAM.js.map → chunk-K2IDR6FR.js.map} +0 -0
- /package/dist/{chunk-QGP67JOK.js.map → chunk-KTZRI27M.js.map} +0 -0
- /package/dist/{chunk-3YNR6U6Q.js.map → chunk-UJSW72LG.js.map} +0 -0
- /package/dist/{chunk-G2SCV2CY.js.map → chunk-VACACCD6.js.map} +0 -0
- /package/dist/{chunk-CV22445U.js.map → chunk-VMAR67FF.js.map} +0 -0
- /package/dist/{chunk-QYHJUHL7.js.map → chunk-VMJ7TBVM.js.map} +0 -0
- /package/dist/{chunk-YACDH6MJ.js.map → chunk-XHEVDABB.js.map} +0 -0
- /package/dist/{chunk-7VBX2M4F.js.map → chunk-XHGF6VC6.js.map} +0 -0
- /package/dist/{credential-546ER7WQ.js.map → credential-GJW7LGYP.js.map} +0 -0
- /package/dist/{credential-template-BWMEBGBN.js.map → credential-template-UWBYKKWD.js.map} +0 -0
- /package/dist/{digest-NIVBDDI2.js.map → digest-XEHGCJM4.js.map} +0 -0
- /package/dist/{docs-AK4MDP6K.js.map → docs-KH4BCEQF.js.map} +0 -0
- /package/dist/{doctor-NCLA47EL.js.map → doctor-FOXXE5SK.js.map} +0 -0
- /package/dist/{environment-X3PV5IN2.js.map → environment-EBDPQTIS.js.map} +0 -0
- /package/dist/{exploration-2RVGIUKT.js.map → exploration-LCGKRGOQ.js.map} +0 -0
- /package/dist/{external-run-4NDVAHQB.js.map → external-run-2AJAI5O7.js.map} +0 -0
- /package/dist/{feature-flag-C4IRE724.js.map → feature-flag-P7N4WQIH.js.map} +0 -0
- /package/dist/{feedback-337OZCKC.js.map → feedback-LAT7TQ2T.js.map} +0 -0
- /package/dist/{flow-D7ZLBKCH.js.map → flow-NH2DC6AP.js.map} +0 -0
- /package/dist/{github-LKXYIALH.js.map → github-FCEKBLXI.js.map} +0 -0
- /package/dist/{init-GKEC6LPH.js.map → init-5U5EZOAW.js.map} +0 -0
- /package/dist/{install-K45SAT2V.js.map → install-X3UNVXKY.js.map} +0 -0
- /package/dist/{issues-2HMTQYWR.js.map → issues-4P6I3YQW.js.map} +0 -0
- /package/dist/{knobs-KUCGLO5Z.js.map → knobs-JKTWJ6ZG.js.map} +0 -0
- /package/dist/{landing-KAET2I73.js.map → landing-6AGLKI66.js.map} +0 -0
- /package/dist/{list-GDV4UYWV.js.map → list-TWP2RP33.js.map} +0 -0
- /package/dist/{local-NFOSJLLV.js.map → local-D75QE5TB.js.map} +0 -0
- /package/dist/{login-Y77HWROY.js.map → login-RBET4TIP.js.map} +0 -0
- /package/dist/{mcp-CPCFMU6B.js.map → mcp-562SUUMK.js.map} +0 -0
- /package/dist/{metrics-Y245ST63.js.map → metrics-4WF2GEPA.js.map} +0 -0
- /package/dist/{monitor-BUDWSC3S.js.map → monitor-WJXH54H2.js.map} +0 -0
- /package/dist/{product-CXL3YTMD.js.map → product-CYEQ7HOB.js.map} +0 -0
- /package/dist/{product-map-656BTU74.js.map → product-map-MSDLIFZY.js.map} +0 -0
- /package/dist/{prompts-3SZ7O5E6.js.map → prompts-ME53WPN4.js.map} +0 -0
- /package/dist/{proofs-4CSCCSNL.js.map → proofs-D3G6ZUFP.js.map} +0 -0
- /package/dist/{psql-M4CM6TSI.js.map → psql-EXAUDU3W.js.map} +0 -0
- /package/dist/{record-QP4TYZBS.js.map → record-EE7NGNKY.js.map} +0 -0
- /package/dist/{redis-KG47IGJV.js.map → redis-M4EYWKOJ.js.map} +0 -0
- /package/dist/{release-QHPSQULK.js.map → release-4KUWVWWC.js.map} +0 -0
- /package/dist/{runbook-YVBG2QK3.js.map → runbook-AHU77ANQ.js.map} +0 -0
- /package/dist/{scenarios-2SX2NUCD.js.map → scenarios-TU656T2B.js.map} +0 -0
- /package/dist/{schedule-P6F7MLXX.js.map → schedule-DXJI6SYO.js.map} +0 -0
- /package/dist/{session-SZMCZTPE.js.map → session-RUFTJHF4.js.map} +0 -0
- /package/dist/{slack-UDXTPOSW.js.map → slack-M3OKDVMY.js.map} +0 -0
- /package/dist/{spec-YCBBIV27.js.map → spec-5MXEBLYR.js.map} +0 -0
- /package/dist/{src-DEGBASCD.js.map → src-2X5OQRPJ.js.map} +0 -0
- /package/dist/{src-DY7GLRO2.js.map → src-72EFBA2R.js.map} +0 -0
- /package/dist/{src-NG7DRE5A.js.map → src-KH6WSBJV.js.map} +0 -0
- /package/dist/{start-ZYZSORPY.js.map → start-PDYBRB5T.js.map} +0 -0
- /package/dist/{status-ESIG6A7W.js.map → status-VMVPVCDA.js.map} +0 -0
- /package/dist/{tag-3K5Y25AR.js.map → tag-7KTDLPVU.js.map} +0 -0
- /package/dist/{task-JLNX7O3M.js.map → task-QLFYZNKR.js.map} +0 -0
- /package/dist/{teams-F4IU3EXE.js.map → teams-Y7BXCY6P.js.map} +0 -0
- /package/dist/{tickets-NBL5WACL.js.map → tickets-CQDJDNPY.js.map} +0 -0
- /package/dist/{trace-ZKYAI5JF.js.map → trace-QDORWXYX.js.map} +0 -0
- /package/dist/{triage-5NWCREUM.js.map → triage-GY7M3UGG.js.map} +0 -0
- /package/dist/{trigger-KXYYY5IR.js.map → trigger-DLFAORX4.js.map} +0 -0
- /package/dist/{update-check-Q2URVJLC.js.map → update-check-ES6XQ7OF.js.map} +0 -0
- /package/dist/{upgrade-4XSASC7U.js.map → upgrade-WKEOW5GS.js.map} +0 -0
- /package/dist/{usage-UY7VZYVY.js.map → usage-E6FDTR3W.js.map} +0 -0
- /package/dist/{utilities-53NXNLA7.js.map → utilities-4Z6YX3L5.js.map} +0 -0
- /package/dist/{visual-IJAT7X7D.js.map → visual-TA6LPVDJ.js.map} +0 -0
- /package/dist/{workflow-cache-FP6MKLVR.js.map → workflow-cache-MNLEMRMM.js.map} +0 -0
- /package/dist/{workflow-cache-convergence-resolve-HS5KO7US.js.map → workflow-cache-convergence-resolve-G5HJM6MF.js.map} +0 -0
- /package/dist/{workflow-debug-EM55H2QE.js.map → workflow-debug-TNBUGSBK.js.map} +0 -0
- /package/dist/{workflow-feedback-GNWNWVHH.js.map → workflow-feedback-G2ZXAUGI.js.map} +0 -0
- /package/dist/{workflow-fork-M5AQWST7.js.map → workflow-fork-6HHOMC2D.js.map} +0 -0
- /package/dist/{workflow-promotion-HYULZDYL.js.map → workflow-promotion-RG7L6JZT.js.map} +0 -0
- /package/dist/{workflow-proposals-EN327FSE.js.map → workflow-proposals-ZNF2F3UE.js.map} +0 -0
- /package/dist/{workflow-revisions-ZMTVNWRW.js.map → workflow-revisions-TP64Z6FO.js.map} +0 -0
- /package/dist/{workflow-status-FNAJG34W.js.map → workflow-status-5RG3JX56.js.map} +0 -0
|
@@ -7,15 +7,15 @@ import {
|
|
|
7
7
|
fetchList,
|
|
8
8
|
promptChoice,
|
|
9
9
|
selectProperty
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EWK44F6V.js";
|
|
11
11
|
import "./chunk-W7CFLOEI.js";
|
|
12
12
|
import "./chunk-S3Q7MDCS.js";
|
|
13
13
|
import {
|
|
14
14
|
getArgValue,
|
|
15
15
|
resolveConfig
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-4MFMPC5P.js";
|
|
17
|
+
import "./chunk-2OHYMT3A.js";
|
|
18
|
+
import "./chunk-RHWPZKRV.js";
|
|
19
19
|
import "./chunk-TOWZAG3I.js";
|
|
20
20
|
|
|
21
21
|
// src/local/start.ts
|
|
@@ -149,4 +149,4 @@ Use \`canary session\` commands to interact with the browser.`);
|
|
|
149
149
|
export {
|
|
150
150
|
runLocalStart
|
|
151
151
|
};
|
|
152
|
-
//# sourceMappingURL=start-
|
|
152
|
+
//# sourceMappingURL=start-PDYBRB5T.js.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; import { fileURLToPath as __fup } from "url"; import { dirname as __dn } from "path"; const require = __cr(import.meta.url); const __filename = __fup(import.meta.url); const __dirname = __dn(__filename);
|
|
2
2
|
import {
|
|
3
3
|
getPositionalArg
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EWK44F6V.js";
|
|
5
5
|
import "./chunk-S3Q7MDCS.js";
|
|
6
6
|
import {
|
|
7
7
|
GLOBAL_VALUE_FLAGS,
|
|
8
8
|
getArgValue,
|
|
9
9
|
hasFlag
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4MFMPC5P.js";
|
|
11
11
|
import {
|
|
12
12
|
writeRawOutput
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-2OHYMT3A.js";
|
|
14
|
+
import "./chunk-RHWPZKRV.js";
|
|
15
15
|
import "./chunk-TOWZAG3I.js";
|
|
16
16
|
|
|
17
17
|
// src/status.ts
|
|
@@ -434,4 +434,4 @@ function printHelp() {
|
|
|
434
434
|
export {
|
|
435
435
|
runStatus
|
|
436
436
|
};
|
|
437
|
-
//# sourceMappingURL=status-
|
|
437
|
+
//# sourceMappingURL=status-VMVPVCDA.js.map
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
runTag,
|
|
8
8
|
splitCsv,
|
|
9
9
|
updateEntityTags
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-C3CXVX2B.js";
|
|
11
|
+
import "./chunk-EWK44F6V.js";
|
|
12
12
|
import "./chunk-S3Q7MDCS.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-4MFMPC5P.js";
|
|
14
|
+
import "./chunk-2OHYMT3A.js";
|
|
15
|
+
import "./chunk-RHWPZKRV.js";
|
|
16
16
|
import "./chunk-TOWZAG3I.js";
|
|
17
17
|
export {
|
|
18
18
|
applyWorkflowTagFlags,
|
|
@@ -23,4 +23,4 @@ export {
|
|
|
23
23
|
splitCsv,
|
|
24
24
|
updateEntityTags
|
|
25
25
|
};
|
|
26
|
-
//# sourceMappingURL=tag-
|
|
26
|
+
//# sourceMappingURL=tag-7KTDLPVU.js.map
|
|
@@ -4,25 +4,25 @@ import {
|
|
|
4
4
|
formatUnknownTagsError,
|
|
5
5
|
resolveTagNames,
|
|
6
6
|
splitCsv
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-C3CXVX2B.js";
|
|
8
8
|
import {
|
|
9
9
|
UUID_RE,
|
|
10
10
|
apiRequest,
|
|
11
11
|
getArgValues,
|
|
12
12
|
getPositionalArgs,
|
|
13
13
|
getTargetOrg
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-EWK44F6V.js";
|
|
15
15
|
import "./chunk-S3Q7MDCS.js";
|
|
16
16
|
import {
|
|
17
17
|
GLOBAL_VALUE_FLAGS,
|
|
18
18
|
getArgValue,
|
|
19
19
|
hasFlag,
|
|
20
20
|
resolveConfig
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-4MFMPC5P.js";
|
|
22
22
|
import {
|
|
23
23
|
writeRawOutput
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-2OHYMT3A.js";
|
|
25
|
+
import "./chunk-RHWPZKRV.js";
|
|
26
26
|
import "./chunk-TOWZAG3I.js";
|
|
27
27
|
|
|
28
28
|
// src/task.ts
|
|
@@ -942,4 +942,4 @@ async function runTask(argv) {
|
|
|
942
942
|
export {
|
|
943
943
|
runTask
|
|
944
944
|
};
|
|
945
|
-
//# sourceMappingURL=task-
|
|
945
|
+
//# sourceMappingURL=task-QLFYZNKR.js.map
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; import { fileURLToPath as __fup } from "url"; import { dirname as __dn } from "path"; const require = __cr(import.meta.url); const __filename = __fup(import.meta.url); const __dirname = __dn(__filename);
|
|
2
2
|
import {
|
|
3
3
|
loadTeamsChannels
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DEVD2WD2.js";
|
|
5
5
|
import {
|
|
6
6
|
apiRequest,
|
|
7
7
|
requireOrgAdmin
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EWK44F6V.js";
|
|
9
9
|
import {
|
|
10
10
|
openUrl
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-K2IDR6FR.js";
|
|
12
12
|
import "./chunk-S3Q7MDCS.js";
|
|
13
13
|
import {
|
|
14
14
|
decodeJwtPayload,
|
|
15
15
|
hasFlag,
|
|
16
16
|
resolveConfig,
|
|
17
17
|
resolveOrgAppUrl
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4MFMPC5P.js";
|
|
19
19
|
import {
|
|
20
20
|
writeRawOutput
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
21
|
+
} from "./chunk-2OHYMT3A.js";
|
|
22
|
+
import "./chunk-RHWPZKRV.js";
|
|
23
23
|
import "./chunk-TOWZAG3I.js";
|
|
24
24
|
|
|
25
25
|
// src/teams.ts
|
|
@@ -200,4 +200,4 @@ export {
|
|
|
200
200
|
teamsConnectUrl,
|
|
201
201
|
teamsInstall
|
|
202
202
|
};
|
|
203
|
-
//# sourceMappingURL=teams-
|
|
203
|
+
//# sourceMappingURL=teams-Y7BXCY6P.js.map
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; import { fileURLToPath as __fup } from "url"; import { dirname as __dn } from "path"; const require = __cr(import.meta.url); const __filename = __fup(import.meta.url); const __dirname = __dn(__filename);
|
|
2
2
|
import {
|
|
3
3
|
formatTeardownLines
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3LGCHNBC.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveSlackChannelIds,
|
|
7
7
|
resolveTeamsChannelValues
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-62EXS76C.js";
|
|
9
|
+
import "./chunk-DEVD2WD2.js";
|
|
10
10
|
import {
|
|
11
11
|
fetchEnvironments,
|
|
12
12
|
resolveEnvironment
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-6ILWJFKY.js";
|
|
14
|
+
import "./chunk-VMJ7TBVM.js";
|
|
15
|
+
import "./chunk-XHEVDABB.js";
|
|
16
16
|
import "./chunk-DEK6B6LX.js";
|
|
17
17
|
import {
|
|
18
18
|
runRemoteTest
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5OYWNS6D.js";
|
|
20
20
|
import {
|
|
21
21
|
UUID_RE,
|
|
22
22
|
apiRequest,
|
|
@@ -27,21 +27,21 @@ import {
|
|
|
27
27
|
getScalarArgValue,
|
|
28
28
|
resolveCredentialId,
|
|
29
29
|
resolveTestSuite
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-EWK44F6V.js";
|
|
31
31
|
import "./chunk-S3Q7MDCS.js";
|
|
32
32
|
import {
|
|
33
33
|
getArgValue,
|
|
34
34
|
hasFlag,
|
|
35
35
|
isSuperadminToken,
|
|
36
36
|
resolveConfig
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-4MFMPC5P.js";
|
|
38
38
|
import {
|
|
39
39
|
writeRawOutput,
|
|
40
40
|
writeUntrustedText
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-2OHYMT3A.js";
|
|
42
42
|
import {
|
|
43
43
|
WORKFLOW_FLOW_TYPES
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-RHWPZKRV.js";
|
|
45
45
|
import "./chunk-TOWZAG3I.js";
|
|
46
46
|
|
|
47
47
|
// src/test-suite.ts
|
|
@@ -1489,8 +1489,8 @@ function printTestSuiteHelp() {
|
|
|
1489
1489
|
" --application <name|id> Target a specific application (alias: --property)",
|
|
1490
1490
|
" --environment <name|id> Target a specific environment (required with --env-mode force)",
|
|
1491
1491
|
" --env-mode <mode> mixed (default \u2014 each flow on its preferred env) | force (pin to --environment)",
|
|
1492
|
-
" --at <sha|pushId|tag> With --suite: pin
|
|
1493
|
-
" or a push id or case-sensitive tag (pushed
|
|
1492
|
+
" --at <sha|pushId|tag> With --suite: pin Sandboxes v2 targets (native or external image suites)",
|
|
1493
|
+
" to a commit SHA (GitHub) or a push id or case-sensitive tag (pushed apps).",
|
|
1494
1494
|
" Mixed GitHub and pushed suites cannot be pinned with one --at.",
|
|
1495
1495
|
" The result shows Pinned at.",
|
|
1496
1496
|
" A pinned run never feeds visual baselines.",
|
|
@@ -1501,6 +1501,7 @@ function printTestSuiteHelp() {
|
|
|
1501
1501
|
" --external-grep <regex> External suites: run only tests whose title matches this regex",
|
|
1502
1502
|
" (can be combined with --area; not with --external-spec)",
|
|
1503
1503
|
" --external-host-shape <shape> External v2 suites: reserve one dedicated host of this exact shape",
|
|
1504
|
+
" --triage <on|off> External suites: automatic AI diagnosis and triage (default: on)",
|
|
1504
1505
|
" --verbose, -v Show all SSE events",
|
|
1505
1506
|
"",
|
|
1506
1507
|
"Choosing which external tests run (all of these need --suite <name|id>):",
|
|
@@ -1697,4 +1698,4 @@ export {
|
|
|
1697
1698
|
handleSuitesList,
|
|
1698
1699
|
runTestSuite
|
|
1699
1700
|
};
|
|
1700
|
-
//# sourceMappingURL=test-suite-
|
|
1701
|
+
//# sourceMappingURL=test-suite-6U22AYFG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/test-suite.ts","../src/test-suite-external.ts","../src/test-suite-declaration.ts","../../test-reporters/src/external-suite-declaration.ts","../../test-reporters/src/playwright-discovery.ts","../../test-reporters/src/mocha-boundary-hook.ts","../../test-reporters/src/visual-attachments.ts","../src/test-suite-catalog.ts"],"sourcesContent":["/**\n * CLI subcommand for querying and triggering test suite (workflow test execution) runs.\n *\n * @module TestSuiteCLI\n */\n\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport {\n apiRequest,\n getArgValues,\n getPositionalArg,\n getScalarArgValue,\n resolveTestSuite,\n} from './cli-helpers.js';\nimport { runRemoteTest } from './remote-test.js';\nimport { UUID_RE } from './cli-helpers.js';\nimport type { WorkflowListResponse } from './workflow-list.js';\nimport { WORKFLOW_FLOW_TYPES } from '@chatsdet/types';\nimport { writeRawOutput, writeUntrustedText } from './brand.js';\nimport { formatTeardownLines, type TeardownSummary } from './teardown-summary.js';\nimport {\n EXTERNAL_CREATE_FLAGS,\n EXTERNAL_RUNNER_FLAGS,\n EXTERNAL_SUITE_FLAGS,\n EXTERNAL_SUITE_HELP_LINES,\n UPDATE_ONLY_RUNNER_FLAGS,\n applyExternalRunnerUpdate,\n buildExternalCreateBlock,\n buildExternalRunnerBodies,\n hasAnyFlag,\n handleSuiteArea,\n} from './test-suite-external.js';\nimport {\n pushTestSuiteBundle,\n testSuitePositionals,\n validateTestSuiteDirectory,\n} from './test-suite-declaration.js';\nimport {\n handleSuiteCatalogGet,\n handleSuitesList,\n type Suite,\n type SuiteDetail,\n type SuiteDetailResponse,\n type SuiteMember,\n type SuiteResponse,\n} from './test-suite-catalog.js';\n\nexport { handleSuitesList };\n\n// ---------------------------------------------------------------------------\n// Types (matching API serializers in apps/api/src/workflows/routes/shared.ts)\n// ---------------------------------------------------------------------------\n\ntype Pagination = {\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n};\n\ntype TestExecutionSummary = {\n id: string;\n status: string;\n totalWorkflows: number;\n completedWorkflows: number;\n failedWorkflows: number;\n successfulWorkflows: number;\n skippedWorkflows: number;\n /** @deprecated Quarantine removed; always 0. Use degradedWorkflows. */\n quarantinedWorkflows: number;\n degradedWorkflows?: number;\n startedAt: string | null;\n finishedAt: string | null;\n createdAt: string;\n};\n\ntype TestExecution = TestExecutionSummary & {\n orgId: string;\n mode: string;\n triggeredByUserId: string | null;\n triggeredReason: string | null;\n errorMessage: string | null;\n updatedAt: string;\n};\n\ntype TestRunResult = {\n id: string;\n testRunId: string;\n workflowId: string;\n nodeId: string;\n status: string;\n message: string | null;\n issueId: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n};\n\ntype TestRun = {\n id: string;\n executionId: string | null;\n workflowId: string;\n status: string;\n snapshotVersion: number;\n workflowRunId: string | null;\n triggeredByUserId: string | null;\n triggeredReason: string | null;\n linkedIssueId: string | null;\n isQuarantined: boolean;\n errorMessage: string | null;\n skipReason: string | null;\n startedAt: string | null;\n finishedAt: string | null;\n workflowName: string | null;\n results: TestRunResult[];\n};\n\ntype TestExecutionListResponse = {\n ok: boolean;\n error?: string;\n data: TestExecutionSummary[];\n pagination: Pagination;\n};\n\ntype TestExecutionDetailResponse = {\n ok: boolean;\n error?: string;\n execution: TestExecution;\n testRuns: TestRun[];\n /** Absent from API servers that predate teardown reporting. */\n teardowns?: TeardownSummary[];\n};\n\ntype RunStep = {\n id: string;\n runId: string;\n nodeId: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n orderIndex: number;\n metadataJson: Record<string, unknown> | null;\n createdAt: string;\n};\n\ntype WorkflowRun = {\n id: string;\n workflowId: string;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n errorMessage: string | null;\n steps: RunStep[];\n};\n\ntype RunWithStepsResponse = {\n ok: boolean;\n error?: string;\n data: { run: WorkflowRun };\n};\n\ntype DiagnosticJson = {\n category?: string;\n title?: string;\n analysis?: string;\n recommendation?: string;\n smokingGun?: { type: string; description: string; detail?: string } | null;\n triage?: { matchedIssueShortcode?: string };\n};\n\ntype DiagnosticThought = {\n content: string;\n toolName: string | null;\n orderIndex: number;\n createdAt: string;\n};\n\ntype FailureDiagnosticResponse = {\n ok: boolean;\n error?: string;\n data: {\n id: string;\n status: string;\n diagnostic: DiagnosticJson | null;\n createdAt: string;\n updatedAt: string;\n thoughts?: DiagnosticThought[];\n } | null;\n};\n\n// ---------------------------------------------------------------------------\n// Suite CRUD + membership types (matching apps/api/src/test-suites/{routes,schemas}.ts)\n// ---------------------------------------------------------------------------\n\ntype SuiteMembersResponse = { ok: boolean; error?: string; data?: { members: SuiteMember[] } };\n/** `DELETE /test-suites/:id` — archives the suite, run history retained. */\ntype SuiteDeleteResponse = {\n ok: boolean;\n error?: string;\n data?: { id: string; archivedAt: string | null };\n};\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nconst STATUS_ICONS: Record<string, string> = {\n completed: '✅',\n completed_with_errors: '⚠️',\n success: '✅',\n failed: '❌',\n running: '🔵',\n queued: '⏳',\n canceled: '🚫',\n timeout: '⏰',\n skipped: '⏭️',\n flaky_success: '🟡',\n pending: '⏳',\n};\n\nfunction statusIcon(status: string): string {\n return STATUS_ICONS[status] ?? '❓';\n}\n\nfunction formatRelative(iso: string | null): string {\n if (!iso) return '—';\n const diffMs = Date.now() - new Date(iso).getTime();\n if (diffMs < 0) return 'just now';\n const seconds = Math.floor(diffMs / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\nfunction computeDuration(startedAt: string | null, finishedAt: string | null): string {\n if (!startedAt || !finishedAt) return '—';\n const ms = new Date(finishedAt).getTime() - new Date(startedAt).getTime();\n if (ms < 0) return '—';\n const totalSeconds = Math.floor(ms / 1000);\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes < 60) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n const remainMins = minutes % 60;\n return remainMins > 0 ? `${hours}h ${remainMins}m` : `${hours}h`;\n}\n\nfunction pad(str: string, len: number): string {\n return str.padEnd(len);\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const page = getArgValue(argv, '--page') ?? '1';\n const pageSize = getArgValue(argv, '--page-size') ?? '20';\n\n const params = new URLSearchParams();\n params.set('page', page);\n params.set('pageSize', pageSize);\n params.set('sortBy', 'createdAt');\n params.set('sortOrder', 'desc');\n\n const result = await apiRequest<TestExecutionListResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/test-executions?${params}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(result, null, 2));\n return;\n }\n\n const { data, pagination } = result;\n\n if (data.length === 0) {\n console.log('No test suites found.');\n return;\n }\n\n console.log(\n `Test Suites (page ${pagination.page}/${pagination.totalPages}, ${pagination.totalItems} total)\\n`\n );\n\n for (const exec of data) {\n const icon = statusIcon(exec.status);\n const total = String(exec.totalWorkflows).padStart(3);\n const passed = String(exec.successfulWorkflows).padStart(3);\n const failed = String(exec.failedWorkflows).padStart(3);\n const time = formatRelative(exec.createdAt);\n\n console.log(\n ` ${icon} ${exec.id} ${total} total ${passed} passed ${failed} failed ${time}`\n );\n }\n\n console.log('');\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const id = argv.find((a) => !a.startsWith('-'));\n if (!id) {\n console.error('Error: Missing execution ID. Usage: canary test-suite get <executionId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const failuresOnly = hasFlag(argv, '--failures-only');\n\n const result = await apiRequest<TestExecutionDetailResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/test-executions/${id}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n const output = failuresOnly\n ? { ...result, testRuns: result.testRuns.filter((r) => r.status === 'failed') }\n : result;\n writeRawOutput(JSON.stringify(output, null, 2));\n return;\n }\n\n const { execution, testRuns } = result;\n const duration = computeDuration(execution.startedAt, execution.finishedAt);\n\n console.log(`Test Suite: ${execution.id}`);\n console.log(`Status: ${statusIcon(execution.status)} ${execution.status}`);\n console.log(`Duration: ${duration}`);\n console.log(\n `Total: ${execution.totalWorkflows} | Passed: ${execution.successfulWorkflows} | Failed: ${execution.failedWorkflows} | Skipped: ${execution.skippedWorkflows} | Degraded: ${execution.degradedWorkflows ?? 0}`\n );\n console.log('');\n\n let runs = testRuns;\n if (failuresOnly) {\n runs = runs.filter((r) => r.status === 'failed');\n if (runs.length === 0) console.log('No failing runs.');\n }\n\n if (runs.length > 0) console.log('Runs:');\n for (const run of runs) {\n const icon = statusIcon(run.status);\n const name = run.workflowName ?? 'Unnamed';\n const dur = computeDuration(run.startedAt, run.finishedAt);\n const runId = run.workflowRunId ?? '—';\n\n console.log(` ${icon} ${pad(name, 30)} ${dur}`);\n console.log(` wf: ${run.workflowId} run: ${runId}`);\n\n if (run.errorMessage) {\n writeRawOutput(` Error: ${run.errorMessage}`);\n }\n if (run.skipReason) {\n console.log(` Skip reason: ${run.skipReason}`);\n }\n if (run.linkedIssueId) {\n console.log(` Linked issue: ${run.linkedIssueId}`);\n }\n }\n\n console.log('');\n\n // Teardowns run after the flows; a failed one is why a green suite can end\n // completed_with_errors, so show it even under --failures-only.\n const allTeardowns = result.teardowns ?? [];\n const teardowns = failuresOnly\n ? allTeardowns.filter((t) => t.status === 'failed')\n : allTeardowns;\n if (teardowns.length > 0) {\n console.log('Teardowns:');\n for (const line of formatTeardownLines(teardowns)) writeUntrustedText(line);\n console.log('');\n }\n\n if (execution.failedWorkflows > 0) {\n console.log(`Triage: canary triage get ${execution.id}`);\n console.log('');\n }\n}\n\nasync function handleDiagnostics(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n if (positional.length < 2) {\n console.error(\n 'Error: Missing arguments. Usage: canary test-suite diagnostics <workflowId> <runId>'\n );\n process.exit(1);\n }\n\n const [workflowId, runId] = positional;\n const jsonOutput = hasFlag(argv, '--json');\n const showThoughts = hasFlag(argv, '--thoughts');\n\n const result = await apiRequest<FailureDiagnosticResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}/failure-diagnostic${\n showThoughts ? '?includeThoughts=true' : ''\n }`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(result, null, 2));\n return;\n }\n\n if (!result.data) {\n console.log('No diagnostic available for this run.');\n return;\n }\n\n const { status, diagnostic } = result.data;\n\n if (status === 'pending' || status === 'running') {\n console.log(`Diagnostic is still in progress (status: ${status}).`);\n return;\n }\n\n if (status === 'failed') {\n console.log('Diagnostic analysis failed.');\n return;\n }\n\n if (!diagnostic) {\n console.log('Diagnostic completed but no analysis data available.');\n return;\n }\n\n console.log('Failure Diagnostic');\n console.log(`Status: ${status}`);\n if (diagnostic.category) {\n console.log(`Category: ${diagnostic.category}`);\n }\n if (diagnostic.title) {\n writeRawOutput(`Title: ${diagnostic.title}`);\n }\n if (diagnostic.triage) {\n writeRawOutput(`Repeat: confirmed repeat failure${diagnostic.triage.matchedIssueShortcode ? ` (issue ${diagnostic.triage.matchedIssueShortcode})` : ''}`);\n }\n\n if (diagnostic.analysis) {\n console.log('');\n console.log('Analysis:');\n writeRawOutput(` ${diagnostic.analysis}`);\n }\n\n if (diagnostic.recommendation) {\n console.log('');\n console.log('Recommendation:');\n writeRawOutput(` ${diagnostic.recommendation}`);\n }\n\n if (diagnostic.smokingGun) {\n console.log('');\n console.log('Smoking Gun:');\n writeRawOutput(` > ${diagnostic.smokingGun.description}`);\n if (diagnostic.smokingGun.detail) {\n writeRawOutput(` ${diagnostic.smokingGun.detail}`);\n }\n }\n\n if (showThoughts) {\n const thoughts = result.data.thoughts ?? [];\n console.log('');\n console.log(`Agent reasoning (${thoughts.length} step${thoughts.length === 1 ? '' : 's'}):`);\n if (thoughts.length === 0) {\n console.log(' (no reasoning trace captured for this diagnostic)');\n } else {\n for (const t of thoughts) {\n const tool = t.toolName ? ` → ${t.toolName}()` : '';\n console.log(` [${t.orderIndex}]${tool}`);\n for (const line of t.content.split('\\n')) {\n console.log(` ${line}`);\n }\n }\n }\n }\n\n console.log('');\n}\n\nasync function handleSteps(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n if (positional.length < 2) {\n console.error('Error: Missing arguments. Usage: canary test-suite steps <workflowId> <runId>');\n process.exit(1);\n }\n\n const [workflowId, runId] = positional;\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<RunWithStepsResponse>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/runs/${runId}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(result, null, 2));\n return;\n }\n\n const { run } = result.data;\n const duration = computeDuration(run.startedAt, run.finishedAt);\n\n console.log(`Run: ${run.id} (${run.status})`);\n console.log(`Duration: ${duration}`);\n\n if (run.errorMessage) {\n writeRawOutput(`Error: ${run.errorMessage}`);\n }\n\n const steps = (run.steps ?? []).sort((a, b) => a.orderIndex - b.orderIndex);\n\n if (steps.length === 0) {\n console.log('\\nNo steps recorded.');\n return;\n }\n\n console.log(`\\nSteps (${steps.length}):`);\n for (const step of steps) {\n const idx = String(step.orderIndex + 1).padStart(2);\n const icon = statusIcon(step.status);\n const nodeId = step.nodeId.slice(0, 8);\n const dur = computeDuration(step.startedAt, step.finishedAt);\n\n console.log(` ${idx}. ${icon} ${pad(nodeId, 10)} ${dur}`);\n\n if (step.errorMessage) {\n writeRawOutput(` Error: ${step.errorMessage}`);\n }\n }\n\n console.log('');\n}\n\n// ---------------------------------------------------------------------------\n// Suite CRUD + membership handlers\n// ---------------------------------------------------------------------------\n\n/** Flags create/update/delete/members/set-members accept that consume the following argv entry. */\nconst SUITE_WRITE_FLAGS = [\n '--name',\n '--description',\n '--failure-mode',\n '--layer',\n '--staging',\n '--env',\n '--api-url',\n '--token',\n '--org',\n ...EXTERNAL_SUITE_FLAGS,\n];\n\n/**\n * Resolve one `--layer`/`--staging` entry (a flow id or name) to a flow UUID.\n * Ambiguous or unknown names exit 1 rather than guessing — duplicate flow\n * names are real in production, and silently picking one would put the wrong\n * flow in a suite.\n */\nasync function resolveFlowRef(ref: string, apiUrl: string, token: string): Promise<string> {\n if (UUID_RE.test(ref)) return ref;\n\n // Explicit flowType: GET /workflows defaults to excluding seed/teardown\n // flows when the param is omitted (apps/api \"standard listing\" default).\n //\n // pageSize 200, not 50: search matches name OR description, so a common\n // word inflates totalItems with flows that merely mention it in prose. The\n // truncation refusal below stays absolute either way — refusing loudly\n // beats silently setting the wrong flow — 200 just shrinks how often a\n // short, common name trips it for no ambiguity reason.\n const params = new URLSearchParams({\n search: ref,\n pageSize: '200',\n flowType: WORKFLOW_FLOW_TYPES.join(','),\n });\n const result = await apiRequest<WorkflowListResponse>(apiUrl, token, 'GET', `/workflows?${params}`);\n if (!result.ok) {\n // `ref` echoes the user's own --layer/--staging entry — write it straight\n // to stderr rather than through console.error, which would rewrite a\n // flow named e.g. \"Canary Smoke\".\n process.stderr.write(`Error: Failed to look up flow \"${ref}\": ${result.error ?? 'Unknown error'}\\n`);\n process.exit(1);\n }\n // `WorkflowListResponse.data` is non-optional and `!result.ok` already\n // exited above, so `result.data` is always an array here.\n const data = result.data;\n const totalItems = result.pagination.totalItems;\n if (totalItems > data.length) {\n // A truncated page is not trustworthy for a NAME lookup either way it\n // could go wrong: zero matches on this page while the real one sits past\n // it (a false \"not found\"), or exactly one match on this page while a\n // same-named duplicate sits past it (a false, confidently wrong, unique\n // match). One rule covers both — never guess past a truncated page.\n process.stderr.write(\n `Error: \"${ref}\" matches more than the first ${data.length} of ${totalItems} flows returned ` +\n `by search — can't confirm the name isn't ambiguous. Pass the flow id instead, or use a ` +\n `more specific name.\\n`\n );\n process.exit(1);\n }\n const matches = data.filter((w) => w.name.toLowerCase() === ref.toLowerCase());\n if (matches.length === 0) {\n process.stderr.write(`Error: No flow named \"${ref}\" found. Pass the flow id instead of the name.\\n`);\n process.exit(1);\n }\n if (matches.length > 1) {\n process.stderr.write(`Error: Multiple flows are named \"${ref}\":\\n`);\n for (const m of matches) console.error(` - ${m.id}`);\n console.error('Pass the flow id instead to disambiguate.');\n process.exit(1);\n }\n return matches[0]!.id;\n}\n\n/**\n * Resolve a comma-separated `--layer`/`--staging` value into flow ids, in\n * order. A flow name containing a comma cannot be expressed this way — pass\n * its id instead.\n */\nasync function resolveFlowListArg(\n raw: string,\n apiUrl: string,\n token: string,\n cache: Map<string, string>\n): Promise<string[]> {\n const refs = raw\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n const ids: string[] = [];\n for (const ref of refs) {\n let id = cache.get(ref);\n if (!id) {\n id = await resolveFlowRef(ref, apiUrl, token);\n cache.set(ref, id);\n }\n ids.push(id);\n }\n return ids;\n}\n\n/**\n * Build the create/update body from flags. Returns only the keys actually\n * supplied, so `update` patches rather than blanking every omitted field.\n * `UpdateTestSuiteBody` only carries name/description/failureMode/\n * environmentId/alertConfig — `kind` is create-only and not settable here.\n */\nfunction buildSuiteWriteBody(argv: string[]): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n\n const name = getScalarArgValue(argv, '--name');\n if (name !== undefined) body.name = name;\n\n // `--description \"\"` is the only way to clear a description, so an empty\n // value is meaningful here where it is a mistake for the other two.\n const description = getScalarArgValue(argv, '--description', { allowEmpty: true });\n if (description !== undefined) body.description = description;\n\n const failureMode = getScalarArgValue(argv, '--failure-mode');\n if (failureMode !== undefined) {\n if (failureMode !== 'continue' && failureMode !== 'stop_on_layer_failure') {\n console.error(\n `Error: --failure-mode must be \"continue\" or \"stop_on_layer_failure\" (got \"${failureMode}\").`\n );\n process.exit(1);\n }\n body.failureMode = failureMode;\n }\n\n return body;\n}\n\nexport async function handleSuiteCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const body = buildSuiteWriteBody(argv);\n\n if (typeof body.name !== 'string' || !body.name.trim()) {\n console.error('Error: --name is required.');\n console.error('Usage: canary test-suite create --name <name> [options]');\n process.exit(1);\n }\n\n const kind = getScalarArgValue(argv, '--kind');\n if (kind !== undefined && kind !== 'native' && kind !== 'external') {\n console.error(`Error: --kind must be \"native\" or \"external\" (got \"${kind}\").`);\n process.exit(1);\n }\n // Refuse rather than drop: a runner flag on `create` would otherwise print\n // \"✓ Created\" over an unconfigured runner, and a repo without `--kind\n // external` would quietly make a native suite.\n if (hasAnyFlag(argv, UPDATE_ONLY_RUNNER_FLAGS)) {\n console.error(\n 'Error: runner flags are set with \"test-suite update <suite> …\" after the suite exists.'\n );\n process.exit(1);\n }\n if (kind !== 'external' && hasAnyFlag(argv, EXTERNAL_SUITE_FLAGS.filter((f) => f !== '--kind'))) {\n console.error(\n 'Error: --provider/--source/--repo/--ref/--property/--environment/--credential/--application require --kind external.'\n );\n process.exit(1);\n }\n let repoLabel: string | undefined;\n if (kind === 'external') {\n const { external, repo, propertyName } = await buildExternalCreateBlock(argv, apiUrl, token);\n body.kind = 'external';\n body.external = external;\n repoLabel = repo ? `${repo.repoFullName} (${repo.propertyName})` : `uploaded bundle (${propertyName})`;\n }\n\n const res = await apiRequest<SuiteResponse>(apiUrl, token, 'POST', '/test-suites', body);\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to create test suite'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n // res.data.name is server-supplied — writeRawOutput, not console.log, so it\n // can't be brand-rewritten (e.g. a suite literally named \"Canary Smoke\").\n writeRawOutput(`✓ Created test suite \"${res.data.name}\" (${res.data.id})`);\n if (repoLabel) writeRawOutput(` external · ${repoLabel}`);\n console.log('');\n console.log('Next:');\n if (kind === 'external') {\n console.log(\n ` canary test-suite update ${res.data.id} --sandbox-template <id> --sandbox-action <slug> ` +\n `[--env-map KEY='$var.USER.KEY'] [--spec <dir/>]`\n );\n console.log(` canary test-suite run --suite ${res.data.id}`);\n } else {\n console.log(` canary test-suite set-members ${res.data.id} --layer <flow[,flow...]>`);\n }\n}\n\nexport async function handleSuiteUpdate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, SUITE_WRITE_FLAGS);\n if (!arg) {\n console.error('Usage: canary test-suite update <id|name> [options]');\n process.exit(1);\n }\n if (hasAnyFlag(argv, EXTERNAL_CREATE_FLAGS)) {\n console.error('Error: --kind and --provider are create-only; a suite\\'s engine cannot change.');\n process.exit(1);\n }\n const suite = await resolveTestSuite(arg, apiUrl, token);\n const jsonOutput = hasFlag(argv, '--json');\n const body = buildSuiteWriteBody(argv);\n\n // Runner flags need the suite's current runner (its application scopes the\n // environment/credential name lookups), so only fetch the detail when one\n // was given — a plain `--name` rename stays a single PATCH.\n let runnerBodies: Awaited<ReturnType<typeof buildExternalRunnerBodies>> = {};\n if (hasAnyFlag(argv, EXTERNAL_RUNNER_FLAGS)) {\n const detail = await fetchSuiteDetail(suite.id, apiUrl, token);\n if (detail.kind !== 'external' || !detail.externalRunner) {\n process.stderr.write(\n `Error: \"${detail.name}\" is a native suite; runner flags (${EXTERNAL_RUNNER_FLAGS.join(', ')}) ` +\n `apply to external suites only.\\n`\n );\n process.exit(1);\n }\n runnerBodies = await buildExternalRunnerBodies(argv, detail.externalRunner, apiUrl, token);\n }\n\n if (\n Object.keys(body).length === 0 &&\n !runnerBodies.runner &&\n !runnerBodies.advanced &&\n !runnerBodies.areas\n ) {\n console.error(\n 'Error: No fields to update. Provide at least one of: --name, --description, --failure-mode, ' +\n `or a runner flag (${EXTERNAL_RUNNER_FLAGS.join(', ')})`\n );\n process.exit(1);\n }\n\n // Runner configuration first (superadmin half first of all — see\n // `applyExternalRunnerUpdate`), suite fields last: the request most likely to\n // be refused runs before anything is written.\n const { runner, applied } = await applyExternalRunnerUpdate(suite.id, runnerBodies, apiUrl, token);\n let updated: Suite | undefined;\n if (Object.keys(body).length > 0) {\n const res = await apiRequest<SuiteResponse>(apiUrl, token, 'PATCH', `/test-suites/${suite.id}`, body);\n if (!res.ok || !res.data) {\n if (applied.length > 0) {\n process.stderr.write(`Already applied before this failure: ${applied.join(', ')}.\\n`);\n }\n console.error(`Error: ${res.error ?? 'Failed to update test suite'}`);\n process.exit(1);\n }\n updated = res.data;\n }\n\n if (jsonOutput) {\n // One shape regardless of which flags were given: the suite id/name plus\n // whichever halves this call wrote (absent keys were not touched).\n writeRawOutput(\n JSON.stringify(\n { id: suite.id, name: (updated ?? suite).name, ...(updated ? { suite: updated } : {}), ...(runner ? { externalRunner: runner } : {}) },\n null,\n 2\n )\n );\n return;\n }\n writeRawOutput(`✓ Updated test suite \"${(updated ?? suite).name}\" (${suite.id})`);\n if (runnerBodies.advanced) console.log(' runner command updated');\n if (runnerBodies.runner) console.log(' runner config updated');\n}\n\nasync function handleSuiteDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, SUITE_WRITE_FLAGS);\n if (!arg) {\n console.error('Usage: canary test-suite delete <id|name> [--yes]');\n process.exit(1);\n }\n const jsonOutput = hasFlag(argv, '--json');\n const suite = await resolveTestSuite(arg, apiUrl, token);\n\n if (!hasFlag(argv, '--yes')) {\n // suite.name is server-supplied — write it straight to stderr rather than\n // through console.error, which the `cofactor` binary brand-rewrites.\n process.stderr.write(`Refusing to delete \"${suite.name}\" (${suite.id}) without --yes.\\n`);\n console.error('Automations and CLI runs pointing at this suite will fail once it is deleted.');\n process.exit(1);\n }\n\n const res = await apiRequest<SuiteDeleteResponse>(apiUrl, token, 'DELETE', `/test-suites/${suite.id}`);\n if (!res.ok || !res.data) {\n // `res.ok && !res.data` is a server contract break, not a case to paper\n // over — synthesizing `{ id, name }` here would print a DIFFERENT shape\n // than the route's real `{ id, archivedAt }`, so a script reading\n // `.archivedAt` couldn't tell \"not archived\" from \"the CLI invented this.\"\n console.error(`Error: ${res.error ?? 'Failed to delete test suite'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n // Every other write verb prints `res.data` under --json; delete was the\n // one silent exception.\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n writeRawOutput(`✓ Deleted test suite \"${suite.name}\" (${suite.id})`);\n}\n\nasync function fetchSuiteDetail(id: string, apiUrl: string, token: string): Promise<SuiteDetail> {\n const res = await apiRequest<SuiteDetailResponse>(apiUrl, token, 'GET', `/test-suites/${id}`);\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to load test suite'}`);\n process.exit(1);\n }\n return res.data;\n}\n\nasync function handleSuiteMembers(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, SUITE_WRITE_FLAGS);\n if (!arg) {\n console.error('Usage: canary test-suite members <id|name> [--json]');\n process.exit(1);\n }\n const suite = await resolveTestSuite(arg, apiUrl, token);\n const detail = await fetchSuiteDetail(suite.id, apiUrl, token);\n\n if (hasFlag(argv, '--json')) {\n writeRawOutput(JSON.stringify(detail, null, 2));\n return;\n }\n\n // The suite name and every workflowName below are server-supplied data —\n // route them through writeRawOutput, never console.log, so a name that\n // happens to contain the prose noun \"Canary\" can't be brand-rewritten.\n writeRawOutput(`${detail.name} (${detail.id})`);\n if (detail.members.length === 0) {\n console.log(' (no members)');\n return;\n }\n\n const layered = detail.members.filter((m) => m.layerIndex !== null);\n const staging = detail.members.filter((m) => m.layerIndex === null);\n\n const byLayer = new Map<number, SuiteMember[]>();\n for (const m of layered) {\n const arr = byLayer.get(m.layerIndex as number) ?? [];\n arr.push(m);\n byLayer.set(m.layerIndex as number, arr);\n }\n for (const [layerIndex, members] of [...byLayer.entries()].sort(([a], [b]) => a - b)) {\n console.log(` Layer ${layerIndex}:`);\n for (const m of members.sort((a, b) => a.orderIndex - b.orderIndex)) {\n writeRawOutput(` - ${m.workflowName} (${m.workflowId}) [${m.health}]`);\n }\n }\n\n if (staging.length > 0) {\n console.log(' Staging (excluded from runs):');\n for (const m of staging.sort((a, b) => a.orderIndex - b.orderIndex)) {\n writeRawOutput(` - ${m.workflowName} (${m.workflowId}) [${m.health}]`);\n }\n }\n}\n\nexport async function handleSuiteSetMembers(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const arg = getPositionalArg(argv, SUITE_WRITE_FLAGS);\n if (!arg) {\n console.error('Usage: canary test-suite set-members <id|name> --layer <flow[,flow...]> [options]');\n process.exit(1);\n }\n const layerArgs = getArgValues(argv, '--layer');\n const stagingArgs = getArgValues(argv, '--staging');\n if (layerArgs.length === 0 && stagingArgs.length === 0) {\n console.error(\n 'Error: Nothing to set. Provide at least one --layer <flow[,flow...]> (repeatable) ' +\n 'and/or --staging <flow[,flow...]>.'\n );\n process.exit(1);\n }\n\n const suite = await resolveTestSuite(arg, apiUrl, token);\n const jsonOutput = hasFlag(argv, '--json');\n const confirmed = hasFlag(argv, '--yes');\n\n // Full replace — destroys any existing membership not listed above. Confirm\n // before wiping a suite that already has members; an empty suite needs no\n // confirmation since nothing is lost. Checked before resolving any flow\n // names, so a refusal doesn't first burn an API call per --layer entry.\n // Skipped entirely with --yes: the member count it would fetch only feeds a\n // message the user has already opted past, so there is no reason to spend\n // the round trip on the path agents always take.\n if (!confirmed) {\n const existing = await fetchSuiteDetail(suite.id, apiUrl, token);\n if (existing.members.length > 0) {\n // suite.name is server-supplied — write straight to stderr, bypassing\n // console.error's brand rewrite.\n process.stderr.write(\n `Refusing to replace ${existing.members.length} existing member(s) of \"${suite.name}\" ` +\n `(${suite.id}) without --yes.\\n`\n );\n console.error('set-members is a FULL REPLACE — anything not listed is removed from the suite.');\n process.exit(1);\n }\n }\n\n const cache = new Map<string, string>();\n const layers: string[][] = [];\n for (const layerArg of layerArgs) {\n layers.push(await resolveFlowListArg(layerArg, apiUrl, token, cache));\n }\n const staging: string[] = [];\n for (const stagingArg of stagingArgs) {\n staging.push(...(await resolveFlowListArg(stagingArg, apiUrl, token, cache)));\n }\n\n if (!jsonOutput) {\n // Gated on !jsonOutput like every sibling handler — otherwise `set-members\n // --json | jq` gets this prose ahead of the JSON payload and fails to parse.\n writeRawOutput(`Setting members of \"${suite.name}\" (${suite.id}):`);\n layers.forEach((layer, i) => console.log(` Layer ${i}: ${layer.length} flow(s)`));\n if (staging.length > 0) console.log(` Staging: ${staging.length} flow(s)`);\n }\n\n const res = await apiRequest<SuiteMembersResponse>(\n apiUrl,\n token,\n 'PUT',\n `/test-suites/${suite.id}/members`,\n { layers, staging }\n );\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to set suite members'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n writeRawOutput(`✓ Set ${res.data.members.length} member(s) on \"${suite.name}\"`);\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printTestSuiteHelp(): void {\n console.log(\n [\n 'Usage: canary test-suite <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' run [options] Trigger a test suite and stream results',\n ' suites [--json] List named suite definitions',\n ' suites get <id|name> [--json] Inspect a named suite',\n ' executions [options] List recent test suite executions',\n ' list [options] (deprecated — will list suite definitions in future; use executions/suites)',\n ' get <executionId> [options] Show one execution\\'s runs',\n ' diagnostics <workflowId> <runId> Get failure diagnostic for a run (--thoughts for the agent reasoning trace)',\n ' steps <workflowId> <runId> Get workflow run steps',\n ' create [options] Create a named test suite',\n ' validate <directory> Validate cofactor.tests.yaml locally',\n ' push <suite-id|name> <directory> Upload an immutable test bundle',\n ' update <id|name> [options] Update suite fields',\n ' delete <id|name> [--yes] Delete a test suite',\n ' members <id|name> [--json] Show the suite\\'s members by layer',\n ' set-members <id|name> [options] Replace the suite\\'s members (full replace)',\n ' area settings <suite> <area> [options] An external suite area\\'s own alerts and triage:',\n ' --slack <channel>, --teams <channel> and/or --email <a,b>',\n ' replace ALL its destinations (pass every one to keep);',\n ' channels take a name like `alert create`;',\n ' --no-alerts clears them; --triage on|off',\n ' area disable|enable <suite> <area> Turn an external suite area off (kept, not run) or',\n ' back on. <area> is its path or last segment',\n '',\n 'After a run, the execution id (from `run`, `executions`, or `get`) can be passed to triage commands:',\n ' canary triage wait <executionId> Block until AI clusters failures (beta)',\n ' canary triage get <executionId> Show clustered failures + suggested actions',\n ' canary triage get latest Resolves to the most recent execution',\n '',\n 'Run options:',\n ' --suite <name|id> Run a named, layered test suite (members run in layer order)',\n ' --application <name|id> Target a specific application (alias: --property)',\n ' --environment <name|id> Target a specific environment (required with --env-mode force)',\n ' --env-mode <mode> mixed (default — each flow on its preferred env) | force (pin to --environment)',\n ' --at <sha|pushId|tag> With --suite: pin Sandboxes v2 targets (native or external image suites)',\n ' to a commit SHA (GitHub) or a push id or case-sensitive tag (pushed apps).',\n ' Mixed GitHub and pushed suites cannot be pinned with one --at.',\n ' The result shows Pinned at.',\n ' A pinned run never feeds visual baselines.',\n ' --tag <tag> Filter workflows by tag',\n ' --name-pattern <pat> Filter workflows by name pattern',\n ' --area <a,b> External suites: run only these areas (one sandbox each)',\n ' --external-spec <path> External suites: run one spec path instead of the suite',\n ' --external-grep <regex> External suites: run only tests whose title matches this regex',\n ' (can be combined with --area; not with --external-spec)',\n ' --external-host-shape <shape> External v2 suites: reserve one dedicated host of this exact shape',\n ' --triage <on|off> External suites: automatic AI diagnosis and triage (default: on)',\n ' --verbose, -v Show all SSE events',\n '',\n 'Choosing which external tests run (all of these need --suite <name|id>):',\n ' Whole suite run --suite acme/all',\n ' Some areas run --suite acme/all --area billing,checkout',\n ' An area is a configured directory; name it by its path or',\n ' its last segment. Each area runs in its own sandbox.',\n ' One spec path run --suite acme/all --external-spec tests/smoke.spec.js',\n ' Runs that path in a single sandbox. Not combinable with --area.',\n ' By title run --suite acme/all --external-grep \"@smoke\"',\n ' A JavaScript regular expression matched against test titles,',\n ' so a tag written in the title (@smoke) selects by tag. Quote it',\n ' so the shell passes it through. Use \\\\b for word boundaries',\n ' (\"\\\\bcheckout\\\\b\"). Exclude with a negative lookahead:',\n ' --external-grep \"^(?!.*@wip)\" runs everything except @wip.',\n ' Areas, by title run --suite acme/all --area billing --external-grep \"@smoke\"',\n ' Only the named areas run, and within them only matching',\n ' titles. Supported for Playwright suites; other frameworks',\n ' reject the combination rather than run a wider scope.',\n ' With several areas, an area with no match reports no tests;',\n ' a single-area run that matches nothing fails.',\n ' Re-run a finished run external-run rerun <run-id> [--failed] [--area <label|index>]',\n ' --failed re-runs the tests that failed, were flaky or skipped;',\n ' --area re-runs one area (see `external-run get <run-id>`).',\n '',\n 'Executions/list options:',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 20)',\n '',\n 'Get options:',\n ' --failures-only Show only failing test runs',\n '',\n 'Create/update options:',\n ' --name <name> Suite name (required on create)',\n ' --description <text> Suite description',\n ' --failure-mode <mode> continue | stop_on_layer_failure',\n '',\n ...EXTERNAL_SUITE_HELP_LINES,\n 'Set-members options:',\n ' --layer <flow[,flow...]> One layer, repeatable; entries are flow ids or names',\n ' (comma-separated — a name containing a comma must be',\n ' passed by id). Layer order = flag order.',\n ' --staging <flow[,flow...]> Members parked outside the run order',\n ' --yes Required to replace a suite that already has members',\n '',\n 'Output options:',\n ' --json Output raw JSON',\n ' Root shape differs by verb: executions/list emits',\n ' {ok, data, pagination}; get/diagnostics/steps emit',\n ' their own {ok, ...} envelope (no pagination — each',\n \" addresses a single execution/run); the suite CRUD\",\n ' verbs (suites, create, update, delete, members,',\n ' set-members) emit the resource itself (an array',\n ' for suites, an object for the rest) — no envelope.',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n '',\n 'Exit codes (run):',\n ' 0 Every runnable test settled, none failed',\n ' 1 One or more tests failed, timed out, or were canceled',\n ' 2 No failures, but one or more tests were inconclusive —',\n ' a platform error meant the product was never checked,',\n ' so the suite proves nothing. Distinct from 1 so CI can',\n ' tell a product bug from infrastructure that never ran.',\n '',\n 'Examples:',\n ' canary test-suite run Run all workflow tests',\n ' canary test-suite run --suite \"Checkout flow\" Run a named, layered suite',\n ' canary test-suite run --tag smoke Run smoke-tagged workflows',\n ' canary test-suite run --suite \"Checkout flow\" --env-mode force --environment staging',\n ' canary test-suite run --suite \"Checkout flow\" --at 0123456789abcdef0123456789abcdef01234567',\n ' canary test-suite run --suite \"web-e2e\" --area billing_invoices,onboarding',\n ' canary test-suite run --suite \"web-e2e\" --area billing_invoices --external-grep \"@smoke\"',\n ' canary test-suite area disable \"web-e2e\" alerts',\n ' canary test-suite run --suite \"Browser tests\" --external-spec tests/smoke.spec.js',\n ' canary test-suite run --suite \"Browser tests\" --external-grep \"checkout\"',\n ' canary test-suite run --application \"My App\" --environment staging',\n ' canary test-suite suites List named suite definitions',\n ' canary test-suite executions List recent suite executions',\n ' canary test-suite get <executionId> --failures-only Show only failures',\n ' canary test-suite get <executionId> --failures-only --json Failures as JSON',\n ' canary test-suite create --name \"Checkout flow\" --failure-mode continue',\n ' canary test-suite create --name \"acme/billing_invoices\" --kind external --provider playwright \\\\',\n ' --repo acme/web-e2e --ref develop --environment Staging --credential Staging',\n ' canary test-suite update \"acme/billing_invoices\" --sandbox-template <id> --sandbox-action playwright-run-suite \\\\',\n \" --env-map APP_SECRET='$var.USER.APP_SECRET' --env-map TEST_ENV=staging --spec .features-gen/bdd/features/billing_invoices/\",\n ' canary test-suite set-members \"Checkout flow\" --layer \"Login,Add to cart\" --layer Checkout',\n ' canary test-suite members \"Checkout flow\" Show members grouped by layer',\n ].join('\\n')\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nexport async function runTestSuite(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printTestSuiteHelp();\n return;\n }\n\n if (subCommand === 'run') {\n // Delegate to runRemoteTest — pass through remaining args\n await runRemoteTest(rest);\n return;\n }\n\n if (subCommand === 'validate') {\n const knownValueFlags = new Set(['--api-url', '--env', '--org', '--token']);\n for (let index = 0; index < rest.length; index += 1) {\n const arg = rest[index]!;\n if (arg === '--json') continue;\n if (knownValueFlags.has(arg)) {\n if (!rest[index + 1] || rest[index + 1]!.startsWith('-')) {\n console.error(`Error: ${arg} requires a value.`);\n process.exit(1);\n }\n index += 1;\n continue;\n }\n if (/^--(?:api-url|env|org|token)=/.test(arg)) continue;\n if (arg.startsWith('-')) {\n console.error(`Error: Unknown validate option: ${arg}`);\n process.exit(1);\n }\n }\n const [directory] = testSuitePositionals(rest);\n if (!directory) {\n console.error('Usage: cofactor test-suite validate <directory>');\n process.exit(1);\n }\n if (testSuitePositionals(rest).length !== 1) {\n console.error('Error: validate accepts exactly one directory.');\n process.exit(1);\n }\n await validateTestSuiteDirectory(directory, { json: hasFlag(rest, '--json') });\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case 'list':\n // Stderr, unconditionally (including under --json) — a scripted caller\n // is exactly who needs to migrate before `list`'s meaning changes, and\n // stderr can't corrupt stdout the way a stdout notice would.\n console.error(\n 'warning: \"test-suite list\" currently shows executions and will list suite definitions in ' +\n 'a future release — including under --json, where the root shape will change from an ' +\n 'object ({ok, data, pagination}) to a bare array, matching \"suites\". Use \"test-suite ' +\n 'executions\" for executions or \"test-suite suites\" for suite definitions.'\n );\n await handleList(rest, apiUrl, token);\n break;\n case 'executions':\n await handleList(rest, apiUrl, token);\n break;\n case 'suites':\n if (rest[0] === 'get') {\n await handleSuiteCatalogGet(rest.slice(1), apiUrl, token);\n } else {\n await handleSuitesList(rest, apiUrl, token);\n }\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'diagnostics':\n await handleDiagnostics(rest, apiUrl, token);\n break;\n case 'steps':\n await handleSteps(rest, apiUrl, token);\n break;\n case 'create':\n await handleSuiteCreate(rest, apiUrl, token);\n break;\n case 'push':\n await pushTestSuiteBundle(rest, apiUrl, token);\n break;\n case 'update':\n await handleSuiteUpdate(rest, apiUrl, token);\n break;\n case 'delete':\n await handleSuiteDelete(rest, apiUrl, token);\n break;\n case 'members':\n await handleSuiteMembers(rest, apiUrl, token);\n break;\n case 'set-members':\n await handleSuiteSetMembers(rest, apiUrl, token);\n break;\n case 'area':\n await handleSuiteArea(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printTestSuiteHelp();\n process.exit(1);\n }\n}\n","/**\n * External-suite flags for `test-suite create` / `test-suite update`.\n *\n * An external suite runs a customer's own Playwright/Selenium/Cypress repo on a\n * leased sandbox. Creating one is `POST /test-suites` with `kind: 'external'`;\n * configuring its runner uses the customer-editable config and areas PATCH\n * routes plus the superadmin command route. This module maps flags onto those\n * bodies, resolves the human-friendly references (`owner/name`, environment and\n * credential names) to the ids the API wants, and applies the update.\n *\n * @module test-suite-external\n */\n\nimport process from 'node:process';\nimport {\n apiRequest,\n fetchProperties,\n getApplicationArg,\n getArgValues,\n getScalarArgValue,\n resolveCredentialId,\n resolveTestSuite,\n UUID_RE,\n} from './cli-helpers.js';\nimport { resolveSlackChannelIds, resolveTeamsChannelValues } from './automation-shared.js';\nimport { writeRawOutput } from './brand.js';\nimport { fetchEnvironments, resolveEnvironment } from './environment.js';\nimport { isSuperadminToken } from './jwt.js';\n\n/** Create-only flags: which engine and which repository the suite is. */\nexport const EXTERNAL_CREATE_FLAGS = ['--kind', '--provider', '--source'];\n\n/** Runner flags accepted by `update` (and the repo/link ones also by `create`). */\nexport const EXTERNAL_RUNNER_FLAGS = [\n '--repo',\n '--ref',\n '--environment',\n '--credential',\n '--env-map',\n '--sandbox-template',\n '--sandbox-action',\n '--sandbox-param',\n '--capture-policy',\n '--retry-granularity',\n '--max-retries',\n '--default-grep',\n '--run-cmd',\n '--install-cmd',\n '--list-cmd',\n '--spec',\n '--shard-timeout-ms',\n '--shard-dirs',\n '--areas-prefix',\n '--shard-count',\n '--toolchain-image',\n];\n\n/** Runner flags `create` does NOT accept — the runner is configured with `update`. */\nexport const UPDATE_ONLY_RUNNER_FLAGS = EXTERNAL_RUNNER_FLAGS.filter(\n (flag) => !['--repo', '--ref', '--environment', '--credential'].includes(flag)\n);\n\n/** Every flag this module consumes, so `getPositionalArg` skips their values. */\nexport const EXTERNAL_SUITE_FLAGS = [\n ...EXTERNAL_CREATE_FLAGS,\n '--application',\n '--property',\n ...EXTERNAL_RUNNER_FLAGS,\n];\n\nconst PROVIDERS = ['selenium', 'playwright', 'cypress'] as const;\ntype Provider = (typeof PROVIDERS)[number];\n\ntype LinkedRepo = {\n id: string;\n repoFullName: string;\n defaultBranch: string;\n propertyId: string;\n propertyName: string;\n};\n\nfunction fail(message: string): never {\n process.stderr.write(`Error: ${message}\\n`);\n process.exit(1);\n}\n\n/** True when any of `flags` was given, in either `--k v` or `--k=v` form. */\nexport function hasAnyFlag(argv: string[], flags: readonly string[]): boolean {\n return flags.some((flag) => argv.includes(flag) || argv.some((a) => a.startsWith(`${flag}=`)));\n}\n\nfunction integer(argv: string[], key: string): number | undefined {\n const raw = getScalarArgValue(argv, key);\n if (raw === undefined) return undefined;\n if (!/^\\d+$/.test(raw)) fail(`${key} must be a non-negative integer (got \"${raw}\").`);\n return Number(raw);\n}\n\nfunction oneOf<T extends string>(argv: string[], key: string, allowed: readonly T[]): T | undefined {\n const raw = getScalarArgValue(argv, key);\n if (raw === undefined) return undefined;\n if (!allowed.includes(raw as T)) fail(`${key} must be one of ${allowed.join(', ')} (got \"${raw}\").`);\n return raw as T;\n}\n\n/**\n * `--env-map KEY=VALUE`, repeatable. The value is a `$var.USER.X` /\n * `$var.ENV.X` reference or a literal. The API REPLACES the whole map, so the\n * command must carry every mapping the runner should keep.\n */\nexport function parseEnvMap(argv: string[]): Record<string, string> | undefined {\n const raw = getArgValues(argv, '--env-map');\n if (raw.length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const entry of raw) {\n const eq = entry.indexOf('=');\n const name = eq > 0 ? entry.slice(0, eq) : '';\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\n fail(`--env-map expects NAME=value with a valid env var name (got \"${entry}\").`);\n }\n out[name] = entry.slice(eq + 1);\n }\n return out;\n}\n\n/** `--sandbox-param key=value`, repeatable; values stay strings (the action schema decides). */\nfunction parseSandboxParams(argv: string[]): Record<string, string> | undefined {\n const raw = getArgValues(argv, '--sandbox-param');\n if (raw.length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const entry of raw) {\n const eq = entry.indexOf('=');\n if (eq <= 0) fail(`--sandbox-param expects key=value (got \"${entry}\").`);\n out[entry.slice(0, eq)] = entry.slice(eq + 1);\n }\n return out;\n}\n\n/**\n * Resolve `--repo <owner/name | property_github_repos.id>` against every\n * application's linked repos (`GET /org/properties/:id/github-repos`, the same\n * listing `application list` prints). `--application` narrows the search when\n * the same repo is linked to more than one application.\n */\nexport async function resolveLinkedRepo(\n repoArg: string,\n apiUrl: string,\n token: string,\n applicationArg?: string\n): Promise<LinkedRepo> {\n let properties = await fetchProperties(apiUrl, token);\n if (applicationArg) {\n properties = properties.filter(\n (p) => p.id === applicationArg || p.name.toLowerCase() === applicationArg.toLowerCase()\n );\n if (properties.length === 0) fail(`Application \"${applicationArg}\" not found.`);\n }\n const matches: LinkedRepo[] = [];\n for (const p of properties) {\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n items?: Array<{ id: string; repoFullName: string; defaultBranch: string }>;\n }>(apiUrl, token, 'GET', `/org/properties/${p.id}/github-repos`);\n for (const r of res.ok ? (res.items ?? []) : []) {\n if (r.id === repoArg || r.repoFullName.toLowerCase() === repoArg.toLowerCase()) {\n matches.push({ ...r, propertyId: p.id, propertyName: p.name });\n }\n }\n }\n if (matches.length === 0) {\n fail(\n `No linked repository \"${repoArg}\". Link it first with \"application repo link ` +\n `--application <name> --repo <owner/name>\" (the GitHub App must be installed on it).`\n );\n }\n if (matches.length > 1) {\n process.stderr.write(`Error: \"${repoArg}\" is linked to more than one application:\\n`);\n for (const m of matches) process.stderr.write(` - ${m.propertyName} (${m.id})\\n`);\n fail('Pass --application <name> to pick one.');\n }\n return matches[0]!;\n}\n\nasync function resolveEnvironmentId(\n propertyId: string,\n envArg: string,\n apiUrl: string,\n token: string\n): Promise<string> {\n if (UUID_RE.test(envArg)) return envArg;\n return resolveEnvironment(await fetchEnvironments(propertyId, apiUrl, token), envArg).id;\n}\n\n/**\n * The `external` block of `POST /test-suites` for `--kind external`.\n */\nexport async function buildExternalCreateBlock(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<{ external: Record<string, unknown>; repo: LinkedRepo | null; propertyName: string }> {\n const provider = oneOf<Provider>(argv, '--provider', PROVIDERS);\n if (!provider) fail('--provider <selenium|playwright|cypress> is required with --kind external.');\n const source = oneOf(argv, '--source', ['image', 'github', 'upload'] as const) ?? 'github';\n if (source !== 'github') {\n if (provider !== 'playwright') fail(`--source ${source} supports --provider playwright only.`);\n if (getScalarArgValue(argv, '--repo') !== undefined || getScalarArgValue(argv, '--ref') !== undefined) {\n fail('--repo and --ref apply only to --source github.');\n }\n const propertyArg = getScalarArgValue(argv, '--property') ?? getApplicationArg(argv);\n if (!propertyArg) fail(`--application <name|id> is required with --source ${source}.`);\n const properties = await fetchProperties(apiUrl, token);\n const property = properties.find(\n (item) => item.id === propertyArg || item.name.toLowerCase() === propertyArg.toLowerCase()\n );\n if (!property) fail(`Application \"${propertyArg}\" not found.`);\n const external: Record<string, unknown> = {\n sourceKind: source,\n provider,\n propertyId: property.id,\n };\n const env = getScalarArgValue(argv, '--environment');\n if (source === 'image' && !env) fail('--environment <name|id> is required with --source image.');\n if (env !== undefined) external.targetEnvironmentId = await resolveEnvironmentId(property.id, env, apiUrl, token);\n const cred = getScalarArgValue(argv, '--credential');\n if (cred !== undefined) external.credentialId = await resolveCredentialId(cred, property.id, apiUrl, token);\n return { external, repo: null, propertyName: property.name };\n }\n const repoArg = getScalarArgValue(argv, '--repo');\n if (!repoArg) fail('--repo <owner/name|id> is required with --kind external.');\n const repo = await resolveLinkedRepo(repoArg, apiUrl, token, getApplicationArg(argv));\n const external: Record<string, unknown> = {\n sourceKind: 'github',\n provider,\n propertyGithubRepoId: repo.id,\n };\n const ref = getScalarArgValue(argv, '--ref');\n if (ref !== undefined) external.repoRef = ref;\n const env = getScalarArgValue(argv, '--environment');\n if (env !== undefined) {\n external.targetEnvironmentId = await resolveEnvironmentId(repo.propertyId, env, apiUrl, token);\n }\n const cred = getScalarArgValue(argv, '--credential');\n if (cred !== undefined) {\n external.credentialId = await resolveCredentialId(cred, repo.propertyId, apiUrl, token);\n }\n return { external, repo, propertyName: repo.propertyName };\n}\n\nexport type ExternalRunnerBodies = {\n /** `PATCH /test-suites/:id/external-runner` — omitted when no such flag was given. */\n runner?: Record<string, unknown>;\n /** `PATCH /test-suites/:id/external-runner/advanced` (superadmin) — same. */\n advanced?: Record<string, unknown>;\n /** `PATCH /test-suites/:id/external-runner/areas` (org member) — same. */\n areas?: { areaPaths: string[]; generatedPrefix: string | null };\n};\n\n/**\n * Split `test-suite update` runner flags into the two PATCH bodies. Only keys\n * that were supplied are sent, so an unrelated `update --name` never touches\n * the runner. `--repo` re-derives the application server-side, so environment\n * and credential names are resolved against the NEW repo's application when\n * both change in one call.\n */\nexport async function buildExternalRunnerBodies(\n argv: string[],\n current: {\n propertyId: string | null;\n shardDirectories: string[] | null;\n areaGeneratedPrefix: string | null;\n },\n apiUrl: string,\n token: string\n): Promise<ExternalRunnerBodies> {\n const runner: Record<string, unknown> = {};\n const advanced: Record<string, unknown> = {};\n\n let propertyId = current.propertyId;\n const repoArg = getScalarArgValue(argv, '--repo');\n if (repoArg !== undefined) {\n const repo = await resolveLinkedRepo(repoArg, apiUrl, token, getApplicationArg(argv));\n runner.propertyGithubRepoId = repo.id;\n propertyId = repo.propertyId;\n }\n const ref = getScalarArgValue(argv, '--ref');\n if (ref !== undefined) runner.repoRef = ref;\n\n const env = getScalarArgValue(argv, '--environment');\n const cred = getScalarArgValue(argv, '--credential');\n if ((env !== undefined || cred !== undefined) && !propertyId) {\n fail('This suite has no application yet; pass --repo so environment/credential names can be resolved.');\n }\n if (env !== undefined) runner.targetEnvironmentId = await resolveEnvironmentId(propertyId!, env, apiUrl, token);\n if (cred !== undefined) runner.credentialId = await resolveCredentialId(cred, propertyId!, apiUrl, token);\n\n const envMapping = parseEnvMap(argv);\n if (envMapping !== undefined) runner.envMapping = envMapping;\n const template = getScalarArgValue(argv, '--sandbox-template');\n if (template !== undefined) runner.sandboxTemplateId = template;\n const action = getScalarArgValue(argv, '--sandbox-action');\n if (action !== undefined) runner.sandboxActionSlug = action;\n const params = parseSandboxParams(argv);\n if (params !== undefined) runner.sandboxActionParams = params;\n const capture = oneOf(argv, '--capture-policy', ['retry', 'always'] as const);\n if (capture !== undefined) runner.capturePolicy = capture;\n const granularity = oneOf(argv, '--retry-granularity', ['suite', 'test'] as const);\n if (granularity !== undefined) runner.retryGranularity = granularity;\n const maxRetries = integer(argv, '--max-retries');\n if (maxRetries !== undefined) runner.maxRetries = maxRetries;\n const defaultGrep = getScalarArgValue(argv, '--default-grep', { allowEmpty: true });\n if (defaultGrep !== undefined) runner.defaultGrep = defaultGrep.length === 0 ? null : defaultGrep;\n\n const runCmd = getScalarArgValue(argv, '--run-cmd');\n if (runCmd !== undefined) advanced.runCmd = runCmd;\n const installCmd = getScalarArgValue(argv, '--install-cmd');\n if (installCmd !== undefined) advanced.installCmd = installCmd;\n const listCmd = getScalarArgValue(argv, '--list-cmd');\n if (listCmd !== undefined) advanced.listCmd = listCmd;\n const spec = getScalarArgValue(argv, '--spec');\n if (spec !== undefined) advanced.defaultSpecPath = spec;\n const timeout = integer(argv, '--shard-timeout-ms');\n if (timeout !== undefined) advanced.shardTimeoutMs = timeout;\n const shardCount = integer(argv, '--shard-count');\n if (shardCount !== undefined) advanced.shardCount = shardCount;\n const image = getScalarArgValue(argv, '--toolchain-image');\n if (image !== undefined) advanced.toolchainImage = image;\n\n const out: ExternalRunnerBodies = {};\n if (Object.keys(runner).length > 0) out.runner = runner;\n if (Object.keys(advanced).length > 0) out.advanced = advanced;\n const shardDirs = getScalarArgValue(argv, '--shard-dirs', { allowEmpty: true });\n const areasPrefix = getScalarArgValue(argv, '--areas-prefix', { allowEmpty: true });\n if (shardDirs !== undefined || areasPrefix !== undefined) {\n out.areas = {\n areaPaths:\n shardDirs === undefined\n ? (current.shardDirectories ?? [])\n : shardDirs\n .split(',')\n .map((path) => path.trim())\n .filter((path) => path.length > 0),\n generatedPrefix:\n areasPrefix === undefined ? current.areaGeneratedPrefix : areasPrefix.trim() || null,\n };\n }\n return out;\n}\n\n/**\n * Apply the runner bodies. The superadmin half normally goes first because it\n * is the request most likely to be refused. Clearing areas must precede a\n * command that removes `<spec>`, though, because either atomic API write would\n * reject the incompatible intermediate state. When a later request fails after\n * an earlier one succeeded, the message says what already landed.\n */\nexport async function applyExternalRunnerUpdate(\n suiteId: string,\n bodies: ExternalRunnerBodies,\n apiUrl: string,\n token: string\n): Promise<{ runner: unknown; applied: string[] }> {\n const applied: string[] = [];\n const bail = (message: string): never => {\n if (applied.length > 0) {\n process.stderr.write(`Already applied before this failure: ${applied.join(', ')}.\\n`);\n }\n fail(message);\n };\n let runner: unknown;\n const applyAreas = async (): Promise<void> => {\n if (!bodies.areas) return;\n const res = await apiRequest<{ ok: boolean; error?: string; data?: unknown }>(\n apiUrl,\n token,\n 'PATCH',\n `/test-suites/${suiteId}/external-runner/areas`,\n bodies.areas\n );\n if (!res.ok) bail(res.error ?? 'Failed to update the runner areas');\n runner = res.data;\n applied.push('runner areas');\n };\n const runCmd = bodies.advanced?.runCmd;\n const clearAreasFirst =\n bodies.areas?.areaPaths.length === 0 &&\n typeof runCmd === 'string' &&\n !runCmd.includes('<spec>');\n const superadminRunnerHint =\n '--run-cmd/--install-cmd/--list-cmd/--spec/--shard-timeout-ms/--shard-count/' +\n '--toolchain-image are superadmin-only (they decide what runs inside the sandbox container). ' +\n 'Ask Cofactor to set them.';\n if (clearAreasFirst && !isSuperadminToken(token)) bail(superadminRunnerHint);\n if (clearAreasFirst) await applyAreas();\n if (bodies.advanced) {\n const res = await apiRequest<{ ok: boolean; error?: string; code?: string; data?: unknown }>(\n apiUrl,\n token,\n 'PATCH',\n `/test-suites/${suiteId}/external-runner/advanced`,\n bodies.advanced\n );\n if (!res.ok) {\n // The superadmin hint only when that is what was refused (the middleware\n // answers `code: 'SUPERADMIN_REQUIRED'`).\n const forbidden = res.code === 'SUPERADMIN_REQUIRED';\n bail(\n forbidden\n ? `${res.error ?? 'Failed to update the runner command'} — ${superadminRunnerHint}`\n : (res.error ?? 'Failed to update the runner command')\n );\n }\n runner = res.data;\n applied.push('runner command');\n }\n if (bodies.runner) {\n const res = await apiRequest<{ ok: boolean; error?: string; data?: unknown }>(\n apiUrl,\n token,\n 'PATCH',\n `/test-suites/${suiteId}/external-runner`,\n bodies.runner\n );\n if (!res.ok) bail(res.error ?? 'Failed to update the external runner');\n runner = res.data;\n applied.push('runner config');\n }\n if (!clearAreasFirst) await applyAreas();\n return { runner, applied };\n}\n\ntype AreaAlertStep = {\n channel: 'email' | 'slack' | 'teams';\n on: Array<'success' | 'failure'>;\n recipients?: string[];\n slackChannelId?: string;\n teamsChannelRef?: string;\n};\n\n/**\n * `test-suite area settings` flags → the PATCH body. `--slack`/`--teams`/`--email`\n * REPLACE the area's destinations (one step each, on success and failure);\n * `--no-alerts` clears them; `--triage on|off` sets the switch. Omitted halves\n * are left as they are. `--slack`/`--teams` values go in as given; a name is\n * resolved by {@link resolveAreaChannels} before the PATCH.\n */\nexport function buildAreaSettingsBody(\n argv: string[]\n): { alertConfig?: { steps: AreaAlertStep[] }; triageEnabled?: boolean } | { error: string } {\n const slack = getScalarArgValue(argv, '--slack');\n const teams = getScalarArgValue(argv, '--teams');\n const emails = getScalarArgValue(argv, '--email');\n const triage = getScalarArgValue(argv, '--triage');\n const clear = argv.includes('--no-alerts');\n if (clear && (slack || teams || emails)) {\n return { error: '--no-alerts cannot be combined with --slack, --teams or --email.' };\n }\n if (triage !== undefined && triage !== 'on' && triage !== 'off') {\n return { error: '--triage takes on or off.' };\n }\n const on: Array<'success' | 'failure'> = ['success', 'failure'];\n const steps: AreaAlertStep[] = [\n ...(slack ? [{ channel: 'slack' as const, on, slackChannelId: slack }] : []),\n ...(teams ? [{ channel: 'teams' as const, on, teamsChannelRef: teams }] : []),\n ...(emails\n ? [{ channel: 'email' as const, on, recipients: emails.split(',').map((email) => email.trim()).filter(Boolean) }]\n : []),\n ];\n const body = {\n ...(steps.length || clear ? { alertConfig: { steps } } : {}),\n ...(triage !== undefined ? { triageEnabled: triage === 'on' } : {}),\n };\n return Object.keys(body).length\n ? body\n : { error: 'Pass --slack <channel>, --teams <channel>, --email <a,b>, --no-alerts and/or --triage on|off.' };\n}\n\n/**\n * `--slack`/`--teams` values in the built steps → the channel ID / reference\n * the API stores, resolved like `alert create` (exits when Slack or Teams is not\n * set up or a name matches nothing).\n */\nasync function resolveAreaChannels(steps: AreaAlertStep[], apiUrl: string, token: string): Promise<AreaAlertStep[]> {\n const resolved: AreaAlertStep[] = [];\n for (const step of steps) {\n if (step.channel === 'slack' && step.slackChannelId) {\n const [slackChannelId] = await resolveSlackChannelIds([step.slackChannelId], apiUrl, token);\n resolved.push({ ...step, slackChannelId });\n } else if (step.channel === 'teams' && step.teamsChannelRef) {\n const [teamsChannelRef] = await resolveTeamsChannelValues([step.teamsChannelRef], apiUrl, token);\n resolved.push({ ...step, teamsChannelRef });\n } else {\n resolved.push(step);\n }\n }\n return resolved;\n}\n\nconst AREA_USAGE =\n 'Usage: cofactor test-suite area settings <suite> <area> [--slack <channel>] [--teams <channel>] ' +\n '[--email <a@x,b@y>] [--no-alerts] [--triage on|off] [--json]\\n' +\n ' cofactor test-suite area disable|enable <suite> <area> [--json]';\n\n/**\n * `cofactor test-suite area settings|disable|enable <suite> <area>`. The area is\n * named like `run --area`: its full path or its last segment.\n */\nexport async function handleSuiteArea(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [action, suiteArg, area] = argv;\n if (!suiteArg || !area || suiteArg.startsWith('-') || area.startsWith('-')) fail(AREA_USAGE);\n if (action === 'disable' || action === 'enable') {\n await setAreaDisabled(argv, suiteArg, area, action === 'disable', apiUrl, token);\n return;\n }\n if (action !== 'settings') fail(AREA_USAGE);\n const body = buildAreaSettingsBody(argv);\n if ('error' in body) fail(body.error);\n const suite = await resolveTestSuite(suiteArg, apiUrl, token);\n if (body.alertConfig) body.alertConfig.steps = await resolveAreaChannels(body.alertConfig.steps, apiUrl, token);\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n data?: { path: string; settings: { alertConfig: { steps: AreaAlertStep[] }; triageEnabled: boolean } | null };\n }>(apiUrl, token, 'PATCH', `/test-suites/${suite.id}/external-runner/areas/settings`, { area, ...body });\n if (!res.ok || !res.data) fail(res.error ?? 'Failed to update the area settings');\n if (argv.includes('--json')) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n const { path, settings } = res.data;\n const destinations =\n settings?.alertConfig.steps\n .map((step) =>\n step.channel === 'slack'\n ? `Slack ${step.slackChannelId}`\n : step.channel === 'teams'\n ? `Teams ${step.teamsChannelRef}`\n : `email ${step.recipients?.join(', ')}`\n )\n .join('; ') || 'none';\n console.log(`Area ${path}`);\n console.log(` Alerts: ${destinations}`);\n console.log(` Triage: ${settings?.triageEnabled ? 'on' : 'off'}`);\n}\n\n\n/** `test-suite area disable|enable` (CAP-ETS-009): a turned-off area is kept but not run. */\nasync function setAreaDisabled(\n argv: string[],\n suiteArg: string,\n area: string,\n disabled: boolean,\n apiUrl: string,\n token: string\n): Promise<void> {\n const suite = await resolveTestSuite(suiteArg, apiUrl, token);\n const res = await apiRequest<{ ok: boolean; error?: string; data?: { disabledAreas: string[] } }>(\n apiUrl,\n token,\n 'PUT',\n `/test-suites/${suite.id}/external-runner/areas/disabled`,\n { path: area, disabled }\n );\n if (!res.ok || !res.data) fail(res.error ?? `Failed to ${disabled ? 'disable' : 'enable'} the area`);\n if (argv.includes('--json')) {\n writeRawOutput(JSON.stringify({ disabledAreas: res.data.disabledAreas }, null, 2));\n return;\n }\n console.log(`Area ${area} ${disabled ? 'turned off' : 'turned on'} for ${suite.name}.`);\n console.log(` Turned off: ${res.data.disabledAreas.join(', ') || 'none'}`);\n}\n\n/** Help lines for the external flags (kept next to the flags they describe). */\nexport const EXTERNAL_SUITE_HELP_LINES = [\n 'External suite (create): run your own Playwright/Selenium/Cypress repo on a sandbox',\n ' --kind external Create an external suite (default: native)',\n ' --provider <p> playwright | selenium | cypress (required with --kind external)',\n ' --source <image|github|upload> Use tests in the sbv2 app image, a separate repo, or an uploaded bundle',\n ' --repo <owner/name|id> A repository linked to an application (see `application list`)',\n \" --ref <branch> Branch or tag (default: the linked repo's default branch)\",\n ' --application <name|id> Disambiguate when the repo is linked to several applications',\n ' --environment <name|id> Target environment on that application (supplies $var.ENV.*;',\n ' not --env, which picks the Cofactor API environment)',\n ' --credential <name|id> Login persona credential (supplies $var.USER.*)',\n '',\n 'External suite (update): runner configuration — only the flags given are changed',\n ' --repo/--ref/--environment/--credential as on create',\n ' --env-map KEY=VALUE Repeatable. VALUE is $var.USER.X or $var.ENV.X for anything',\n ' secret (the mapping is readable org config), or a literal for',\n ' non-secret values. REPLACES the whole map: pass every mapping.',\n ' Optional: a suite whose tests read no variables needs none.',\n ' --sandbox-template <id> Environment template whose instances run the suite',\n ' --sandbox-action <slug> Action on that template that runs the suite (runner adapter)',\n ' --sandbox-param k=v Repeatable. Extra string params for that action (replaces all)',\n ' --capture-policy <p> retry | always',\n ' --retry-granularity <g> suite | test',\n ' --max-retries <n> 0-5',\n ' --default-grep <regex> Default test title regex; pass an empty value to clear it',\n ' --shard-dirs a,b Directory area paths or last-segment globs (empty clears)',\n ' --areas-prefix <path/> Generated prefix stripped for matching, then restored; empty clears',\n ' Superadmin only (what runs inside the container; normally applied first):',\n ' --run-cmd <cmd> Must keep <spec> (and <cofactor-playwright-args> for Playwright)',\n ' --install-cmd <cmd> e.g. \"npm ci --include=dev\"',\n ' --spec <path/> Default spec directory — keep the trailing slash for Playwright',\n ' --shard-timeout-ms <ms> Per-attempt cap (max 14400000, 4 h)',\n ' --shard-count <n> Label shards (1-32)',\n ' --toolchain-image <id> Framework preset id, e.g. playwright-node22',\n '',\n];\n","import { execFile as execFileCallback } from 'node:child_process';\nimport { mkdtemp, readFile, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport process from 'node:process';\nimport { MAX_EXTERNAL_SUITE_DECLARATION_BYTES, parseExternalSuiteDeclaration } from '@chatsdet/test-reporters';\nimport { resolveTestSuite } from './cli-helpers.js';\nimport { writeRawOutput } from './brand.js';\n\nconst execFile = promisify(execFileCallback);\nconst valueFlags = new Set(['--api-url', '--env', '--org', '--token']);\n\nexport function testSuitePositionals(argv: string[]): string[] {\n const positionals: string[] = [];\n for (let index = 0; index < argv.length; index += 1) {\n const value = argv[index]!;\n if (valueFlags.has(value)) {\n index += 1;\n continue;\n }\n if (!value.startsWith('-')) positionals.push(value);\n }\n return positionals;\n}\n\nexport async function validateTestSuiteDirectory(\n directoryArg: string,\n options: { quiet?: boolean; json?: boolean } = {}\n): Promise<void> {\n const directory = path.resolve(directoryArg);\n const info = await stat(directory).catch(() => null);\n if (!info?.isDirectory()) fail(`Test suite directory does not exist: ${directoryArg}`);\n const declarationPath = path.join(directory, 'cofactor.tests.yaml');\n const declarationInfo = await stat(declarationPath).catch(() => null);\n if (declarationInfo && declarationInfo.size > MAX_EXTERNAL_SUITE_DECLARATION_BYTES) {\n fail('Invalid cofactor.tests.yaml: declaration exceeds the 64KB limit');\n }\n const source = await readFile(declarationPath, 'utf8').catch(() => null);\n if (source === null) fail(`Missing ${path.join(directoryArg, 'cofactor.tests.yaml')}.`);\n try {\n parseExternalSuiteDeclaration(source);\n } catch (error) {\n fail(`Invalid cofactor.tests.yaml: ${error instanceof Error ? error.message : String(error)}`);\n }\n if (options.quiet) return;\n const validated = path.join(directoryArg, 'cofactor.tests.yaml');\n writeRawOutput(options.json ? JSON.stringify({ valid: true, file: validated }) : `✓ Validated ${validated}`);\n}\n\nexport async function pushTestSuiteBundle(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const positionals: string[] = [];\n let json = false;\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index]!;\n if (token === '--json') {\n json = true;\n continue;\n }\n if (valueFlags.has(token)) {\n if (!argv[index + 1] || argv[index + 1]!.startsWith('-')) fail(`${token} requires a value.`);\n index += 1;\n continue;\n }\n if (/^--(?:api-url|env|org|token)=/.test(token)) continue;\n if (token.startsWith('-')) fail(`Unknown push option: ${token}`);\n positionals.push(token);\n }\n const [suiteArg, directoryArg] = positionals;\n if (!suiteArg || !directoryArg) fail('Usage: cofactor test-suite push <suite-id|name> <directory>.');\n if (positionals.length !== 2) fail('Push accepts exactly a suite and a directory.');\n const directory = path.resolve(directoryArg);\n await validateTestSuiteDirectory(directory, { quiet: true });\n const suite = await resolveTestSuite(suiteArg, apiUrl, token);\n const temp = await mkdtemp(path.join(tmpdir(), 'cofactor-test-suite-'));\n const archivePath = path.join(temp, 'suite.tar.gz');\n try {\n await execFile('tar', [\n '-czf', archivePath,\n '--exclude=./.git',\n '--exclude=./node_modules',\n '--exclude=./.canary',\n '--exclude=./output',\n '--exclude=./.env',\n '--exclude=./.env.*',\n '--exclude=./.npmrc',\n '--exclude=._*',\n '--exclude=.DS_Store',\n '.',\n ], {\n cwd: directory,\n env: { ...process.env, COPYFILE_DISABLE: '1' },\n maxBuffer: 1024 * 1024,\n });\n const bytes = await readFile(archivePath);\n const form = new FormData();\n form.append('bundle', new Blob([bytes], { type: 'application/gzip' }), 'suite.tar.gz');\n const response = await fetch(`${apiUrl}/test-suites/${suite.id}/bundle`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}` },\n body: form,\n });\n const result = await response.json() as {\n ok?: boolean;\n data?: { bundleDigest?: string; bundleStorageKey?: string };\n error?: string;\n };\n if (!response.ok || !result.ok) fail(`Bundle upload failed: ${result.error ?? response.statusText}`);\n writeRawOutput(json\n ? JSON.stringify({ suiteId: suite.id, suiteName: suite.name, ...result.data }, null, 2)\n : `✓ Uploaded test bundle for \"${suite.name}\" (${suite.id})`);\n } finally {\n await rm(temp, { recursive: true, force: true });\n }\n}\n\nfunction fail(message: string): never {\n process.stderr.write(`Error: ${message}\\n`);\n process.exit(1);\n}\n","/**\n * The Playwright-only `cofactor.tests.yaml` contract shared by the API and CLI.\n * Runtime references are parsed separately from build-time values so install\n * and discovery never receive a copy URL, persona credential, or app seed.\n *\n * @module external-suite-declaration\n */\nimport { z } from 'zod';\nimport { parseDocument } from 'yaml';\n\nexport const MAX_EXTERNAL_SUITE_DECLARATION_BYTES = 64 * 1024;\n\nconst SeedReference = /^\\$\\{seeds\\.([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)\\}$/;\nconst PersonaReference = /^\\$\\{personas\\.([A-Za-z0-9_-]+)\\.(email|password)\\}$/;\nconst AppUrlReference = '${app.url}';\n\nexport const ExternalSuiteDeclarationSchema = z\n .object({\n version: z.literal(1),\n install: z.string().min(1),\n run: z.union([\n z.literal('playwright'),\n z.object({ playwright: z.object({ config: z.string().min(1).optional() }).strict() }).strict(),\n ]),\n env: z.record(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/), z.string()).optional(),\n })\n .strict()\n .superRefine((declaration, context) => {\n for (const [name, value] of Object.entries(declaration.env ?? {})) {\n if (value.includes('${') && value !== AppUrlReference && !PersonaReference.test(value) && !SeedReference.test(value)) {\n context.addIssue({ code: 'custom', path: ['env', name], message: 'contains an unsupported reference' });\n }\n }\n });\n\nexport type ExternalSuiteDeclaration = z.infer<typeof ExternalSuiteDeclarationSchema>;\n\ntype ExternalSuiteEnvReference =\n | { kind: 'literal'; value: string }\n | { kind: 'app-url' }\n | { kind: 'persona'; name: string; field: 'email' | 'password' }\n | { kind: 'seed'; seed: string; output: string };\n\nclass ExternalSuiteDeclarationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ExternalSuiteDeclarationError';\n }\n}\n\nexport function parseExternalSuiteDeclaration(source: string): ExternalSuiteDeclaration {\n if (Buffer.byteLength(source, 'utf8') > MAX_EXTERNAL_SUITE_DECLARATION_BYTES) {\n throw new ExternalSuiteDeclarationError('declaration exceeds the 64KB limit');\n }\n const document = parseDocument(source, { uniqueKeys: true, prettyErrors: false });\n if (document.errors.length > 0) {\n throw new ExternalSuiteDeclarationError(document.errors.map((error) => error.message).join('; '));\n }\n const result = ExternalSuiteDeclarationSchema.safeParse(document.toJS());\n if (!result.success) {\n throw new ExternalSuiteDeclarationError(\n result.error.issues.map((issue) => `${issue.path.join('.') || 'declaration'}: ${issue.message}`).join('; ')\n );\n }\n return result.data;\n}\n\nexport function externalSuiteConfigPath(declaration: ExternalSuiteDeclaration): string | null {\n return declaration.run === 'playwright' ? null : declaration.run.playwright.config ?? null;\n}\n\nexport function externalSuiteEnvReferences(\n declaration: ExternalSuiteDeclaration\n): Record<string, ExternalSuiteEnvReference> {\n return Object.fromEntries(\n Object.entries(declaration.env ?? {}).map(([name, value]) => {\n if (value === AppUrlReference) return [name, { kind: 'app-url' }];\n const persona = PersonaReference.exec(value);\n if (persona) return [name, { kind: 'persona', name: persona[1]!, field: persona[2]! }];\n const seed = SeedReference.exec(value);\n if (seed) return [name, { kind: 'seed', seed: seed[1]!, output: seed[2]! }];\n return [name, { kind: 'literal', value }];\n })\n );\n}\n\n/** Build-time values never contain persona, seed, or per-copy app data. */\nexport function externalSuiteBuildEnv(declaration: ExternalSuiteDeclaration): Record<string, string> {\n return Object.fromEntries(\n Object.entries(externalSuiteEnvReferences(declaration)).map(([name, reference]) => [\n name,\n reference.kind === 'literal'\n ? reference.value\n : reference.kind === 'app-url'\n ? 'https://app.placeholder.invalid'\n : reference.kind === 'persona'\n ? `persona-${reference.field}.placeholder.invalid`\n : `seed-${reference.output}.placeholder.invalid`,\n ])\n );\n}\n\n/** Resolve runtime values against a fresh copy's URL, persona pool, and app seed outputs. */\nexport function externalSuiteRuntimeEnv(\n declaration: ExternalSuiteDeclaration,\n input: {\n appUrl: string;\n personas: Record<string, { email: string; password: string }>;\n seeds: Record<string, Record<string, unknown>>;\n }\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [name, reference] of Object.entries(externalSuiteEnvReferences(declaration))) {\n let value: unknown;\n switch (reference.kind) {\n case 'literal': value = reference.value; break;\n case 'app-url': value = input.appUrl; break;\n case 'persona': value = input.personas[reference.name]?.[reference.field]; break;\n case 'seed': value = input.seeds[reference.seed]?.[reference.output]; break;\n }\n if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {\n throw new ExternalSuiteDeclarationError(`env.${name} could not resolve its declared reference`);\n }\n result[name] = String(value);\n }\n return result;\n}\n","import { createHash } from 'node:crypto';\nimport * as path from 'node:path';\n\nexport type DiscoveredPlaywrightTest = {\n testId: string;\n sourcePath: string;\n /** Path relative to Playwright config.rootDir, for native --test-list rows. */\n testListPath: string;\n title: string;\n titlePath: string[];\n /** Playwright 1.62.1's native grep title, including inherited tags. */\n grepTitle: string;\n project: string;\n line: number;\n column: number;\n repeatEachIndex: number;\n area: string;\n groupKey: string;\n};\n\nexport type PlaywrightDiscoveryGroup = {\n groupKey: string;\n area: string;\n tests: DiscoveredPlaywrightTest[];\n};\n\nexport type PlaywrightProject = { name: string; dependencies: string[]; teardown?: string };\nexport type PlaywrightDiscoveryRow = {\n title: string;\n titlePath: string[];\n project: string;\n file: string;\n line: number;\n column: number;\n repeatEachIndex: number;\n grepTitle: string;\n serialPath: string[];\n};\nexport type PlaywrightDiscoveryInput = { version: string; rootDir: string; projects: PlaywrightProject[]; tests: PlaywrightDiscoveryRow[] };\n\n/** Stable execution/report identity shared with the boundary result parser. */\nexport function externalPlaywrightTestKey(repo: string | null, sourcePath: string, titlePath: readonly string[]): string {\n return `${repo ? `${repo}/` : ''}${sourcePath}#${titlePath.join(' › ')}`;\n}\n\n/**\n * The title path a native `--test-list` row can carry for this test.\n *\n * Playwright 1.62.1 splits each row on `›` (or on `>` when the row has no `›`)\n * and has no escape. A row that carries any title or project contains ` › `,\n * so a `>` inside a title is plain text, but a `›` inside a title would split\n * it. The row therefore stops before the first title containing `›`;\n * Playwright matches a row's titles as a prefix, so that row selects every\n * test below the prefix, and discovery keeps all of those tests in one\n * execution group that runs together even when only one of them is selected.\n */\nfunction playwrightTestListTitlePath(titlePath: readonly string[]): string[] {\n const reserved = titlePath.findIndex((title) => title.includes('›'));\n return reserved === -1 ? [...titlePath] : titlePath.slice(0, reserved);\n}\n\n/** One native `--test-list` row for a discovered test. */\nexport function playwrightTestListRow(test: { project: string; testListPath: string; line: number; column: number; titlePath: readonly string[] }): string {\n const titles = playwrightTestListTitlePath(test.titlePath);\n return `${test.project ? `[${test.project}] › ` : ''}${test.testListPath}:${test.line}:${test.column}${titles.map((title) => ` › ${title}`).join('')}`;\n}\n\n/** Apply a run selection without splitting serial or project dependency groups. */\nexport function selectPlaywrightGroups<Group extends {\n tests: ReadonlyArray<Pick<DiscoveredPlaywrightTest, 'sourcePath' | 'project' | 'titlePath' | 'area' | 'grepTitle'>>;\n}>(groups: readonly Group[], filters: {\n grep: string | null;\n areaDirectories: string[] | null;\n disabledAreas: string[];\n selectedTests: Array<{ areaPath: string | null; testKeys: string[] }> | null;\n testKeyPrefix: string | null;\n}): Group[] {\n const requestedKeys = new Set((filters.selectedTests ?? []).flatMap((group) => group.testKeys));\n const allKeys = new Set(groups.flatMap((group) => group.tests.map((test) => externalPlaywrightTestKey(\n filters.testKeyPrefix,\n test.sourcePath,\n [...(test.project ? [test.project] : []), ...test.titlePath],\n ))));\n const missing = [...requestedKeys].filter((key) => !allKeys.has(key));\n if (missing.length > 0) throw new Error(`Selected test identities were not discovered: ${missing.join(', ')}`);\n let grep: RegExp | null = null;\n try { if (filters.grep) grep = new RegExp(filters.grep); } catch (cause) {\n throw new Error(`Invalid Playwright grep expression: ${cause instanceof Error ? cause.message : String(cause)}`);\n }\n const areaMatches = (area: string, requested: string) => requested === '.' || area === requested || area.startsWith(`${requested}/`);\n const selected = groups.filter((group) => group.tests.some((test) => {\n const key = externalPlaywrightTestKey(filters.testKeyPrefix, test.sourcePath, [...(test.project ? [test.project] : []), ...test.titlePath]);\n const areaSelected = !filters.areaDirectories?.length || filters.areaDirectories.some((area) => areaMatches(test.area, area));\n const areaEnabled = !filters.disabledAreas.some((area) => areaMatches(test.area, area));\n const titleSelected = !grep || grep.test(test.grepTitle);\n return areaSelected && areaEnabled && titleSelected && (requestedKeys.size === 0 || requestedKeys.has(key));\n }));\n if (selected.length === 0) throw new Error('Run filters selected no Playwright execution groups.');\n return selected;\n}\n\nclass DisjointSet {\n private readonly parents = new Map<string, string>();\n add(key: string) { this.parents.set(key, key); }\n find(key: string): string {\n const parent = this.parents.get(key);\n if (parent === undefined) throw new Error(`Unknown Playwright discovery unit \"${key}\".`);\n if (parent === key) return key;\n const root = this.find(parent);\n this.parents.set(key, root);\n return root;\n }\n union(left: string, right: string) {\n const a = this.find(left);\n const b = this.find(right);\n if (a !== b) this.parents.set(b, a);\n }\n}\n\nfunction projectGraph(projects: readonly PlaywrightProject[]) {\n const byName = new Map(projects.map((project) => [project.name, project]));\n if (byName.size !== projects.length) throw new Error('Playwright project names must be unique.');\n for (const project of projects) {\n for (const dependency of [...project.dependencies, ...(project.teardown ? [project.teardown] : [])]) {\n if (!byName.has(dependency)) throw new Error(`Playwright project \"${project.name}\" references unknown project \"${dependency}\".`);\n }\n }\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const visit = (name: string) => {\n if (visiting.has(name)) throw new Error(`Playwright project dependency cycle includes \"${name}\".`);\n if (visited.has(name)) return;\n const project = byName.get(name);\n if (!project) throw new Error(`Unknown Playwright project \"${name}\".`);\n visiting.add(name);\n // Teardown declarations create an ordering edge from the project lifecycle\n // to a later cleanup project. They are not Playwright dependencies and must\n // not participate in dependency cycle detection.\n for (const dependency of project.dependencies) visit(dependency);\n visiting.delete(name);\n visited.add(name);\n };\n for (const name of byName.keys()) visit(name);\n return byName;\n}\n\n/** Build immutable execution units from Playwright PublicReporter metadata. */\nexport function discoverPlaywrightGroups(input: PlaywrightDiscoveryInput, options: {\n repoRoot: string;\n areaForPath: (sourcePath: string) => string;\n}): PlaywrightDiscoveryGroup[] {\n if (input.version !== '1.62.1') throw new Error(`External test discovery requires Playwright 1.62.1; found ${input.version}.`);\n const projects = projectGraph(input.projects);\n if (input.tests.length === 0) throw new Error('Playwright discovery found no tests.');\n\n const units = new DisjointSet();\n const rows = input.tests.map((test) => {\n const sourcePath = path.relative(options.repoRoot, test.file).replaceAll('\\\\', '/');\n if (!sourcePath || sourcePath.startsWith('../') || path.isAbsolute(sourcePath)) throw new Error(`Playwright test location is outside the checkout: ${test.file}`);\n const testListPath = path.relative(input.rootDir, test.file).replaceAll('\\\\', '/');\n if (!testListPath || path.isAbsolute(testListPath)) throw new Error(`Playwright test location cannot be represented relative to config.rootDir: ${test.file}`);\n // A row cannot escape a delimiter in its project or path; titles are\n // handled by truncating the row (see playwrightTestListTitlePath).\n if ([test.project, sourcePath, testListPath].some((part) => /[\\r\\n›>]/.test(part)) || [test.title, ...test.titlePath].some((part) => /[\\r\\n]/.test(part)) || [test.project, testListPath, test.title, ...test.titlePath].some((part) => part.trim() !== part)) {\n throw new Error(`Playwright project, path, or title contains a reserved test-list delimiter at ${sourcePath}:${test.line}.`);\n }\n if (typeof test.grepTitle !== 'string') throw new Error(`Playwright test is missing its pinned grep identity at ${sourcePath}:${test.line}.`);\n if (!projects.has(test.project)) throw new Error(`Playwright test references unknown project \"${test.project}\".`);\n if (!Number.isInteger(test.repeatEachIndex) || test.repeatEachIndex < 0) throw new Error(`Playwright test has invalid repeatEachIndex at ${sourcePath}:${test.line}.`);\n const testId = createHash('sha256').update(JSON.stringify([test.project, sourcePath, test.line, test.column, test.titlePath, test.repeatEachIndex])).digest('hex');\n const unitKey = `test:${testId}`;\n units.add(unitKey);\n return {\n testId,\n sourcePath,\n testListPath,\n title: test.title,\n titlePath: test.titlePath,\n project: test.project,\n line: test.line,\n column: test.column,\n repeatEachIndex: test.repeatEachIndex,\n grepTitle: test.grepTitle,\n area: options.areaForPath(sourcePath),\n unitKey,\n };\n });\n\n // externalPlaywrightTestKey joins project and titles with ` › `, so a title\n // containing `›` can give two different tests one key, and results would\n // attach to the wrong test. Titles without `›` keep their existing keys.\n const identityByKey = new Map<string, string>();\n for (const row of rows) {\n const identityPath = [...(row.project ? [row.project] : []), ...row.titlePath];\n const key = externalPlaywrightTestKey(null, row.sourcePath, identityPath);\n const identity = JSON.stringify([row.project, row.titlePath]);\n const previous = identityByKey.get(key);\n if (previous !== undefined && previous !== identity && (previous.includes('›') || identity.includes('›'))) {\n throw new Error(`Playwright test at ${row.sourcePath}:${row.line} shares the test identity \"${key}\" with another test because a title contains \"›\"; rename one so the joined titles differ.`);\n }\n identityByKey.set(key, identity);\n }\n\n // A test-list row selects every test whose titles start with the row's\n // titles (a row for the unnamed project carries no `[project]` and matches\n // every project; a length-0 prefix is a row with no titles). Keep each row's\n // selection inside its group so one attempt never runs another group's test.\n const byTitlePrefix = new Map<string, Array<{ project: string; unitKey: string }>>();\n for (const row of rows) {\n for (let length = 0; length <= row.titlePath.length; length += 1) {\n const prefix = JSON.stringify([row.testListPath, ...row.titlePath.slice(0, length)]);\n const members = byTitlePrefix.get(prefix) ?? [];\n members.push({ project: row.project, unitKey: row.unitKey });\n byTitlePrefix.set(prefix, members);\n }\n }\n for (const row of rows) {\n const selected = byTitlePrefix.get(JSON.stringify([row.testListPath, ...playwrightTestListTitlePath(row.titlePath)])) ?? [];\n for (const member of selected) {\n if (!row.project || member.project === row.project) units.union(row.unitKey, member.unitKey);\n }\n }\n\n // Every nested serial describe participates. A test nested below two serial\n // suites stays connected to both complete suites.\n const serialUnit = new Map<string, string>();\n for (const [index, test] of input.tests.entries()) {\n const unitKey = rows[index]!.unitKey;\n for (const serialSuite of test.serialPath) {\n const previous = serialUnit.get(serialSuite);\n if (previous) units.union(previous, unitKey);\n else serialUnit.set(serialSuite, unitKey);\n }\n }\n\n const projectUnits = new DisjointSet();\n for (const name of projects.keys()) projectUnits.add(name);\n for (const project of projects.values()) {\n for (const dependency of [...project.dependencies, ...(project.teardown ? [project.teardown] : [])]) projectUnits.union(project.name, dependency);\n }\n const testsByConnectedProject = new Map<string, string[]>();\n for (const row of rows) {\n const root = projectUnits.find(row.project);\n const members = testsByConnectedProject.get(root) ?? [];\n members.push(row.unitKey);\n testsByConnectedProject.set(root, members);\n }\n for (const [projectRoot, testUnits] of testsByConnectedProject) {\n const connectedProjects = [...projects.keys()].filter((name) => projectUnits.find(name) === projectRoot);\n const hasEdges = connectedProjects.some((name) => {\n const project = projects.get(name)!;\n return project.dependencies.length > 0 || project.teardown !== undefined;\n });\n if (hasEdges) for (const testUnit of testUnits.slice(1)) units.union(testUnits[0]!, testUnit);\n }\n\n const grouped = new Map<string, typeof rows>();\n for (const row of rows) {\n const root = units.find(row.unitKey);\n const group = grouped.get(root) ?? [];\n group.push(row);\n grouped.set(root, group);\n }\n return [...grouped.values()].map((tests) => {\n const groupKey = createHash('sha256').update(tests.map((test) => test.testId).sort().join('\\n')).digest('hex');\n const area = [...new Set(tests.map((test) => test.area))].sort().join(', ');\n return {\n groupKey,\n area,\n tests: tests.map(({ unitKey: _unitKey, ...test }) => ({ ...test, groupKey })),\n };\n });\n}\n","/**\n * The in-container mocha boundary hook.\n *\n * @module test-reporters/mocha-boundary-hook\n * @description Records, for every test mocha runs, the wall-clock window it\n * occupied: `{titlePath, file, start, end, state}` appended as JSONL to\n * `$COFACTOR_CAPTURE_DIR/boundaries.jsonl`. That window is what lets us say\n * \"this test is the 4.2s starting 61.8s into the video\" — mochawesome reports a\n * duration but no absolute start, so without this there is nothing to align a\n * recording against.\n *\n * The clock is deliberately `Date.now()`: the same absolute epoch the collector\n * stamps its console/network entries with, and the same one `frameSwapWallTimeMs`\n * carries out of a Playwright trace. One clock, three producers, no rebasing.\n *\n * ## Why the source lives here as a string\n *\n * This code does not run in our runtime. It runs inside the customer's container,\n * under *their* Node and *their* mocha, loaded by `--require` with no build step\n * and no resolution against this monorepo. So it must be plain CommonJS with no\n * imports — which it is.\n *\n * It is a string rather than a checked-in `.cjs` asset because the API ships as a\n * bundle (`bun run dist/server.js`): a sibling file in `packages/` cannot be\n * located from bundled output by any stable path, and a resolution that works in\n * dev and silently fails in production is the worst of both. As a constant it is\n * simply part of the bundle. The tests write it to disk and `require()` it\n * against fake mocha contexts, so it is executed, not merely compared.\n *\n * ## Why it can't fail a customer's test\n *\n * Every statement that touches the filesystem or mocha's runner state is inside\n * a `try`/`catch` that swallows. With `COFACTOR_CAPTURE_DIR` unset it installs\n * hooks that immediately return, so an uncaptured attempt pays two no-op calls\n * per test. A capture bug of ours must never turn a customer's green suite red.\n */\n\n/** Filename the hook appends to inside `$COFACTOR_CAPTURE_DIR`. */\nexport const BOUNDARIES_FILENAME = 'boundaries.jsonl';\n\n/** Filename the hook is written as inside the prepared workspace. */\nexport const MOCHA_BOUNDARY_HOOK_FILENAME = 'mocha-boundary.cjs';\n\n/**\n * Plain CommonJS source of the mocha root-hook plugin.\n *\n * Exported as `mochaHooks` (the Mocha 8+ root hook plugin contract) rather than\n * bare top-level `beforeEach`/`afterEach` calls: `--require`d files are loaded\n * before mocha's BDD globals exist, so the top-level form is a `ReferenceError`\n * on any modern mocha — and it is the only form that works under `--parallel`.\n */\nexport const MOCHA_BOUNDARY_HOOK_SOURCE = `'use strict';\n// Generated by @chatsdet/test-reporters — records per-test wall-clock windows\n// for video/diagnostics alignment. Safe to delete; safe to ignore.\nvar fs = require('fs');\nvar path = require('path');\n\nvar dir = process.env.COFACTOR_CAPTURE_DIR;\nvar outFile = null;\n\nif (dir) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n outFile = path.join(dir, '${BOUNDARIES_FILENAME}');\n } catch (err) {\n outFile = null;\n }\n}\n\n// Keyed by the mocha Test object so a retried or repeated title can't collide.\nvar starts = new WeakMap();\nvar driver = null;\nvar MAX_DOM_BYTES = 2 * 1024 * 1024;\n\n// Capture the customer's Selenium driver without requiring a repo change. The\n// hook is loaded before their config builds it, so patching Builder#build here\n// sees the singleton as soon as it is created. Every failure below is isolated:\n// diagnostics must never change the suite verdict.\ntry {\n var webdriver = require('selenium-webdriver');\n var originalBuild = webdriver.Builder && webdriver.Builder.prototype.build;\n if (typeof originalBuild === 'function') {\n webdriver.Builder.prototype.build = function () {\n var built = originalBuild.apply(this, arguments);\n Promise.resolve(built).then(function (value) { driver = value; }, function () {});\n return built;\n };\n }\n} catch (err) {\n // Non-Selenium suite, or a different module layout: boundaries still work.\n}\n\nfunction titlePathOf(test) {\n try {\n if (typeof test.titlePath === 'function') {\n var parts = test.titlePath();\n if (Array.isArray(parts) && parts.length > 0) return parts;\n }\n } catch (err) {\n // fall through\n }\n return [String((test && test.title) || '')];\n}\n\nfunction record(line) {\n try {\n fs.appendFileSync(outFile, JSON.stringify(line) + '\\\\n');\n } catch (err) {\n // Losing a boundary costs alignment for one test. Failing here would cost\n // the customer their test run.\n }\n}\n\nfunction boundedUtf8(value, maxBytes) {\n try {\n var bytes = Buffer.from(String(value || ''), 'utf8');\n if (bytes.length <= maxBytes) return { text: bytes.toString('utf8'), truncated: false };\n return { text: bytes.subarray(0, maxBytes).toString('utf8'), truncated: true };\n } catch (err) {\n return { text: '', truncated: false };\n }\n}\n\nexports.mochaHooks = {\n beforeEach: function () {\n if (!outFile) return;\n try {\n var test = this.currentTest;\n if (test) starts.set(test, Date.now());\n } catch (err) {\n // ignore\n }\n },\n afterEach: async function () {\n if (!outFile) return;\n try {\n var test = this.currentTest;\n if (!test) return;\n var end = Date.now();\n var start = starts.get(test);\n record({\n titlePath: titlePathOf(test),\n file: test.file || null,\n // A test that never reached beforeEach (a failed before-hook) still gets\n // a well-formed zero-width window rather than being dropped.\n start: typeof start === 'number' ? start : end,\n end: end,\n state: test.state || null,\n });\n if (test.state === 'failed' && driver) {\n var stem = titlePathOf(test).join('__').replace(/[^a-zA-Z0-9_.-]+/g, '_').slice(-120);\n try {\n var png = await driver.takeScreenshot();\n fs.writeFileSync(path.join(dir, 'failure-' + end + '-' + stem + '.png'), png, 'base64');\n } catch (err) {\n // Screenshot support is browser-dependent.\n }\n try {\n var logs = await driver.manage().logs().get('browser');\n fs.writeFileSync(\n path.join(dir, 'failure-' + end + '-' + stem + '.browser.json'),\n JSON.stringify(logs).slice(-131072)\n );\n } catch (err) {\n // Chrome logging may not be enabled by the customer's capabilities.\n }\n try {\n var dom = boundedUtf8(await driver.getPageSource(), MAX_DOM_BYTES);\n var domName = 'failure-' + end + '-' + stem + '.dom.html';\n fs.writeFileSync(path.join(dir, domName), dom.text, 'utf8');\n fs.writeFileSync(\n path.join(dir, domName + '.meta.json'),\n JSON.stringify({ truncated: dom.truncated, maxBytes: MAX_DOM_BYTES })\n );\n } catch (err) {\n // DOM support is browser-dependent and must never replace the failure.\n }\n }\n } catch (err) {\n // ignore\n }\n },\n};\n`;\n","import { z } from 'zod';\n\n/** One explicit Playwright PNG attachment harvested as a visual checkpoint. */\nexport type PlaywrightVisualAttachment = {\n specFile: string;\n titlePath: string[];\n attachmentName: string;\n retry: number;\n sha256: string;\n relPath: string;\n sizeBytes: number;\n};\n\n/** The checkpoint identity of an attachment: spec file, test title, and name. */\nexport const playwrightCheckpointKey = (\n attachment: Pick<PlaywrightVisualAttachment, 'specFile' | 'titlePath' | 'attachmentName'>\n): string =>\n `playwright:${attachment.specFile}#${attachment.titlePath.join(' › ')}#${attachment.attachmentName}`;\n\nconst visualAttachmentLineSchema = z\n .object({\n file: z.string().min(1).max(1000),\n titlePath: z.array(z.string().min(1).max(1000)).min(1),\n name: z.string().min(1).max(1000),\n retry: z.number().int().nonnegative(),\n sha256: z.string().regex(/^[a-f0-9]{64}$/),\n relPath: z.string(),\n sizeBytes: z.number().int().positive().max(5 * 1024 * 1024),\n superseded: z.boolean().optional(),\n })\n .superRefine((line, context) => {\n if (line.relPath !== `visual/${line.sha256}.png`) {\n context.addIssue({ code: 'custom', path: ['relPath'], message: 'Invalid content-addressed path' });\n }\n });\n\nfunction parseAttachment(value: unknown): PlaywrightVisualAttachment | null {\n const parsed = visualAttachmentLineSchema.safeParse(value);\n if (!parsed.success || parsed.data.superseded === true) return null;\n const line = parsed.data;\n return {\n specFile: line.file,\n titlePath: line.titlePath,\n attachmentName: line.name,\n retry: line.retry,\n sha256: line.sha256,\n relPath: line.relPath,\n sizeBytes: line.sizeBytes,\n };\n}\n\n/** Parse reporter JSONL, skipping notes, superseded rows, and malformed lines. */\nexport function parseVisualAttachments(jsonl: string): PlaywrightVisualAttachment[] {\n const attachments: PlaywrightVisualAttachment[] = [];\n for (const line of jsonl.split(/\\r?\\n/)) {\n if (line.length === 0) continue;\n try {\n const attachment = parseAttachment(JSON.parse(line) as unknown);\n if (attachment) attachments.push(attachment);\n } catch {\n // A malformed diagnostic line must not prevent valid attachments from being read.\n }\n }\n return attachments;\n}\n","/** Catalog listing and inspection for named test suites.\n *\n * @module test-suite-catalog\n * @see apps/api/src/test-suites/routes.ts\n */\n\nimport process from 'node:process';\nimport { getPositionalArg, resolveTestSuite, apiRequest } from './cli-helpers.js';\nimport { hasFlag } from './auth.js';\nimport { writeRawOutput } from './brand.js';\n\nexport type Suite = {\n id: string;\n name: string;\n description: string | null;\n kind: 'native' | 'external';\n isDefault: boolean;\n failureMode: 'continue' | 'stop_on_layer_failure';\n environmentId: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type SuiteMember = {\n workflowId: string;\n workflowName: string;\n health: string;\n layerIndex: number | null;\n orderIndex: number;\n};\n\nexport type SuiteDetail = Suite & {\n members: SuiteMember[];\n externalRunner?: {\n propertyId: string | null;\n shardDirectories: string[] | null;\n areaGeneratedPrefix: string | null;\n } | null;\n};\n\nexport type SuiteListItem = Suite & { workflowCount: number; layerCount: number };\nexport type SuiteResponse = { ok: boolean; error?: string; data?: Suite };\nexport type SuiteListResponse = { ok: boolean; error?: string; data?: SuiteListItem[] };\nexport type SuiteDetailResponse = { ok: boolean; error?: string; data?: SuiteDetail };\n\nexport async function handleSuitesList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const res = await apiRequest<SuiteListResponse>(apiUrl, token, 'GET', '/test-suites');\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to list test suites'}`);\n process.exit(1);\n }\n\n const suites = res.data ?? [];\n if (jsonOutput) {\n writeRawOutput(JSON.stringify(suites, null, 2));\n return;\n }\n if (suites.length === 0) {\n console.log('No test suites found.');\n return;\n }\n writeRawOutput(formatSuitesTable(suites));\n}\n\nexport async function handleSuiteCatalogGet(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<void> {\n const suiteRef = getPositionalArg(argv, ['--api-url', '--token', '--org', '--env']);\n if (!suiteRef) {\n console.error('Usage: cofactor test-suite suites get <suite-id|name> [--json]');\n process.exit(1);\n }\n const suite = await resolveTestSuite(suiteRef, apiUrl, token);\n const response = await apiRequest<SuiteDetailResponse>(\n apiUrl,\n token,\n 'GET',\n `/test-suites/${encodeURIComponent(suite.id)}`\n );\n if (!response.ok || !response.data) {\n console.error(`Error: ${response.error ?? 'Failed to read test suite'}`);\n process.exit(1);\n }\n const detail = response.data;\n if (hasFlag(argv, '--json')) {\n writeRawOutput(JSON.stringify(detail, null, 2));\n return;\n }\n writeRawOutput(\n [\n `Suite: ${detail.name}`,\n `ID: ${detail.id}`,\n `Default: ${detail.isDefault ? 'yes' : 'no'}`,\n `Kind: ${detail.kind}`,\n `Failure mode: ${detail.failureMode}`,\n `Members: ${detail.members.length}`,\n ].join('\\n')\n );\n}\n\nfunction formatSuitesTable(suites: readonly SuiteListItem[]): string {\n const lines = [\n `Named suites (${suites.length}):`,\n '',\n ' NAME KIND DEFAULT MEMBERS LAYERS FAILURE MODE ID',\n ];\n for (const suite of suites) {\n lines.push(\n ` ${suite.name.padEnd(30)} ${suite.kind.padEnd(9)} ${String(suite.isDefault ? 'yes' : 'no').padEnd(7)} ` +\n `${String(suite.workflowCount).padEnd(8)} ${String(suite.layerCount).padEnd(7)} ` +\n `${suite.failureMode.padEnd(22)} ${suite.id}`\n );\n }\n lines.push('');\n return lines.join('\\n');\n}\n"],"mappings":"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AAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,M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","names":["process","external","env","cred","path","path","process","z","z","path","fail","token","process","process","process","process"]}
|