@qwen-code/qwen-code 0.21.6-preview.0 → 0.21.6
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/bundled/qc-helper/docs/features/channels/github.md +31 -19
- package/bundled/qc-helper/docs/features/code-review.md +3 -1
- package/bundled/review/SKILL.md +16 -11
- package/chunks/{MaxSizedBox-A3UYJS6B.js → MaxSizedBox-2HFKP4LI.js} +8 -8
- package/chunks/{StandaloneSessionPicker-NGLY26I4.js → StandaloneSessionPicker-RBV72M5N.js} +23 -23
- package/chunks/{acp-startup-profiler-3RICG2YW.js → acp-startup-profiler-ORIQ2CCQ.js} +2 -2
- package/chunks/{acpAgent-V54T2EEL.js → acpAgent-WO6JFCVQ.js} +1059 -118
- package/chunks/{agent-2P53VL2L.js → agent-AHGLYNZ4.js} +8 -8
- package/chunks/{agent-headless-6X4GCFRD.js → agent-headless-NTXKKGRO.js} +8 -8
- package/chunks/{bridge-TCFMLKHR.js → bridge-RPAU64CA.js} +13 -13
- package/chunks/{channel-management-service-5XPPTWUQ.js → channel-management-service-IGEUOVRT.js} +1 -1
- package/chunks/{channel-settings-store-B4HNMNQV.js → channel-settings-store-ON64MF7G.js} +15 -15
- package/chunks/{channel-worker-group-SVGPDH2C.js → channel-worker-group-JWQK224X.js} +5 -5
- package/chunks/{channel-worker-manager-72ZK2GTS.js → channel-worker-manager-77E3OXRQ.js} +5 -5
- package/chunks/{channel-worker-supervisor-NUEDVHX4.js → channel-worker-supervisor-62YWUGP2.js} +3 -3
- package/chunks/{chunk-AFZTZLFB.js → chunk-2POQWYM6.js} +2 -2
- package/chunks/{chunk-RTWF7FF7.js → chunk-3LZKY4V4.js} +3 -3
- package/chunks/{chunk-T4XY5CT4.js → chunk-3UOLYNTF.js} +5 -5
- package/chunks/{chunk-WAOLM6SQ.js → chunk-4JH77A2U.js} +1 -1
- package/chunks/{chunk-MISUEWB4.js → chunk-4S4OEQ6U.js} +10 -6
- package/chunks/{chunk-URJHXOSO.js → chunk-4WTAQEHV.js} +1 -1
- package/chunks/{chunk-BU4BRCPX.js → chunk-536SWZTA.js} +5 -5
- package/chunks/{chunk-6KEN3RIC.js → chunk-5MJGUQU5.js} +3 -3
- package/chunks/{chunk-Z5S6KH2B.js → chunk-75QMRMO7.js} +4 -4
- package/chunks/{chunk-DOA7MCDY.js → chunk-A4VTILZT.js} +898 -847
- package/chunks/{chunk-72DZPDH4.js → chunk-ACZRB7AD.js} +8 -3
- package/chunks/{chunk-P7LKADIT.js → chunk-BOGOR4HB.js} +5 -5
- package/chunks/{chunk-QL4TN4HS.js → chunk-BRVWYMKV.js} +1 -1
- package/chunks/{chunk-7FUVSN4D.js → chunk-C4CBJQKY.js} +1 -1
- package/chunks/{chunk-X6DV3WKN.js → chunk-CA4UIDFU.js} +1 -1
- package/chunks/{chunk-MVLM6PJK.js → chunk-CJ5WLD5Y.js} +6 -2
- package/chunks/{chunk-6D6V55ZQ.js → chunk-DIT4V3XH.js} +1 -1
- package/chunks/{chunk-DOICUTPO.js → chunk-DVBEGGLG.js} +8 -8
- package/chunks/{chunk-DTAPI453.js → chunk-EMYZIABH.js} +1 -1
- package/chunks/{chunk-4E5PO6R7.js → chunk-EXCEQD22.js} +3 -3
- package/chunks/{chunk-EHMN6SEG.js → chunk-FZFP7RZI.js} +3 -3
- package/chunks/{chunk-C4GRKMUL.js → chunk-G5NNWEYE.js} +5 -5
- package/chunks/{chunk-QWUYFMAR.js → chunk-GESMMPAK.js} +33 -33
- package/chunks/{chunk-WPKIU4PA.js → chunk-GK2H5GRC.js} +4 -4
- package/chunks/{chunk-SQ3ZJOYL.js → chunk-GWRHVJY2.js} +11 -11
- package/chunks/{chunk-BK2UNYWD.js → chunk-HIBNSEJE.js} +12 -0
- package/chunks/{chunk-5CDI4UOY.js → chunk-HY25ULVN.js} +1 -1
- package/chunks/{chunk-IISDPZ5X.js → chunk-IMOQO6YL.js} +1 -1
- package/chunks/{chunk-ZQL73PPE.js → chunk-JE44IPH6.js} +1 -1
- package/chunks/{chunk-NYZAL2W2.js → chunk-K2B3X3E7.js} +3 -3
- package/chunks/{chunk-OWAK7LMW.js → chunk-KGJGEEVR.js} +7 -0
- package/chunks/{chunk-546CDN6D.js → chunk-KHUA3NQV.js} +2 -2
- package/chunks/{chunk-7GYP5COR.js → chunk-LAAFLUQV.js} +1 -1
- package/chunks/{chunk-XNZBXQCG.js → chunk-MKVZE4ZJ.js} +1 -1
- package/chunks/{chunk-N47ZM2KI.js → chunk-N2GJU6KI.js} +9 -9
- package/chunks/{chunk-WIPQR44Y.js → chunk-NGJOAKJY.js} +3 -3
- package/chunks/chunk-NKLP3DCK.js +22 -0
- package/chunks/{chunk-3ZRS2XNY.js → chunk-NKSF7HYF.js} +1 -1
- package/chunks/{chunk-HKNSU4WX.js → chunk-O7V7N4G7.js} +1 -1
- package/chunks/{chunk-CJBRIJ7W.js → chunk-ODPXHGLL.js} +2 -2
- package/chunks/{chunk-4T6QMNX2.js → chunk-OP2OHZ7K.js} +183 -10
- package/chunks/{chunk-CDHNGCJI.js → chunk-OWSW7EYP.js} +5 -5
- package/chunks/{chunk-FDV3CXTD.js → chunk-OXX3FG2N.js} +2 -2
- package/chunks/{chunk-YUVTZ4UH.js → chunk-PPUOYL77.js} +70 -5
- package/chunks/{chunk-O656RSMC.js → chunk-PX5DNLSA.js} +1 -1
- package/chunks/{chunk-6KZP75GT.js → chunk-Q5RM32DR.js} +1 -1
- package/chunks/{chunk-AU3XNTMV.js → chunk-QZKYZCN3.js} +1 -1
- package/chunks/{chunk-UKZEXS6K.js → chunk-R574ATRM.js} +11 -0
- package/chunks/{chunk-XKTCA6BW.js → chunk-R5RBXLNC.js} +3 -3
- package/chunks/{chunk-NAYPZ72V.js → chunk-RFUHDCNF.js} +1 -1
- package/chunks/{chunk-QG2ACINA.js → chunk-RHTTKJTP.js} +1 -1
- package/chunks/{chunk-IKXE3AAC.js → chunk-RK2EE3T7.js} +1 -1
- package/chunks/{chunk-3DTM3RPU.js → chunk-S7CV4KO6.js} +3 -3
- package/chunks/{chunk-ZH7G3A4U.js → chunk-SKNE3KQC.js} +3 -3
- package/chunks/{chunk-PQTK2FVO.js → chunk-SLSWFHDF.js} +3 -3
- package/chunks/{chunk-2U7GPHA6.js → chunk-SQC6K5HI.js} +1 -1
- package/chunks/{chunk-Y5HIDFKZ.js → chunk-SQOMTWQT.js} +4 -4
- package/chunks/{chunk-CXYBX4AL.js → chunk-SUKEUUAA.js} +1 -1
- package/chunks/{chunk-WXS647W5.js → chunk-T4JSA7KU.js} +2 -2
- package/chunks/{chunk-I7JDGNG6.js → chunk-T5U6IM4C.js} +6 -2
- package/chunks/{chunk-TVFC3XF5.js → chunk-TGGEZINK.js} +5 -5
- package/chunks/{chunk-AVDEBBMI.js → chunk-TOGZTG4X.js} +2 -2
- package/chunks/{chunk-A6SX5TAH.js → chunk-TSERKWCX.js} +6 -2
- package/chunks/{chunk-XSGQKR37.js → chunk-U4AF3QLU.js} +355 -17
- package/chunks/{chunk-WIRAPZ62.js → chunk-UGTWD35F.js} +7 -1
- package/chunks/{chunk-DG563ZCS.js → chunk-ULPQQSDN.js} +2 -2
- package/chunks/{chunk-DBIEZC7T.js → chunk-VGFPFM4U.js} +3 -3
- package/chunks/{chunk-VDLXPEI5.js → chunk-VNQCPBC2.js} +3 -3
- package/chunks/{chunk-WVRJKSIG.js → chunk-VSALQLT7.js} +1 -1
- package/chunks/{chunk-EKWNNQQD.js → chunk-W5DXUTXD.js} +12 -6
- package/chunks/{chunk-M744OFVE.js → chunk-W7U4ESW2.js} +1 -1
- package/chunks/{chunk-MFBUJMQ3.js → chunk-WNU7TZTO.js} +4 -4
- package/chunks/{chunk-GTM6IHBB.js → chunk-WO2B5E5B.js} +1 -0
- package/chunks/{chunk-SPUDIAHX.js → chunk-XA4TMLFN.js} +11 -11
- package/chunks/{chunk-XOZ2R6XI.js → chunk-XM2O73NC.js} +1245 -295
- package/chunks/{chunk-NKST54XA.js → chunk-YMBOEAF4.js} +1 -1
- package/chunks/{chunk-QONSRAEV.js → chunk-YP5KH5Y7.js} +1 -1
- package/chunks/{chunk-XZCMQUOF.js → chunk-YZQTA3ID.js} +20 -11
- package/chunks/{computer-use-GTOP2CVH.js → computer-use-5HXJ2P4X.js} +8 -8
- package/chunks/{config-utils-LIRO7NSU.js → config-utils-VXD4SPVR.js} +2 -2
- package/chunks/{contextCommand-K6T6RRF3.js → contextCommand-7BEHRX2H.js} +11 -11
- package/chunks/{core-runtime-D2626QQU.js → core-runtime-U4VJ5TIV.js} +8 -8
- package/chunks/create-sub-session-QZNQY332.js +772 -0
- package/chunks/{daemon-CCIX4BMG.js → daemon-YI5RY62O.js} +115 -3
- package/chunks/{daemon-status-provider-2EHRZZVF.js → daemon-status-provider-UJUGTDTL.js} +17 -17
- package/chunks/{daemon-trust-policy-B3EPDJDR.js → daemon-trust-policy-ZHDD5VYQ.js} +14 -14
- package/chunks/{daemon-trust-policy-monitor-MFM5X26G.js → daemon-trust-policy-monitor-5SHYBDGA.js} +14 -14
- package/chunks/{deferred-core-runtime-KXN7HLN7.js → deferred-core-runtime-QWAEBTR5.js} +8 -8
- package/chunks/discovery-XLHITE74.js +220 -0
- package/chunks/{dist-IKGVITP3.js → dist-KS4O2NKE.js} +99 -6
- package/chunks/{earlyInputCapture-WUNYYFOS.js → earlyInputCapture-5BMSGKOI.js} +8 -8
- package/chunks/{edit-DMFCBP2D.js → edit-IVQQVYYK.js} +8 -8
- package/chunks/{enter-worktree-5SVBCXFC.js → enter-worktree-P3DF2N6O.js} +8 -8
- package/chunks/{enterPlanMode-QUIZFQ4M.js → enterPlanMode-KKTDVLAD.js} +8 -8
- package/chunks/{environment-U6QP23VJ.js → environment-W5TRDM3G.js} +11 -11
- package/chunks/{errors-GZWFA6ON.js → errors-GJJB36IG.js} +11 -11
- package/chunks/{exit-worktree-FUB44KAF.js → exit-worktree-LV5RLOCU.js} +8 -8
- package/chunks/{exitPlanMode-XSHHYR73.js → exitPlanMode-TUGOB2LL.js} +8 -8
- package/chunks/{fast-path-JHQJSIMZ.js → fast-path-2FU23PAQ.js} +2 -2
- package/chunks/{gemini-O44ETOKT.js → gemini-KDULDQPP.js} +47 -47
- package/chunks/{geminiContentGenerator-TTM4TZJM.js → geminiContentGenerator-LOCFHNVA.js} +1 -1
- package/chunks/{glob-YECOWTRW.js → glob-Z4NQFKWS.js} +8 -8
- package/chunks/{grep-BZO4LOTA.js → grep-Z67Z7EN6.js} +8 -8
- package/chunks/{handleAutoUpdate-TOO52D6H.js → handleAutoUpdate-DFUZE6I6.js} +13 -13
- package/chunks/{i18n-ARJYXZQ5.js → i18n-R4FMZ7N2.js} +10 -10
- package/chunks/{image-gen-J6Q2YBEU.js → image-gen-4CQJPQP5.js} +1 -1
- package/chunks/{initializer-CEZ4RPQV.js → initializer-DK672ZVE.js} +14 -14
- package/chunks/{installationInfo-AEGIIQAT.js → installationInfo-PO4Z3ES7.js} +9 -9
- package/chunks/{list-7XLPV5GC.js → list-QXQF6C53.js} +17 -17
- package/chunks/{loadedSettingsAdapter-YK5SBHOT.js → loadedSettingsAdapter-4D7GUGW6.js} +14 -14
- package/chunks/{loggingContentGenerator-I7QDXS43.js → loggingContentGenerator-2P3MNACM.js} +3 -3
- package/chunks/{managed-npm-update-YSL7PA7G.js → managed-npm-update-LWVJQTWO.js} +21 -12
- package/chunks/{mcp-RKFQZXP6.js → mcp-GHETAR6V.js} +14 -14
- package/chunks/{monitor-QHHJIKGL.js → monitor-4T7W4M6Q.js} +8 -8
- package/chunks/{nonInteractiveCli-XEBIE7MG.js → nonInteractiveCli-P4UKCJFM.js} +42 -42
- package/chunks/{notebook-edit-SG7X2EQA.js → notebook-edit-OC2V7U5D.js} +8 -8
- package/chunks/{openaiContentGenerator-63CVR33K.js → openaiContentGenerator-RAJUFWQY.js} +3 -3
- package/chunks/{pidfile-I3CXJGQD.js → pidfile-HVPYVRLS.js} +8 -8
- package/chunks/{processUtils-LJ3DSANX.js → processUtils-VIQ4JHVX.js} +2 -2
- package/chunks/{qwenContentGenerator-JINBVCH6.js → qwenContentGenerator-2QLCUFNZ.js} +9 -9
- package/chunks/{qwenOAuth2-SY2O3NRR.js → qwenOAuth2-J2X3EN43.js} +1 -1
- package/chunks/{read-file-PGTXF25I.js → read-file-ZNAN2B26.js} +2 -2
- package/chunks/{resumeHistoryUtils-FB2NFVZ2.js → resumeHistoryUtils-RCY7AL5Y.js} +12 -12
- package/chunks/{ripGrep-IY3KGPM6.js → ripGrep-C3KMLZM5.js} +8 -8
- package/chunks/{run-qwen-serve-UYEMGPKA.js → run-qwen-serve-3JN75CIQ.js} +481 -74
- package/chunks/{runtime-CG3BKRFE.js → runtime-VUA4WQYD.js} +17 -17
- package/chunks/{scheduler-VFUVGDE5.js → scheduler-Z4IBXCOY.js} +8 -8
- package/chunks/{serve-ZCCQ2G2L.js → serve-67T3P7XI.js} +14 -14
- package/chunks/{server-WS7LWXPP.js → server-46ZO2CLV.js} +7648 -596
- package/chunks/{session-IQLCT32T.js → session-B4IFAFC4.js} +45 -45
- package/chunks/{settings-NX4EUIE6.js → settings-AI2BTBOZ.js} +13 -13
- package/chunks/{shell-THDYM4CS.js → shell-BKII3B6E.js} +8 -8
- package/chunks/{skill-OXXZBNQB.js → skill-6CFOWVGA.js} +3 -3
- package/chunks/{skill-settings-T3JZ33T2.js → skill-settings-6BFQWMW4.js} +13 -13
- package/chunks/{spawnChannel-COLJMSA7.js → spawnChannel-FJXW35U7.js} +10 -10
- package/chunks/{standalone-update-ICW7H5IF.js → standalone-update-WVINHRNS.js} +11 -11
- package/chunks/{startInteractiveUI-6BDRXSMF.js → startInteractiveUI-YE57CJ57.js} +132 -132
- package/chunks/{stdioHelpers-HGIYTWAY.js → stdioHelpers-7A2EE64Z.js} +5 -3
- package/chunks/{task-create-2X4UP4F3.js → task-create-Q727MXHJ.js} +2 -2
- package/chunks/{task-list-WOLJPZ64.js → task-list-G6KPQ5JT.js} +1 -1
- package/chunks/{task-update-VDUSN36E.js → task-update-YB7PXO4R.js} +2 -2
- package/chunks/{team-create-BCSMDK4Z.js → team-create-GNC7NFY6.js} +8 -8
- package/chunks/{team-delete-D2VMSDOT.js → team-delete-GDO7H2T4.js} +1 -1
- package/chunks/{team-plan-approval-B5YRLJFV.js → team-plan-approval-ECALJLIO.js} +8 -8
- package/chunks/{terminal-image-renderer-PW6Z6VFY.js → terminal-image-renderer-II74TFVW.js} +8 -8
- package/chunks/{theme-manager-CMVKD2JH.js → theme-manager-2MGEDD22.js} +8 -8
- package/chunks/{tool-search-SQTUSG6P.js → tool-search-S6LRRACA.js} +2 -2
- package/chunks/{total-session-admission-XAXOSE46.js → total-session-admission-7WVAWQPU.js} +13 -13
- package/chunks/{trustedFolders-Z2UAEG2V.js → trustedFolders-NFS4KHO4.js} +10 -10
- package/chunks/{update-relaunch-JBLI6LJF.js → update-relaunch-Q5HLZ6UW.js} +6 -6
- package/chunks/{updateCheck-FDAVGOFT.js → updateCheck-UOVZSTP7.js} +12 -12
- package/chunks/{useAutoAcceptIndicator-PDZFIYRM.js → useAutoAcceptIndicator-PC6MOJCO.js} +16 -16
- package/chunks/{validateNonInterActiveAuth-Q4763ONQ.js → validateNonInterActiveAuth-YMQP3ZM7.js} +39 -39
- package/chunks/{version-C7MPCGWD.js → version-T4AQFZJH.js} +1 -1
- package/chunks/{web-fetch-L7RAPOJB.js → web-fetch-JQCJHEEX.js} +2 -2
- package/chunks/{web-search-IDOYUOWX.js → web-search-QGZ2KY4G.js} +2 -2
- package/chunks/{workflow-HXURUJB5.js → workflow-YIT27YWZ.js} +9 -9
- package/chunks/{workspace-providers-status-JZ3GPWNU.js → workspace-providers-status-FIDZQ2PL.js} +17 -17
- package/chunks/{workspace-registration-store-SM2PWB6L.js → workspace-registration-store-RCSPE4DU.js} +1 -1
- package/chunks/{workspace-registry-6W4ES7BJ.js → workspace-registry-5PEUCY6E.js} +13 -13
- package/chunks/{workspace-service-V47ZFJRX.js → workspace-service-LANDVPL7.js} +18 -18
- package/chunks/{workspace-skills-status-6ZQ45XKA.js → workspace-skills-status-2IQVJNIN.js} +15 -15
- package/chunks/{workspace-trust-reconciler-6V25LMCN.js → workspace-trust-reconciler-CZPZZCZC.js} +22 -22
- package/chunks/{write-file-H2QOF25K.js → write-file-G5VNGCOG.js} +8 -8
- package/chunks/{zoom-image-JTUSS43N.js → zoom-image-6RBLD7X6.js} +2 -2
- package/cli.js +15 -15
- package/package.json +3 -3
- package/web-shell/assets/{arc-DtI1rZcQ.js → arc-B-Vtkp1W.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BPZwSVct.js → architectureDiagram-3BPJPVTR-qmTXIj64.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BIQ03j4C.js → blockDiagram-GPEHLZMM-ZlnXEtdP.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CB0RyFGm.js → c4Diagram-AAUBKEIU-Wyoirf6Z.js} +1 -1
- package/web-shell/assets/channel-DXaHnfjS.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-B3WoS-4H.js → chunk-2J33WTMH-WQwbq9d8.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-C98xYZ1X.js → chunk-4BX2VUAB-DQKnAXC4.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-CbTIWRwQ.js → chunk-55IACEB6-DIdgXNcO.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DWGnKTPu.js → chunk-727SXJPM-CUwGOLEd.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-4__QyCEX.js → chunk-AQP2D5EJ-CCBGZFZ4.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DFtG1YCW.js → chunk-FMBD7UC4-DMGXProk.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-rvAhW51N.js → chunk-ND2GUHAM-yejcFqsh.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-DfiU9pwZ.js → chunk-QZHKN3VN-DxCyqTf7.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BigU82A0.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BigU82A0.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-Cc4EIdxu.js → cose-bilkent-S5V4N54A-DOrF3cg_.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CZNj4dGW.js → dagre-BM42HDAG-Be6CdYQ_.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-D5tiqQCr.js → diagram-2AECGRRQ-B_Rjsft2.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-pwzw0jVO.js → diagram-5GNKFQAL-BvQbKSm1.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-4CWiM00x.js → diagram-KO2AKTUF-BsdmMdpS.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-Dd7rc7Qf.js → diagram-LMA3HP47-CrQlBaNr.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-_vzV52ml.js → diagram-OG6HWLK6-aB1MD_DL.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CqbE2bx_.js → erDiagram-TEJ5UH35-F-eUUn9n.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CaxNr7w4.js → flowDiagram-I6XJVG4X-DY_d8lUK.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-AGjrtfUA.js → ganttDiagram-6RSMTGT7-Dqu7KBPg.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-ADG2zSkc.js → gitGraphDiagram-PVQCEYII-2IkU_VEj.js} +1 -1
- package/web-shell/assets/{index-BOryKCqt.js → index-BuSbqggh.js} +1 -1
- package/web-shell/assets/index-DrfC2e9s.js +1768 -0
- package/web-shell/assets/index-QQlUCJGg.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-CE3B_IoZ.js → infoDiagram-5YYISTIA-C4orwzPw.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CN-Frhoi.js → ishikawaDiagram-YF4QCWOH-fXUEfef_.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CGgezS93.js → journeyDiagram-JHISSGLW-Bs0I1_J5.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BqWijky5.js → kanban-definition-UN3LZRKU-BPRj1dw_.js} +1 -1
- package/web-shell/assets/{linear-D8sfpZf6.js → linear-DFS6ZDpW.js} +1 -1
- package/web-shell/assets/{mermaid.core-3PA4QrzM.js → mermaid.core-CZxjWMaO.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-D9QxwiCY.js → mindmap-definition-RKZ34NQL-Dsr3PmNs.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-Bioaf6uE.js → pieDiagram-4H26LBE5-D5Ngpz5Y.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DBb2AS73.js → quadrantDiagram-W4KKPZXB-WJK9I25z.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DXOvZ3KB.js → requirementDiagram-4Y6WPE33-CmrYcwOH.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-D9qg09Dm.js → sankeyDiagram-5OEKKPKP-7SjCc4Mv.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DSAUIfpw.js → sequenceDiagram-3UESZ5HK-Dl9E0IRM.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-BPZkzfQ3.js → stateDiagram-AJRCARHV-CRRio7yV.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-1atT7XaU.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-UDaQp9sP.js → timeline-definition-PNZ67QCA-DVyXjjfq.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-2ouhAnHO.js → vennDiagram-CIIHVFJN-Nb2Lckzq.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-Cq_WEvTK.js → wardley-L42UT6IY-DuL_otIP.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Dt24aXOM.js → wardleyDiagram-YWT4CUSO-DVI9Q4Aa.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-A5Xk2WCH.js → xychartDiagram-2RQKCTM6-BNjAm7KD.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/create-sub-session-MWUWNBM6.js +0 -401
- package/web-shell/assets/channel-vfbVFuM1.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-Cvr8atq3.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Cvr8atq3.js +0 -1
- package/web-shell/assets/index-Cb1LjsCv.css +0 -5
- package/web-shell/assets/index-CvJDaIy8.js +0 -1756
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DInOqnhZ.js +0 -1
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
serveCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GK2H5GRC.js";
|
|
6
6
|
import {
|
|
7
7
|
listCommand
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-536SWZTA.js";
|
|
9
9
|
import {
|
|
10
10
|
getErrorMessage as getErrorMessage2
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-FZFP7RZI.js";
|
|
12
12
|
import {
|
|
13
13
|
ObservedChannelContactStore
|
|
14
14
|
} from "./chunk-DYA25Y7U.js";
|
|
@@ -24,6 +24,11 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
isLoopbackBind
|
|
26
26
|
} from "./chunk-RXFQM6FQ.js";
|
|
27
|
+
import {
|
|
28
|
+
collectProviderModelsForProtocol,
|
|
29
|
+
getAuthTypeFromEnv,
|
|
30
|
+
resolveCliGenerationConfig
|
|
31
|
+
} from "./chunk-5MJGUQU5.js";
|
|
27
32
|
import {
|
|
28
33
|
resolvePath
|
|
29
34
|
} from "./chunk-JELIWHXD.js";
|
|
@@ -46,22 +51,17 @@ import {
|
|
|
46
51
|
registerToolCallDispatch,
|
|
47
52
|
selectFirstModel,
|
|
48
53
|
sessionsPath
|
|
49
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-OWSW7EYP.js";
|
|
50
55
|
import {
|
|
51
56
|
getExtensionManager,
|
|
52
57
|
requestChoicePluginNonInteractive,
|
|
53
58
|
requestConsentNonInteractive,
|
|
54
59
|
requestConsentOrFail,
|
|
55
60
|
resolveExtensionCommandScope
|
|
56
|
-
} from "./chunk-
|
|
57
|
-
import {
|
|
58
|
-
collectProviderModelsForProtocol,
|
|
59
|
-
getAuthTypeFromEnv,
|
|
60
|
-
resolveCliGenerationConfig
|
|
61
|
-
} from "./chunk-6KEN3RIC.js";
|
|
61
|
+
} from "./chunk-G5NNWEYE.js";
|
|
62
62
|
import {
|
|
63
63
|
parseChannelConfig
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-LAAFLUQV.js";
|
|
65
65
|
import {
|
|
66
66
|
findCliEntryPath
|
|
67
67
|
} from "./chunk-V6WHFGST.js";
|
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
isChannelDeliveryMessage,
|
|
89
89
|
isChannelStartupReportAckMessage,
|
|
90
90
|
isChannelWebhookTaskMessage
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-YP5KH5Y7.js";
|
|
92
92
|
import {
|
|
93
93
|
normalizeWorkerDiagnostic,
|
|
94
94
|
sanitizeWorkerDiagnostic
|
|
@@ -131,29 +131,29 @@ import {
|
|
|
131
131
|
assembleMcpServers,
|
|
132
132
|
getPendingGatedMcpServers,
|
|
133
133
|
mcpCommand
|
|
134
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-3UOLYNTF.js";
|
|
135
135
|
import {
|
|
136
136
|
loadSettings
|
|
137
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-PPUOYL77.js";
|
|
138
138
|
import {
|
|
139
139
|
detectSystemLanguage,
|
|
140
140
|
getCurrentLanguage,
|
|
141
141
|
initializeI18n,
|
|
142
142
|
resolveLanguageSetting,
|
|
143
143
|
t
|
|
144
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-KHUA3NQV.js";
|
|
145
145
|
import {
|
|
146
146
|
loadEnvironment
|
|
147
|
-
} from "./chunk-
|
|
147
|
+
} from "./chunk-RK2EE3T7.js";
|
|
148
148
|
import {
|
|
149
149
|
getCliVersion
|
|
150
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-YMBOEAF4.js";
|
|
151
151
|
import {
|
|
152
152
|
getPackageJson
|
|
153
153
|
} from "./chunk-VJNBRRZG.js";
|
|
154
154
|
import {
|
|
155
155
|
isWorkspaceTrusted
|
|
156
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-ACZRB7AD.js";
|
|
157
157
|
import {
|
|
158
158
|
require_strip_json_comments
|
|
159
159
|
} from "./chunk-ALGGS7UH.js";
|
|
@@ -194,29 +194,30 @@ import {
|
|
|
194
194
|
unquoteCStylePath,
|
|
195
195
|
updateChannelMemoryEntry,
|
|
196
196
|
updateSetting
|
|
197
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-A4VTILZT.js";
|
|
198
198
|
import {
|
|
199
199
|
nextFireTime,
|
|
200
200
|
parseCron
|
|
201
201
|
} from "./chunk-IRH27ZC2.js";
|
|
202
202
|
import {
|
|
203
203
|
require_dist
|
|
204
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-4S4OEQ6U.js";
|
|
205
205
|
import {
|
|
206
206
|
parseBooleanEnvFlag,
|
|
207
207
|
resolveTelemetrySettings
|
|
208
208
|
} from "./chunk-MGSSJT27.js";
|
|
209
209
|
import {
|
|
210
210
|
getAllGeminiMdFilenames,
|
|
211
|
+
parseLineTolerant,
|
|
211
212
|
setGeminiMdFilename
|
|
212
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-PX5DNLSA.js";
|
|
213
214
|
import {
|
|
214
215
|
SchemaValidator,
|
|
215
216
|
ToolNames
|
|
216
217
|
} from "./chunk-D7D7RXIJ.js";
|
|
217
218
|
import {
|
|
218
219
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
219
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-BOGOR4HB.js";
|
|
220
221
|
import {
|
|
221
222
|
isTlsVerificationDisabled
|
|
222
223
|
} from "./chunk-BFHXDAR7.js";
|
|
@@ -237,8 +238,9 @@ import {
|
|
|
237
238
|
import {
|
|
238
239
|
writeStderrLine,
|
|
239
240
|
writeStderrLineSafe,
|
|
240
|
-
writeStdoutLine
|
|
241
|
-
|
|
241
|
+
writeStdoutLine,
|
|
242
|
+
writeStdoutLineSafe
|
|
243
|
+
} from "./chunk-KGJGEEVR.js";
|
|
242
244
|
import {
|
|
243
245
|
init_esbuild_shims
|
|
244
246
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -361,9 +363,9 @@ var require_command_exists = __commonJS({
|
|
|
361
363
|
cleanInput = /* @__PURE__ */ __name(function(s) {
|
|
362
364
|
var isPathName = /[\\]/.test(s);
|
|
363
365
|
if (isPathName) {
|
|
364
|
-
var
|
|
366
|
+
var dirname25 = '"' + path3.dirname(s) + '"';
|
|
365
367
|
var basename6 = '"' + path3.basename(s) + '"';
|
|
366
|
-
return
|
|
368
|
+
return dirname25 + ":" + basename6;
|
|
367
369
|
}
|
|
368
370
|
return '"' + s + '"';
|
|
369
371
|
}, "cleanInput");
|
|
@@ -371,10 +373,10 @@ var require_command_exists = __commonJS({
|
|
|
371
373
|
module.exports = /* @__PURE__ */ __name(function commandExists2(commandName, callback) {
|
|
372
374
|
var cleanedCommandName = cleanInput(commandName);
|
|
373
375
|
if (!callback && typeof Promise !== "undefined") {
|
|
374
|
-
return new Promise(function(
|
|
376
|
+
return new Promise(function(resolve25, reject) {
|
|
375
377
|
commandExists2(commandName, function(error, output) {
|
|
376
378
|
if (output) {
|
|
377
|
-
|
|
379
|
+
resolve25(commandName);
|
|
378
380
|
} else {
|
|
379
381
|
reject(error);
|
|
380
382
|
}
|
|
@@ -703,6 +705,7 @@ import { join, resolve } from "node:path";
|
|
|
703
705
|
var REVIEW_TMP_DIR = join(".qwen", "tmp");
|
|
704
706
|
var REVIEWS_DIR = join(".qwen", "reviews");
|
|
705
707
|
var REVIEW_CACHE_DIR = join(".qwen", "review-cache");
|
|
708
|
+
var LEASE_PREFIX = "qwen-review-lease-";
|
|
706
709
|
var PARSE_ARGS_REPORT = join(
|
|
707
710
|
REVIEW_TMP_DIR,
|
|
708
711
|
"qwen-review-parse-args.json"
|
|
@@ -738,7 +741,6 @@ function tmpPrefix(target) {
|
|
|
738
741
|
__name(tmpPrefix, "tmpPrefix");
|
|
739
742
|
|
|
740
743
|
// packages/cli/src/services/review-worktree-lease.ts
|
|
741
|
-
var LEASE_PREFIX = "qwen-review-lease-";
|
|
742
744
|
var GIT_TIMEOUT_MS = 12e4;
|
|
743
745
|
var debugLogger = createDebugLogger("REVIEW_WORKTREE_LEASE");
|
|
744
746
|
function gitOptions(timeout) {
|
|
@@ -2258,8 +2260,8 @@ function createBridgeReadinessGate() {
|
|
|
2258
2260
|
current: /* @__PURE__ */ __name(() => pending, "current"),
|
|
2259
2261
|
block: /* @__PURE__ */ __name(() => {
|
|
2260
2262
|
if (pending) return;
|
|
2261
|
-
pending = new Promise((
|
|
2262
|
-
releasePending =
|
|
2263
|
+
pending = new Promise((resolve25) => {
|
|
2264
|
+
releasePending = resolve25;
|
|
2263
2265
|
});
|
|
2264
2266
|
}, "block"),
|
|
2265
2267
|
release: /* @__PURE__ */ __name(() => {
|
|
@@ -2341,7 +2343,7 @@ function createBridgeRecovery(options) {
|
|
|
2341
2343
|
writeStderrLine(
|
|
2342
2344
|
`[Channel] Bridge crashed (${recentCrashCount}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2343
2345
|
);
|
|
2344
|
-
await new Promise((
|
|
2346
|
+
await new Promise((resolve25) => setTimeout(resolve25, RESTART_DELAY_MS));
|
|
2345
2347
|
const bridge = new AcpBridge(bridgeOpts);
|
|
2346
2348
|
setBridge(bridge);
|
|
2347
2349
|
attachDisconnectHandler(bridge);
|
|
@@ -2659,7 +2661,7 @@ var stopCommand = {
|
|
|
2659
2661
|
if (argv["daemon-url"]) {
|
|
2660
2662
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2661
2663
|
try {
|
|
2662
|
-
const sdk = await import("./daemon-
|
|
2664
|
+
const sdk = await import("./daemon-YI5RY62O.js");
|
|
2663
2665
|
const client = new sdk.DaemonClient({
|
|
2664
2666
|
baseUrl: argv["daemon-url"],
|
|
2665
2667
|
...token ? { token } : {}
|
|
@@ -2773,7 +2775,7 @@ function formatChannelStartupFailures(source, fallbackWorkspaceCwd) {
|
|
|
2773
2775
|
} catch {
|
|
2774
2776
|
return [];
|
|
2775
2777
|
}
|
|
2776
|
-
const
|
|
2778
|
+
const lines = [];
|
|
2777
2779
|
for (const raw of limitedFailures) {
|
|
2778
2780
|
try {
|
|
2779
2781
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
@@ -2805,16 +2807,16 @@ function formatChannelStartupFailures(source, fallbackWorkspaceCwd) {
|
|
|
2805
2807
|
"phase=connect",
|
|
2806
2808
|
...code ? [`code=${code}`] : []
|
|
2807
2809
|
];
|
|
2808
|
-
|
|
2810
|
+
lines.push(
|
|
2809
2811
|
`[Channel] Startup failure (${fields.join(", ")}): ${safeMessage}`
|
|
2810
2812
|
);
|
|
2811
2813
|
} catch {
|
|
2812
2814
|
}
|
|
2813
2815
|
}
|
|
2814
2816
|
if (rawTruncated === true || rawFailureCount > MAX_CHANNEL_STARTUP_FAILURES) {
|
|
2815
|
-
|
|
2817
|
+
lines.push("[Channel] Additional startup failures were truncated.");
|
|
2816
2818
|
}
|
|
2817
|
-
return
|
|
2819
|
+
return lines;
|
|
2818
2820
|
}
|
|
2819
2821
|
__name(formatChannelStartupFailures, "formatChannelStartupFailures");
|
|
2820
2822
|
|
|
@@ -2845,7 +2847,7 @@ var statusCommand = {
|
|
|
2845
2847
|
if (argv["daemon-url"]) {
|
|
2846
2848
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2847
2849
|
try {
|
|
2848
|
-
const sdk = await import("./daemon-
|
|
2850
|
+
const sdk = await import("./daemon-YI5RY62O.js");
|
|
2849
2851
|
const client = new sdk.DaemonClient({
|
|
2850
2852
|
baseUrl: argv["daemon-url"],
|
|
2851
2853
|
...token ? { token } : {}
|
|
@@ -2956,7 +2958,7 @@ var reloadCommand = {
|
|
|
2956
2958
|
const token = resolveToken(argv.token);
|
|
2957
2959
|
let sdk;
|
|
2958
2960
|
try {
|
|
2959
|
-
sdk = await import("./daemon-
|
|
2961
|
+
sdk = await import("./daemon-YI5RY62O.js");
|
|
2960
2962
|
} catch (err) {
|
|
2961
2963
|
writeStderrLine(
|
|
2962
2964
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(err)}`
|
|
@@ -3036,7 +3038,7 @@ var setCommand2 = {
|
|
|
3036
3038
|
const selection = names[0] === "all" ? { mode: "all" } : { mode: "names", names };
|
|
3037
3039
|
let sdk;
|
|
3038
3040
|
try {
|
|
3039
|
-
sdk = await import("./daemon-
|
|
3041
|
+
sdk = await import("./daemon-YI5RY62O.js");
|
|
3040
3042
|
} catch (error) {
|
|
3041
3043
|
writeStderrLine(
|
|
3042
3044
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(error)}`
|
|
@@ -3162,7 +3164,7 @@ function createDaemonChannelBridgeFacade(bridge, opts) {
|
|
|
3162
3164
|
}
|
|
3163
3165
|
__name(createDaemonChannelBridgeFacade, "createDaemonChannelBridgeFacade");
|
|
3164
3166
|
async function loadDaemonSdk() {
|
|
3165
|
-
return await import("./daemon-
|
|
3167
|
+
return await import("./daemon-YI5RY62O.js");
|
|
3166
3168
|
}
|
|
3167
3169
|
__name(loadDaemonSdk, "loadDaemonSdk");
|
|
3168
3170
|
function selectedChannelNames(channelsConfig, selection) {
|
|
@@ -3209,12 +3211,12 @@ async function abortableStartup(value, signal) {
|
|
|
3209
3211
|
const promise = Promise.resolve(value);
|
|
3210
3212
|
if (!signal) return await promise;
|
|
3211
3213
|
if (signal.aborted) throw startupAbortError();
|
|
3212
|
-
return await new Promise((
|
|
3214
|
+
return await new Promise((resolve25, reject) => {
|
|
3213
3215
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3214
3216
|
reject(startupAbortError());
|
|
3215
3217
|
}, "onAbort");
|
|
3216
3218
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3217
|
-
promise.then(
|
|
3219
|
+
promise.then(resolve25, reject).finally(() => {
|
|
3218
3220
|
signal.removeEventListener("abort", onAbort);
|
|
3219
3221
|
});
|
|
3220
3222
|
});
|
|
@@ -3623,7 +3625,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3623
3625
|
if (!send) {
|
|
3624
3626
|
return Promise.reject(new Error("Channel worker IPC is unavailable."));
|
|
3625
3627
|
}
|
|
3626
|
-
return new Promise((
|
|
3628
|
+
return new Promise((resolve25, reject) => {
|
|
3627
3629
|
let settled = false;
|
|
3628
3630
|
let unsubscribeMessage = /* @__PURE__ */ __name(() => {
|
|
3629
3631
|
}, "unsubscribeMessage");
|
|
@@ -3637,7 +3639,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3637
3639
|
settled = true;
|
|
3638
3640
|
cleanup();
|
|
3639
3641
|
if (error) reject(error);
|
|
3640
|
-
else
|
|
3642
|
+
else resolve25();
|
|
3641
3643
|
}, "finish");
|
|
3642
3644
|
const onMessage = /* @__PURE__ */ __name((value) => {
|
|
3643
3645
|
if (isChannelStartupReportAckMessage(value)) {
|
|
@@ -3885,8 +3887,8 @@ var daemonWorkerCommand = {
|
|
|
3885
3887
|
let shuttingDown = false;
|
|
3886
3888
|
let exitCode = 0;
|
|
3887
3889
|
let finish;
|
|
3888
|
-
const finished = new Promise((
|
|
3889
|
-
finish =
|
|
3890
|
+
const finished = new Promise((resolve25) => {
|
|
3891
|
+
finish = resolve25;
|
|
3890
3892
|
});
|
|
3891
3893
|
const shutdown = /* @__PURE__ */ __name(async (reason) => {
|
|
3892
3894
|
if (shuttingDown) {
|
|
@@ -3914,8 +3916,8 @@ var daemonWorkerCommand = {
|
|
|
3914
3916
|
...activeChannelDeliveries.values(),
|
|
3915
3917
|
...activeWebhookTasks.values()
|
|
3916
3918
|
]),
|
|
3917
|
-
new Promise((
|
|
3918
|
-
const timer = setTimeout(
|
|
3919
|
+
new Promise((resolve25) => {
|
|
3920
|
+
const timer = setTimeout(resolve25, WORKER_SHUTDOWN_DRAIN_MS);
|
|
3919
3921
|
timer.unref();
|
|
3920
3922
|
})
|
|
3921
3923
|
]);
|
|
@@ -4556,7 +4558,7 @@ import { dirname as dirname4, join as join9 } from "node:path";
|
|
|
4556
4558
|
|
|
4557
4559
|
// packages/cli/src/commands/review/lib/coverage.ts
|
|
4558
4560
|
init_esbuild_shims();
|
|
4559
|
-
import { readFileSync as readFileSync8, statSync as
|
|
4561
|
+
import { readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
4560
4562
|
|
|
4561
4563
|
// packages/cli/src/commands/review/lib/transcripts.ts
|
|
4562
4564
|
init_esbuild_shims();
|
|
@@ -4567,7 +4569,7 @@ var TranscriptsUnavailableError = class extends Error {
|
|
|
4567
4569
|
__name(this, "TranscriptsUnavailableError");
|
|
4568
4570
|
}
|
|
4569
4571
|
};
|
|
4570
|
-
function
|
|
4572
|
+
function transcriptPaths(env = process.env) {
|
|
4571
4573
|
const projectDir = env["QWEN_CODE_PROJECT_DIR"]?.trim();
|
|
4572
4574
|
const sessionId = env["QWEN_CODE_SESSION_ID"]?.trim();
|
|
4573
4575
|
if (!projectDir || !sessionId) {
|
|
@@ -4575,7 +4577,15 @@ function transcriptDir(env = process.env) {
|
|
|
4575
4577
|
"the CLI did not export QWEN_CODE_PROJECT_DIR / QWEN_CODE_SESSION_ID, so this run cannot find the harness's record of what its agents did"
|
|
4576
4578
|
);
|
|
4577
4579
|
}
|
|
4578
|
-
return
|
|
4580
|
+
return {
|
|
4581
|
+
projectDir,
|
|
4582
|
+
sessionId,
|
|
4583
|
+
dir: join5(projectDir, "subagents", sessionId)
|
|
4584
|
+
};
|
|
4585
|
+
}
|
|
4586
|
+
__name(transcriptPaths, "transcriptPaths");
|
|
4587
|
+
function transcriptDir(env = process.env) {
|
|
4588
|
+
return transcriptPaths(env).dir;
|
|
4579
4589
|
}
|
|
4580
4590
|
__name(transcriptDir, "transcriptDir");
|
|
4581
4591
|
function textOf(rec) {
|
|
@@ -4606,8 +4616,8 @@ function parseTranscript(file, diffPath) {
|
|
|
4606
4616
|
} catch {
|
|
4607
4617
|
return null;
|
|
4608
4618
|
}
|
|
4609
|
-
const
|
|
4610
|
-
if (
|
|
4619
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
4620
|
+
if (lines.length === 0) return null;
|
|
4611
4621
|
let agentId = "";
|
|
4612
4622
|
let agentName = "";
|
|
4613
4623
|
let launchPrompt = "";
|
|
@@ -4618,7 +4628,7 @@ function parseTranscript(file, diffPath) {
|
|
|
4618
4628
|
const successfulCallArgs = [];
|
|
4619
4629
|
const byId = /* @__PURE__ */ new Map();
|
|
4620
4630
|
const anonymous = [];
|
|
4621
|
-
for (const line of
|
|
4631
|
+
for (const line of lines) {
|
|
4622
4632
|
let rec;
|
|
4623
4633
|
try {
|
|
4624
4634
|
rec = JSON.parse(line);
|
|
@@ -4692,11 +4702,15 @@ function parseTranscript(file, diffPath) {
|
|
|
4692
4702
|
};
|
|
4693
4703
|
}
|
|
4694
4704
|
__name(parseTranscript, "parseTranscript");
|
|
4705
|
+
function listAgentTranscriptFiles(dir) {
|
|
4706
|
+
return readdirSync2(dir).filter((name) => name.endsWith(".jsonl"));
|
|
4707
|
+
}
|
|
4708
|
+
__name(listAgentTranscriptFiles, "listAgentTranscriptFiles");
|
|
4695
4709
|
function readTranscripts(since, env = process.env, diffPath) {
|
|
4696
4710
|
const dir = transcriptDir(env);
|
|
4697
4711
|
let names;
|
|
4698
4712
|
try {
|
|
4699
|
-
names =
|
|
4713
|
+
names = listAgentTranscriptFiles(dir);
|
|
4700
4714
|
} catch (err) {
|
|
4701
4715
|
throw new TranscriptsUnavailableError(
|
|
4702
4716
|
`no subagent transcripts at ${dir} (${err.message}). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.`
|
|
@@ -4704,7 +4718,6 @@ function readTranscripts(since, env = process.env, diffPath) {
|
|
|
4704
4718
|
}
|
|
4705
4719
|
const out = [];
|
|
4706
4720
|
for (const name of names) {
|
|
4707
|
-
if (!name.endsWith(".jsonl")) continue;
|
|
4708
4721
|
const rec = parseTranscript(join5(dir, name), diffPath);
|
|
4709
4722
|
if (!rec) continue;
|
|
4710
4723
|
if (since !== void 0 && rec.mtimeMs < since) continue;
|
|
@@ -4722,7 +4735,13 @@ __name(wasGivenTheDiff, "wasGivenTheDiff");
|
|
|
4722
4735
|
|
|
4723
4736
|
// packages/cli/src/commands/review/lib/prompt-record.ts
|
|
4724
4737
|
init_esbuild_shims();
|
|
4725
|
-
import {
|
|
4738
|
+
import {
|
|
4739
|
+
mkdirSync as mkdirSync3,
|
|
4740
|
+
readFileSync as readFileSync5,
|
|
4741
|
+
readdirSync as readdirSync3,
|
|
4742
|
+
statSync as statSync2,
|
|
4743
|
+
writeFileSync as writeFileSync3
|
|
4744
|
+
} from "node:fs";
|
|
4726
4745
|
import { dirname as dirname2, join as join6, basename as basename3, resolve as resolve3 } from "node:path";
|
|
4727
4746
|
function promptRecordDir(planPath) {
|
|
4728
4747
|
const p = resolve3(planPath);
|
|
@@ -4764,7 +4783,7 @@ function recordPrompt(planPath, key, prompt) {
|
|
|
4764
4783
|
}
|
|
4765
4784
|
}
|
|
4766
4785
|
__name(recordPrompt, "recordPrompt");
|
|
4767
|
-
function readRecordedPrompts(planPath) {
|
|
4786
|
+
function readRecordedPrompts(planPath, sinceMs) {
|
|
4768
4787
|
const out = /* @__PURE__ */ new Map();
|
|
4769
4788
|
const dir = promptRecordDir(planPath);
|
|
4770
4789
|
let names;
|
|
@@ -4782,7 +4801,9 @@ function readRecordedPrompts(planPath) {
|
|
|
4782
4801
|
} catch {
|
|
4783
4802
|
continue;
|
|
4784
4803
|
}
|
|
4785
|
-
|
|
4804
|
+
const file = join6(dir, name);
|
|
4805
|
+
if (sinceMs !== void 0 && statSync2(file).mtimeMs < sinceMs) continue;
|
|
4806
|
+
out.set(key, readFileSync5(file, "utf8"));
|
|
4786
4807
|
} catch {
|
|
4787
4808
|
}
|
|
4788
4809
|
}
|
|
@@ -4790,25 +4811,33 @@ function readRecordedPrompts(planPath) {
|
|
|
4790
4811
|
}
|
|
4791
4812
|
__name(readRecordedPrompts, "readRecordedPrompts");
|
|
4792
4813
|
function wasDeliveredVerbatim(launchPrompt, built) {
|
|
4814
|
+
return deliveredVerbatim(flattenPrompt(launchPrompt), built);
|
|
4815
|
+
}
|
|
4816
|
+
__name(wasDeliveredVerbatim, "wasDeliveredVerbatim");
|
|
4817
|
+
function deliveredVerbatim(flattenedLaunch, built) {
|
|
4793
4818
|
if (built.trim().length === 0) return false;
|
|
4794
|
-
|
|
4819
|
+
return deliveredVerbatimLines(flattenedLaunch, promptLines(built));
|
|
4820
|
+
}
|
|
4821
|
+
__name(deliveredVerbatim, "deliveredVerbatim");
|
|
4822
|
+
function deliveredVerbatimLines(flattenedLaunch, builtLines) {
|
|
4823
|
+
if (builtLines.length === 0) return false;
|
|
4795
4824
|
let at = 0;
|
|
4796
|
-
for (const line of
|
|
4797
|
-
const i =
|
|
4825
|
+
for (const line of builtLines) {
|
|
4826
|
+
const i = flattenedLaunch.indexOf(line, at);
|
|
4798
4827
|
if (i === -1) return false;
|
|
4799
4828
|
at = i + line.length;
|
|
4800
4829
|
}
|
|
4801
4830
|
return true;
|
|
4802
4831
|
}
|
|
4803
|
-
__name(
|
|
4804
|
-
function
|
|
4832
|
+
__name(deliveredVerbatimLines, "deliveredVerbatimLines");
|
|
4833
|
+
function flattenPrompt(s) {
|
|
4805
4834
|
return s.replace(/\s+/g, " ").trim();
|
|
4806
4835
|
}
|
|
4807
|
-
__name(
|
|
4808
|
-
function
|
|
4809
|
-
return built.split("\n").map((l) =>
|
|
4836
|
+
__name(flattenPrompt, "flattenPrompt");
|
|
4837
|
+
function promptLines(built) {
|
|
4838
|
+
return built.split("\n").map((l) => flattenPrompt(l)).filter((l) => l.length > 0);
|
|
4810
4839
|
}
|
|
4811
|
-
__name(
|
|
4840
|
+
__name(promptLines, "promptLines");
|
|
4812
4841
|
|
|
4813
4842
|
// packages/cli/src/commands/review/lib/roster.ts
|
|
4814
4843
|
init_esbuild_shims();
|
|
@@ -4912,9 +4941,9 @@ function splitHeaderPaths(rest) {
|
|
|
4912
4941
|
}
|
|
4913
4942
|
__name(splitHeaderPaths, "splitHeaderPaths");
|
|
4914
4943
|
function parseDiff(diffText) {
|
|
4915
|
-
const
|
|
4916
|
-
if (
|
|
4917
|
-
const total =
|
|
4944
|
+
const lines = diffText.split("\n");
|
|
4945
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
4946
|
+
const total = lines.length;
|
|
4918
4947
|
const files = [];
|
|
4919
4948
|
let cur = null;
|
|
4920
4949
|
let curHunk = null;
|
|
@@ -4941,7 +4970,7 @@ function parseDiff(diffText) {
|
|
|
4941
4970
|
}
|
|
4942
4971
|
}, "closeFile");
|
|
4943
4972
|
for (let i = 0; i < total; i++) {
|
|
4944
|
-
const line =
|
|
4973
|
+
const line = lines[i];
|
|
4945
4974
|
const n = i + 1;
|
|
4946
4975
|
if (line.startsWith("diff --git ")) {
|
|
4947
4976
|
closeFile(n - 1);
|
|
@@ -5020,9 +5049,9 @@ function parseDiff(diffText) {
|
|
|
5020
5049
|
}
|
|
5021
5050
|
__name(parseDiff, "parseDiff");
|
|
5022
5051
|
var MIN_SPLIT_SEGMENT = 40;
|
|
5023
|
-
function isSafeSplitPoint(
|
|
5024
|
-
const cur =
|
|
5025
|
-
const prev =
|
|
5052
|
+
function isSafeSplitPoint(lines, n) {
|
|
5053
|
+
const cur = lines[n - 1];
|
|
5054
|
+
const prev = lines[n - 2];
|
|
5026
5055
|
if (cur === void 0 || prev === void 0) return false;
|
|
5027
5056
|
const isNewSide = /* @__PURE__ */ __name((l) => l === "" || /^[+ ]/.test(l), "isNewSide");
|
|
5028
5057
|
if (!isNewSide(cur) || !isNewSide(prev)) return false;
|
|
@@ -5032,9 +5061,9 @@ function isSafeSplitPoint(lines2, n) {
|
|
|
5032
5061
|
return prev === "" || /^\s*$/.test(prev.slice(1));
|
|
5033
5062
|
}
|
|
5034
5063
|
__name(isSafeSplitPoint, "isSafeSplitPoint");
|
|
5035
|
-
function charPrefix(
|
|
5036
|
-
const p = new Array(
|
|
5037
|
-
for (let i = 0; i <
|
|
5064
|
+
function charPrefix(lines) {
|
|
5065
|
+
const p = new Array(lines.length + 1).fill(0);
|
|
5066
|
+
for (let i = 0; i < lines.length; i++) p[i + 1] = p[i] + lines[i].length + 1;
|
|
5038
5067
|
return p;
|
|
5039
5068
|
}
|
|
5040
5069
|
__name(charPrefix, "charPrefix");
|
|
@@ -5042,14 +5071,14 @@ function charsIn(prefix, s, e) {
|
|
|
5042
5071
|
return prefix[e] - prefix[s - 1];
|
|
5043
5072
|
}
|
|
5044
5073
|
__name(charsIn, "charsIn");
|
|
5045
|
-
function splitUnit(unit,
|
|
5074
|
+
function splitUnit(unit, lines, prefix, maxChunkLines, bodyStart) {
|
|
5046
5075
|
const over = /* @__PURE__ */ __name((s, e) => e - s + 1 > maxChunkLines || charsIn(prefix, s, e) > MAX_CHUNK_CHARS, "over");
|
|
5047
5076
|
const bigEnough = /* @__PURE__ */ __name((s, e) => e - s + 1 >= MIN_SPLIT_SEGMENT || charsIn(prefix, s, e) >= MAX_CHUNK_CHARS / 2, "bigEnough");
|
|
5048
5077
|
if (!over(unit.start, unit.end)) return [unit];
|
|
5049
5078
|
const newLineOf = /* @__PURE__ */ new Map();
|
|
5050
5079
|
let newLine = unit.newStart;
|
|
5051
5080
|
for (let n = bodyStart; n <= unit.end; n++) {
|
|
5052
|
-
const c =
|
|
5081
|
+
const c = lines[n - 1]?.[0];
|
|
5053
5082
|
if (c === " " || c === "+") newLineOf.set(n, newLine++);
|
|
5054
5083
|
}
|
|
5055
5084
|
const out = [];
|
|
@@ -5058,7 +5087,7 @@ function splitUnit(unit, lines2, prefix, maxChunkLines, bodyStart) {
|
|
|
5058
5087
|
const upper = Math.min(unit.end, segStart + maxChunkLines - 1);
|
|
5059
5088
|
let cut = -1;
|
|
5060
5089
|
for (let n = upper; n > bodyStart; n--) {
|
|
5061
|
-
if (!isSafeSplitPoint(
|
|
5090
|
+
if (!isSafeSplitPoint(lines, n)) continue;
|
|
5062
5091
|
if (over(segStart, n - 1)) continue;
|
|
5063
5092
|
if (!bigEnough(segStart, n - 1)) continue;
|
|
5064
5093
|
cut = n;
|
|
@@ -5066,7 +5095,7 @@ function splitUnit(unit, lines2, prefix, maxChunkLines, bodyStart) {
|
|
|
5066
5095
|
}
|
|
5067
5096
|
if (cut < 0) {
|
|
5068
5097
|
for (let n = upper + 1; n <= unit.end; n++) {
|
|
5069
|
-
if (isSafeSplitPoint(
|
|
5098
|
+
if (isSafeSplitPoint(lines, n) && bigEnough(segStart, n - 1)) {
|
|
5070
5099
|
cut = n;
|
|
5071
5100
|
break;
|
|
5072
5101
|
}
|
|
@@ -5092,10 +5121,10 @@ function splitUnit(unit, lines2, prefix, maxChunkLines, bodyStart) {
|
|
|
5092
5121
|
return out;
|
|
5093
5122
|
}
|
|
5094
5123
|
__name(splitUnit, "splitUnit");
|
|
5095
|
-
function planChunks(files,
|
|
5096
|
-
const diffLines =
|
|
5124
|
+
function planChunks(files, lines, maxChunkLines = DEFAULT_MAX_CHUNK_LINES) {
|
|
5125
|
+
const diffLines = lines.length;
|
|
5097
5126
|
if (diffLines === 0) return [];
|
|
5098
|
-
const prefix = charPrefix(
|
|
5127
|
+
const prefix = charPrefix(lines);
|
|
5099
5128
|
const units = [];
|
|
5100
5129
|
for (const f of files) {
|
|
5101
5130
|
if (f.hunks.length === 0) {
|
|
@@ -5119,7 +5148,7 @@ function planChunks(files, lines2, maxChunkLines = DEFAULT_MAX_CHUNK_LINES) {
|
|
|
5119
5148
|
newEnd: h.newEnd
|
|
5120
5149
|
};
|
|
5121
5150
|
units.push(
|
|
5122
|
-
...splitUnit(unit,
|
|
5151
|
+
...splitUnit(unit, lines, prefix, maxChunkLines, h.diffStart + 1)
|
|
5123
5152
|
);
|
|
5124
5153
|
});
|
|
5125
5154
|
}
|
|
@@ -5131,7 +5160,7 @@ function planChunks(files, lines2, maxChunkLines = DEFAULT_MAX_CHUNK_LINES) {
|
|
|
5131
5160
|
cur.chars = charsIn(prefix, cur.startLine, cur.endLine);
|
|
5132
5161
|
let widest = 0;
|
|
5133
5162
|
for (let n = cur.startLine; n <= cur.endLine; n++) {
|
|
5134
|
-
if (
|
|
5163
|
+
if (lines[n - 1].length > widest) widest = lines[n - 1].length;
|
|
5135
5164
|
}
|
|
5136
5165
|
cur.maxLineChars = widest;
|
|
5137
5166
|
chunks.push(cur);
|
|
@@ -5174,10 +5203,10 @@ function planChunks(files, lines2, maxChunkLines = DEFAULT_MAX_CHUNK_LINES) {
|
|
|
5174
5203
|
__name(planChunks, "planChunks");
|
|
5175
5204
|
function buildDiffPlan(diffText, maxChunkLines = DEFAULT_MAX_CHUNK_LINES) {
|
|
5176
5205
|
const { files, diffLines } = parseDiff(diffText);
|
|
5177
|
-
const
|
|
5178
|
-
if (
|
|
5206
|
+
const lines = diffText.split("\n");
|
|
5207
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
5179
5208
|
const linesOf = /* @__PURE__ */ __name((kind) => files.filter((f) => f.kind === kind).reduce((n, f) => n + (f.diffEnd - f.diffStart + 1), 0), "linesOf");
|
|
5180
|
-
const chunks = planChunks(files,
|
|
5209
|
+
const chunks = planChunks(files, lines, maxChunkLines);
|
|
5181
5210
|
if (!chunksCoverDiff(chunks, diffLines)) {
|
|
5182
5211
|
throw new Error(
|
|
5183
5212
|
`diff-plan: chunks do not tile the diff (${chunks.length} chunks over ${diffLines} lines). Refusing to plan a review with a coverage hole.`
|
|
@@ -5696,6 +5725,7 @@ __name(requiredAgents, "requiredAgents");
|
|
|
5696
5725
|
|
|
5697
5726
|
// packages/cli/src/commands/review/lib/agent-briefs.ts
|
|
5698
5727
|
init_esbuild_shims();
|
|
5728
|
+
var REVERSE_AUDIT_EXAMPLE_RECEIPT = "No issues found \u2014 re-walked the reconnect state machine and the two changed exports' call sites; every gap I checked was already in the list";
|
|
5699
5729
|
var BRIEFS = {
|
|
5700
5730
|
"0": {
|
|
5701
5731
|
label: "Agent 0: Issue fidelity & root-cause ownership",
|
|
@@ -5994,11 +6024,11 @@ You are undirected on purpose. Do not restrict yourself to the list.`
|
|
|
5994
6024
|
readsDiff: false,
|
|
5995
6025
|
brief: `You are **Agent 7: Build & Test Verification**. You do not review the diff \u2014 you run the project's own deterministic checks and report what they say. Your evidence is **the commands you ran and their output**; a return that names no command has not done this job.
|
|
5996
6026
|
|
|
5997
|
-
**Run \`qwen review build-test\` (the exact command, with its \`--plan\` and \`--worktree\`, is below).** It installs if needed, then builds only the workspaces the diff changes plus everything they compile against, and tests the changed ones \u2014 reading the plan for what changed and the root \`package.json\` for the workspace layout. Do **not** substitute \`npm run build\` / \`npm test\` by hand. The old brief did, with a 120-second deadline, and this repo's cold full build is 125 seconds: measured across the harness's own transcripts, that command timed out **71 times** and verified nothing. \`build-test\` scopes the build, gives it a deadline it can meet, and \u2014 this is the part a hand-run command gets wrong \u2014 reports a timeout as **infrastructure, not a finding**. A build that runs out of time is never a Critical against someone's pull request.
|
|
6027
|
+
**Run \`qwen review build-test\` (the exact command, with its \`--plan\` and \`--worktree\`, is below).** It installs if needed, then builds only the workspaces the diff changes plus everything they compile against, and tests the changed ones plus every workspace that depends on them \u2014 reading the plan for what changed and the root \`package.json\` for the workspace layout. Do **not** substitute \`npm run build\` / \`npm test\` by hand. The old brief did, with a 120-second deadline, and this repo's cold full build is 125 seconds: measured across the harness's own transcripts, that command timed out **71 times** and verified nothing. \`build-test\` scopes the build, gives it a deadline it can meet, and \u2014 this is the part a hand-run command gets wrong \u2014 reports a timeout as **infrastructure, not a finding**. A build that runs out of time is never a Critical against someone's pull request.
|
|
5998
6028
|
|
|
5999
6029
|
Read the JSON it prints:
|
|
6000
6030
|
|
|
6001
|
-
- \`toolchain: "npm"\` \u2192 use its \`build[]\` / \`test[]\` results. A failure in a file **the diff changed** is a **Critical** (\`Source: [build]\` or \`[test]\`); a failure in a file it did **not** touch is pre-existing \u2014 say so, do not file it against this PR. A non-empty \`timedOut\`, or a failed \`install\`, is environment/infrastructure \u2014 informational, never a Critical. On \`ok: true\`, name the workspaces built and the commands run; a return that names no command is a whiff.
|
|
6031
|
+
- \`toolchain: "npm"\` \u2192 use its \`build[]\` / \`test[]\` results. A failure in a file **the diff changed** is a **Critical** (\`Source: [build]\` or \`[test]\`); a failure in a file it did **not** touch is pre-existing \u2014 say so, do not file it against this PR. A non-empty \`timedOut\`, or a failed \`install\`, is environment/infrastructure \u2014 informational, never a Critical. On \`ok: true\`, name the workspaces built and the commands run; a return that names no command is a whiff. Report the TEST coverage from \`testScope\`, never from assumption. \`testScope.workspaces\` lists exactly the suites that ran \u2014 say "tests scoped to <list> \u2014 the changed workspaces and their declared dependents that define a test script". \`testScope.notRun\`, when present, names suites the whole-call budget stopped before they ran \u2014 say they did not run, never fold them into the coverage. When \`testScope.caveat\` is present, the scope may be incomplete \u2014 quote the caveat and say exactly that. A green run is a claim about those suites only \u2014 do not phrase it as the whole suite passing.
|
|
6002
6032
|
- **When any \`test[]\` command failed (exit non-zero, not a timeout), MEASURE which failures are the PR's before ruling by path.** The path rule above misclassifies in both directions \u2014 an environment-flaky test in a touched file gets filed as a Critical it did not cause, and a PR that breaks a test in an UNTOUCHED file gets waved through as pre-existing. The measurement is two commands: \`qwen review base-tree --plan <plan> --worktree <worktree> --out <plan dir>/qwen-review-pr-<n>-base-tree.json\` (builds the merge base beside the worktree). **Read \`available\` before using \`path\`** \u2014 a tree that was created but did NOT build populates \`path\` too, and a base that failed to build says nothing whatsoever about the PR, so measuring against it turns an infrastructure failure into a list of Criticals. \`available: false\` (local/lightweight review, no merge base, a base that would not compile) means the path rule stands \u2014 say so and stop here, and \`qwen review test-delta --report <the build-test report you wrote> --baseline <the base-tree report's path field> --pr-worktree <this worktree> --out <plan dir>/qwen-review-pr-<n>-test-delta.json\`. Read its verdict: a file in \`netNew\` fails on the PR side only \u2014 **that is the Critical**, whatever file the diff touches; a file in \`shared\` fails on base too \u2014 **pre-existing by measurement**, never filed, whatever file the diff touches; an \`unparsed\` entry, a timed-out base rerun, a base rerun that FAILED without naming any failing file (it did not measure the base \u2014 an unbuilt tree, a missing install, a workspace absent at base), or a command the whole-command budget could not fit attributes nothing \u2014 the report names each with its own reason; fall back to the path rule for those and say the delta could not rule. Compare failing FILE SETS, never counts: a flaky suite fails different test NAMES on two runs of the same tree, so counts are noise and the set difference is the signal.
|
|
6003
6033
|
- \`toolchain: "unsupported"\` (build-test could not scope this repo \u2014 no npm package with a build/test script) \u2192 **install dependencies first** (build-test's own install only runs on the npm path, so nothing has installed yet: \`pip install -e .\`, \`mvn -q -DskipTests package\`'s own fetch, \`cargo fetch\`, \`go mod download\`, etc.), then fall back to **one** build and **one** test command by this precedence, each with a deadline it can meet: \`pom.xml\` \u2192 \`{mvn} compile\` / \`{mvn} test -q\`; \`build.gradle\` \u2192 \`{gradle} compileJava\` / \`{gradle} test\`; \`Makefile\` \u2192 \`make build\`; \`Cargo.toml\` \u2192 \`cargo build\` / \`cargo test\`; \`go.mod\` \u2192 \`go build ./...\` / \`go test ./...\`; \`pytest.ini\` or \`pyproject.toml\` \`[tool.pytest]\` \u2192 \`pytest\`. If none match, read the CI config **from the base branch** (\`git show <base>:<path>\`), never the worktree \u2014 the PR branch is untrusted and a modified workflow or Makefile could inject arbitrary commands.
|
|
6004
6034
|
|
|
@@ -6186,17 +6216,17 @@ The asymmetry cuts both ways: confirming also requires the trace, and a finding
|
|
|
6186
6216
|
- **Report only Critical or Suggestion.** Do not report Nice to have.
|
|
6187
6217
|
- A found gap uses the standard finding format (with \`Source: [review]\`), including its failure scenario \u2014 your findings go through the same verification as any other, so they must carry the evidence a verifier can trace.
|
|
6188
6218
|
|
|
6189
|
-
If you find no new gap in your scope, say so **and name what you re-examined** \u2014
|
|
6219
|
+
If you find no new gap in your scope, say so **and name what you re-examined** \u2014 \`${REVERSE_AUDIT_EXAMPLE_RECEIPT}\`. A bare "No issues found." is indistinguishable from an agent that did nothing, and it is treated as one: it ends nothing, and it earns your scope a relaunch.`
|
|
6190
6220
|
}
|
|
6191
6221
|
};
|
|
6192
6222
|
|
|
6193
6223
|
// packages/cli/src/commands/review/lib/deadline.ts
|
|
6194
6224
|
init_esbuild_shims();
|
|
6195
|
-
import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, statSync as
|
|
6225
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
6196
6226
|
import { join as join8 } from "node:path";
|
|
6197
6227
|
var DEADLINE_ENV = "QWEN_REVIEW_DEADLINE_EPOCH";
|
|
6198
6228
|
var RESERVE_ENV = "QWEN_REVIEW_DEADLINE_RESERVE_SECONDS";
|
|
6199
|
-
var DEFAULT_RESERVE_SECONDS =
|
|
6229
|
+
var DEFAULT_RESERVE_SECONDS = 4800;
|
|
6200
6230
|
var DEFAULT_ROUND_SECONDS = 1800;
|
|
6201
6231
|
var MIN_OBSERVED_ROUND_SECONDS = 600;
|
|
6202
6232
|
var STAMPS_FILE = "budget-rounds.json";
|
|
@@ -6204,7 +6234,7 @@ var STOP_FILE = "budget-stop.json";
|
|
|
6204
6234
|
var RUN_EPOCH_SLACK_MS = 2e3;
|
|
6205
6235
|
function runEpochMs(planPath) {
|
|
6206
6236
|
try {
|
|
6207
|
-
return
|
|
6237
|
+
return statSync3(planPath).mtimeMs - RUN_EPOCH_SLACK_MS;
|
|
6208
6238
|
} catch {
|
|
6209
6239
|
return Number.NEGATIVE_INFINITY;
|
|
6210
6240
|
}
|
|
@@ -6240,14 +6270,19 @@ function stampRound(planPath, round, nowMs = Date.now()) {
|
|
|
6240
6270
|
}
|
|
6241
6271
|
__name(stampRound, "stampRound");
|
|
6242
6272
|
function expectedRoundSeconds(planPath, round, nowMs = Date.now()) {
|
|
6243
|
-
const stamps = readRoundStamps(planPath)
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6273
|
+
const stamps = readRoundStamps(planPath).filter(
|
|
6274
|
+
(s) => round === void 0 || s.round !== round
|
|
6275
|
+
);
|
|
6276
|
+
if (stamps.length === 0) return DEFAULT_ROUND_SECONDS;
|
|
6277
|
+
let maxSeconds = 0;
|
|
6278
|
+
for (let i = 0; i < stamps.length; i++) {
|
|
6279
|
+
const end = i + 1 < stamps.length ? stamps[i + 1].atMs : nowMs;
|
|
6280
|
+
maxSeconds = Math.max(
|
|
6281
|
+
maxSeconds,
|
|
6282
|
+
Math.round((end - stamps[i].atMs) / 1e3)
|
|
6283
|
+
);
|
|
6249
6284
|
}
|
|
6250
|
-
return
|
|
6285
|
+
return Math.max(MIN_OBSERVED_ROUND_SECONDS, maxSeconds);
|
|
6251
6286
|
}
|
|
6252
6287
|
__name(expectedRoundSeconds, "expectedRoundSeconds");
|
|
6253
6288
|
function reverseAuditBudgetExhausted(env, roundCostSeconds, nowMs = Date.now()) {
|
|
@@ -6354,7 +6389,7 @@ function readPlan(path3) {
|
|
|
6354
6389
|
if (problem) {
|
|
6355
6390
|
throw new Error(`coverage: ${path3} has ${problem}`);
|
|
6356
6391
|
}
|
|
6357
|
-
return { plan, mtimeMs:
|
|
6392
|
+
return { plan, mtimeMs: statSync4(path3).mtimeMs };
|
|
6358
6393
|
}
|
|
6359
6394
|
__name(readPlan, "readPlan");
|
|
6360
6395
|
var CHUNK_RE = /\bchunk\s+(\d+)\s+of\s+\d+\b/i;
|
|
@@ -7146,6 +7181,7 @@ __name(footerVersion, "footerVersion");
|
|
|
7146
7181
|
|
|
7147
7182
|
// packages/cli/src/commands/review/compose-review.ts
|
|
7148
7183
|
var LOW_SIGNAL_SRC_DIFF_LINES = 100;
|
|
7184
|
+
var UNVERIFIED_FINDING_TAG_RE = /—\s*\[unverified\]/gi;
|
|
7149
7185
|
function withMarker(line) {
|
|
7150
7186
|
return line.startsWith(CRITICAL_PREFIX) ? line : `${CRITICAL_PREFIX} ${line}`;
|
|
7151
7187
|
}
|
|
@@ -7393,6 +7429,33 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7393
7429
|
criticalsUnverified = criticalsNeedingVerify >= 1;
|
|
7394
7430
|
}
|
|
7395
7431
|
}
|
|
7432
|
+
let findingsUnverifiedAtCompose = false;
|
|
7433
|
+
let findingsFileUnreadable = false;
|
|
7434
|
+
let unverifiedTagCount = 0;
|
|
7435
|
+
const findingsPath = input.findingsPath;
|
|
7436
|
+
if (findingsPath !== void 0 && findingsPath !== null) {
|
|
7437
|
+
if (typeof findingsPath !== "string" || findingsPath.trim() === "") {
|
|
7438
|
+
throw new TypeError(
|
|
7439
|
+
`compose-review: findingsPath must be a non-empty string, got ${JSON.stringify(findingsPath)}`
|
|
7440
|
+
);
|
|
7441
|
+
}
|
|
7442
|
+
try {
|
|
7443
|
+
const findingsContent = readFileSync9(findingsPath, "utf8");
|
|
7444
|
+
unverifiedTagCount = (findingsContent.match(UNVERIFIED_FINDING_TAG_RE) ?? []).length;
|
|
7445
|
+
findingsUnverifiedAtCompose = unverifiedTagCount > 0;
|
|
7446
|
+
if (findingsUnverifiedAtCompose) {
|
|
7447
|
+
remediation.push(
|
|
7448
|
+
"findings still tagged `\u2014 [unverified]`: relaunch the verifier for each tagged entry (Step 4, `--role verify` with that entry), apply its verdict in the cumulative findings file, and run compose-review again with the updated file"
|
|
7449
|
+
);
|
|
7450
|
+
}
|
|
7451
|
+
} catch {
|
|
7452
|
+
findingsFileUnreadable = true;
|
|
7453
|
+
findingsUnverifiedAtCompose = true;
|
|
7454
|
+
remediation.push(
|
|
7455
|
+
"findings file not readable: pass the cumulative reverse-audit findings file \u2014 the one every round's `--findings` received \u2014 as `findingsPath` in the state JSON, and run compose-review again"
|
|
7456
|
+
);
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7396
7459
|
const contextUnavailable = toBool(
|
|
7397
7460
|
input.contextUnavailable,
|
|
7398
7461
|
"contextUnavailable"
|
|
@@ -7439,10 +7502,13 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7439
7502
|
}
|
|
7440
7503
|
if (contextUnavailable) cappedBy.push("context-unavailable");
|
|
7441
7504
|
if (criticalsUnverified) cappedBy.push("criticals-unverified");
|
|
7505
|
+
if (findingsUnverifiedAtCompose) {
|
|
7506
|
+
cappedBy.push("findings-unverified-at-compose");
|
|
7507
|
+
}
|
|
7442
7508
|
let event2 = baseEvent;
|
|
7443
7509
|
if (event2 === "APPROVE" && cappedBy.length > 0) event2 = "COMMENT";
|
|
7444
7510
|
const deterministicBodyCriticals = bodyCriticals.length - nonDeterministicBodyCriticals;
|
|
7445
|
-
if (event2 === "REQUEST_CHANGES" && criticalsUnverified && deterministicBodyCriticals === 0) {
|
|
7511
|
+
if (event2 === "REQUEST_CHANGES" && (criticalsUnverified || findingsUnverifiedAtCompose && criticalsNeedingVerify >= 1) && deterministicBodyCriticals === 0) {
|
|
7446
7512
|
event2 = "COMMENT";
|
|
7447
7513
|
}
|
|
7448
7514
|
let downgraded = false;
|
|
@@ -7608,11 +7674,23 @@ ${footer}`;
|
|
|
7608
7674
|
zh: `Test Plan\uFF08\u975E\u963B\u65AD\uFF09\uFF1A${testPlanNotes.join("; ")}\u3002`
|
|
7609
7675
|
}
|
|
7610
7676
|
] : [];
|
|
7677
|
+
const unverifiedTagsBlock = !findingsUnverifiedAtCompose ? [] : findingsFileUnreadable ? [
|
|
7678
|
+
{
|
|
7679
|
+
en: "\u26A0\uFE0F The reverse-audit findings file could not be read at compose time, so this run cannot show its findings were verified.",
|
|
7680
|
+
zh: "\u26A0\uFE0F \u7EC4\u5408\u8BC4\u5BA1\u65F6\u65E0\u6CD5\u8BFB\u53D6\u53CD\u5411\u5BA1\u8BA1\u53D1\u73B0\u6587\u4EF6\uFF0C\u672C\u6B21\u8FD0\u884C\u65E0\u6CD5\u8BC1\u660E\u5176\u53D1\u73B0\u5DF2\u7ECF\u8FC7\u9A8C\u8BC1\u3002"
|
|
7681
|
+
}
|
|
7682
|
+
] : [
|
|
7683
|
+
{
|
|
7684
|
+
en: `\u26A0\uFE0F ${unverifiedTagCount} finding(s) still carried the \`\u2014 [unverified]\` tag when the loop ended \u2014 the verifier never ruled on them, and they are not confirmed.`,
|
|
7685
|
+
zh: `\u26A0\uFE0F \u5FAA\u73AF\u7ED3\u675F\u65F6\u4ECD\u6709 ${unverifiedTagCount} \u6761\u53D1\u73B0\u5E26\u7740 \`\u2014 [unverified]\` \u6807\u8BB0\u2014\u2014\u9A8C\u8BC1\u8005\u4ECE\u672A\u5BF9\u5B83\u4EEC\u4F5C\u51FA\u88C1\u51B3\uFF0C\u5B83\u4EEC\u4E0D\u7B97\u5DF2\u786E\u8BA4\u3002`
|
|
7686
|
+
}
|
|
7687
|
+
];
|
|
7611
7688
|
if (event2 === "REQUEST_CHANGES") {
|
|
7612
7689
|
const parts = [
|
|
7613
7690
|
...contextUnavailable ? [contextUnavailableClause] : [],
|
|
7614
7691
|
...cannotTellBlock,
|
|
7615
7692
|
...notReviewedParts,
|
|
7693
|
+
...unverifiedTagsBlock,
|
|
7616
7694
|
...deferredBlock,
|
|
7617
7695
|
...testPlanBlock,
|
|
7618
7696
|
...bodyCriticalBlock
|
|
@@ -7661,8 +7739,9 @@ ${footer}`;
|
|
|
7661
7739
|
} else {
|
|
7662
7740
|
const canCertify = !downgraded && !downgradeApprove && !downgradeRequestChanges && c === 0 && cannotTell.length === 0 && uncoverable.length === 0 && unreviewed.length + coverageEntries.length === 0 && // A missing receipt caps the event but was left out of certification, so a
|
|
7663
7741
|
// body could open "Reviewed — no blockers." two lines above "nobody read
|
|
7664
|
-
// them." Nothing nobody read can be certified blocker-free
|
|
7665
|
-
|
|
7742
|
+
// them." Nothing nobody read can be certified blocker-free — and neither
|
|
7743
|
+
// can a loop that ended with findings no verifier ever ruled on.
|
|
7744
|
+
missingReceipts.length === 0 && !findingsUnverifiedAtCompose;
|
|
7666
7745
|
const disclosedChunkIds = /* @__PURE__ */ new Set();
|
|
7667
7746
|
for (const e of coverageEntries) {
|
|
7668
7747
|
const m = /^chunk (\d+)$/.exec(e.subject);
|
|
@@ -7687,6 +7766,7 @@ ${footer}`;
|
|
|
7687
7766
|
}
|
|
7688
7767
|
clauses.push(...cannotTellBlock);
|
|
7689
7768
|
clauses.push(...notReviewedParts);
|
|
7769
|
+
clauses.push(...unverifiedTagsBlock);
|
|
7690
7770
|
clauses.push(...deferredBlock);
|
|
7691
7771
|
clauses.push(...testPlanBlock);
|
|
7692
7772
|
if (downgradedFrom === "Request changes" || criticalsUnverified) {
|
|
@@ -8049,11 +8129,12 @@ function verdictLine(r) {
|
|
|
8049
8129
|
"chunk-nobody-read": "part of the diff was never read",
|
|
8050
8130
|
"uncoverable-chunk": "part of the diff cannot be read at all",
|
|
8051
8131
|
"unreviewed-dimension": "a dimension nobody reviewed",
|
|
8052
|
-
"context-unavailable": "the PR's existing discussion could not be read"
|
|
8132
|
+
"context-unavailable": "the PR's existing discussion could not be read",
|
|
8133
|
+
"findings-unverified-at-compose": "findings were still unverified when the loop ended"
|
|
8053
8134
|
};
|
|
8054
8135
|
let line = `Verdict: ${label2[r.event]}`;
|
|
8055
|
-
if (r.baseEvent === "REQUEST_CHANGES" && r.event === "COMMENT" && r.cappedBy.includes("criticals-unverified")) {
|
|
8056
|
-
line += " \u2014 a Request changes was NOT available: its blockers were never verified (they are posted, disclosed as unverified)";
|
|
8136
|
+
if (r.baseEvent === "REQUEST_CHANGES" && r.event === "COMMENT" && (r.cappedBy.includes("criticals-unverified") || r.cappedBy.includes("findings-unverified-at-compose"))) {
|
|
8137
|
+
line += " \u2014 a Request changes was NOT available: " + (r.cappedBy.includes("criticals-unverified") ? "its blockers were never verified (they are posted, disclosed as unverified)" : "findings were still unverified when the loop ended (they are posted, disclosed)");
|
|
8057
8138
|
} else if (r.baseEvent === "APPROVE" && r.event !== "APPROVE") {
|
|
8058
8139
|
const reasons = r.cappedBy.map((c) => why[c] ?? c);
|
|
8059
8140
|
if (r.downgraded) reasons.push("a presubmit check failed");
|
|
@@ -8682,7 +8763,7 @@ __name(planEffortField, "planEffortField");
|
|
|
8682
8763
|
|
|
8683
8764
|
// packages/cli/src/commands/review/lib/report.ts
|
|
8684
8765
|
init_esbuild_shims();
|
|
8685
|
-
import { statSync as
|
|
8766
|
+
import { statSync as statSync5 } from "node:fs";
|
|
8686
8767
|
|
|
8687
8768
|
// packages/cli/src/commands/review/lib/heavy.ts
|
|
8688
8769
|
init_esbuild_shims();
|
|
@@ -8785,7 +8866,7 @@ __name(buildPlanReport, "buildPlanReport");
|
|
|
8785
8866
|
function warnOnReportSize(path3, cap) {
|
|
8786
8867
|
let size = 0;
|
|
8787
8868
|
try {
|
|
8788
|
-
size =
|
|
8869
|
+
size = statSync5(path3).size;
|
|
8789
8870
|
} catch {
|
|
8790
8871
|
return;
|
|
8791
8872
|
}
|
|
@@ -9141,7 +9222,7 @@ import { dirname as dirname7, resolve as resolve8 } from "node:path";
|
|
|
9141
9222
|
|
|
9142
9223
|
// packages/cli/src/commands/review/lib/local-diff.ts
|
|
9143
9224
|
init_esbuild_shims();
|
|
9144
|
-
import { lstatSync as lstatSync2, statSync as
|
|
9225
|
+
import { lstatSync as lstatSync2, statSync as statSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
9145
9226
|
import { join as join10, relative as relative2, resolve as resolve7, isAbsolute as isAbsolute2, sep as sep2 } from "node:path";
|
|
9146
9227
|
var MAX_UNTRACKED_BYTES = 1e6;
|
|
9147
9228
|
var MAX_UNTRACKED_FILES = 500;
|
|
@@ -9163,7 +9244,7 @@ function describeUndiffable(abs, st) {
|
|
|
9163
9244
|
}
|
|
9164
9245
|
if (st.isSymbolicLink()) {
|
|
9165
9246
|
try {
|
|
9166
|
-
return
|
|
9247
|
+
return statSync6(abs).isDirectory() ? "is a symlink to a directory \u2014 git cannot diff it as a file" : null;
|
|
9167
9248
|
} catch {
|
|
9168
9249
|
return null;
|
|
9169
9250
|
}
|
|
@@ -9709,9 +9790,9 @@ function blockerSection(roots, issueBlockers, repliesByRoot, ctx) {
|
|
|
9709
9790
|
""
|
|
9710
9791
|
];
|
|
9711
9792
|
let spent = out.join("\n").length;
|
|
9712
|
-
const charge = /* @__PURE__ */ __name((
|
|
9713
|
-
spent +=
|
|
9714
|
-
return
|
|
9793
|
+
const charge = /* @__PURE__ */ __name((lines) => {
|
|
9794
|
+
spent += lines.join("\n").length;
|
|
9795
|
+
return lines;
|
|
9715
9796
|
}, "charge");
|
|
9716
9797
|
const refsLine = /* @__PURE__ */ __name((body) => {
|
|
9717
9798
|
const refs = extractCodeRefs(body);
|
|
@@ -10371,11 +10452,11 @@ function showFile(baseRef, path3) {
|
|
|
10371
10452
|
}
|
|
10372
10453
|
__name(showFile, "showFile");
|
|
10373
10454
|
function extractCodeReviewSection(content) {
|
|
10374
|
-
const
|
|
10455
|
+
const lines = content.split("\n");
|
|
10375
10456
|
let start = -1;
|
|
10376
|
-
let end =
|
|
10377
|
-
for (let i = 0; i <
|
|
10378
|
-
const line =
|
|
10457
|
+
let end = lines.length;
|
|
10458
|
+
for (let i = 0; i < lines.length; i++) {
|
|
10459
|
+
const line = lines[i];
|
|
10379
10460
|
if (start < 0) {
|
|
10380
10461
|
if (/^## Code Review\s*$/i.test(line)) start = i;
|
|
10381
10462
|
} else if (/^## /.test(line)) {
|
|
@@ -10384,7 +10465,7 @@ function extractCodeReviewSection(content) {
|
|
|
10384
10465
|
}
|
|
10385
10466
|
}
|
|
10386
10467
|
if (start < 0) return null;
|
|
10387
|
-
return
|
|
10468
|
+
return lines.slice(start, end).join("\n").trim();
|
|
10388
10469
|
}
|
|
10389
10470
|
__name(extractCodeReviewSection, "extractCodeReviewSection");
|
|
10390
10471
|
function loadCombined(baseRef) {
|
|
@@ -10855,7 +10936,7 @@ var presubmitCommand = {
|
|
|
10855
10936
|
// packages/cli/src/commands/review/publish-assets.ts
|
|
10856
10937
|
init_esbuild_shims();
|
|
10857
10938
|
import { createHash as createHash2 } from "node:crypto";
|
|
10858
|
-
import { readFileSync as readFileSync16, statSync as
|
|
10939
|
+
import { readFileSync as readFileSync16, statSync as statSync7, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "node:fs";
|
|
10859
10940
|
import { basename as basename5, dirname as dirname11, resolve as resolve10 } from "node:path";
|
|
10860
10941
|
|
|
10861
10942
|
// packages/cli/src/commands/review/lib/authorization.ts
|
|
@@ -11038,7 +11119,64 @@ __name(reviewWriteAuthorization, "reviewWriteAuthorization");
|
|
|
11038
11119
|
|
|
11039
11120
|
// packages/cli/src/commands/review/lib/assets.ts
|
|
11040
11121
|
init_esbuild_shims();
|
|
11041
|
-
var
|
|
11122
|
+
var EXTENSION_FORMAT = {
|
|
11123
|
+
png: "png",
|
|
11124
|
+
jpg: "jpeg",
|
|
11125
|
+
jpeg: "jpeg",
|
|
11126
|
+
gif: "gif",
|
|
11127
|
+
webp: "webp"
|
|
11128
|
+
};
|
|
11129
|
+
var ASSET_EXTENSIONS = new Set(Object.keys(EXTENSION_FORMAT));
|
|
11130
|
+
function claimedExtension(basename6) {
|
|
11131
|
+
return basename6.includes(".") ? basename6.slice(basename6.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
11132
|
+
}
|
|
11133
|
+
__name(claimedExtension, "claimedExtension");
|
|
11134
|
+
var ASSET_HEADER_BYTES = 16;
|
|
11135
|
+
function sniffImageFormat(header) {
|
|
11136
|
+
const at = /* @__PURE__ */ __name((i) => header[i] ?? -1, "at");
|
|
11137
|
+
const ascii = /* @__PURE__ */ __name((i, s) => [...s].every((ch, k) => at(i + k) === ch.charCodeAt(0)), "ascii");
|
|
11138
|
+
if (at(0) === 137 && ascii(1, "PNG") && at(4) === 13 && at(5) === 10 && at(6) === 26 && at(7) === 10) {
|
|
11139
|
+
return "png";
|
|
11140
|
+
}
|
|
11141
|
+
if (at(0) === 255 && at(1) === 216 && at(2) === 255) {
|
|
11142
|
+
return "jpeg";
|
|
11143
|
+
}
|
|
11144
|
+
if (ascii(0, "GIF87a") || ascii(0, "GIF89a")) {
|
|
11145
|
+
return "gif";
|
|
11146
|
+
}
|
|
11147
|
+
if (ascii(0, "RIFF") && ascii(8, "WEBP") && // The container claim is not the image: a RIFF box carrying WEBP at
|
|
11148
|
+
// offset 8 could still hold anything. Every spec-conformant WebP's
|
|
11149
|
+
// first chunk is VP8, VP8L or VP8X at byte 12, and the 16-byte read
|
|
11150
|
+
// this gate sniffs always covers it.
|
|
11151
|
+
(ascii(12, "VP8 ") || ascii(12, "VP8L") || ascii(12, "VP8X"))) {
|
|
11152
|
+
return "webp";
|
|
11153
|
+
}
|
|
11154
|
+
return null;
|
|
11155
|
+
}
|
|
11156
|
+
__name(sniffImageFormat, "sniffImageFormat");
|
|
11157
|
+
function refusedExtension(basename6, ext) {
|
|
11158
|
+
return {
|
|
11159
|
+
ok: false,
|
|
11160
|
+
reason: `${basename6}: extension ${JSON.stringify(ext)} is not an allowed evidence image type (${[...ASSET_EXTENSIONS].join(", ")})`
|
|
11161
|
+
};
|
|
11162
|
+
}
|
|
11163
|
+
__name(refusedExtension, "refusedExtension");
|
|
11164
|
+
function validateAssetContent(basename6, header) {
|
|
11165
|
+
const ext = claimedExtension(basename6);
|
|
11166
|
+
const claimed = Object.hasOwn(EXTENSION_FORMAT, ext) ? EXTENSION_FORMAT[ext] : void 0;
|
|
11167
|
+
if (claimed === void 0) {
|
|
11168
|
+
return refusedExtension(basename6, ext);
|
|
11169
|
+
}
|
|
11170
|
+
const actual = sniffImageFormat(header);
|
|
11171
|
+
if (actual !== claimed) {
|
|
11172
|
+
return {
|
|
11173
|
+
ok: false,
|
|
11174
|
+
reason: `content is ${actual ?? "not a recognized image"} but the extension claims ${claimed} \u2014 evidence is admitted by content, not by name`
|
|
11175
|
+
};
|
|
11176
|
+
}
|
|
11177
|
+
return { ok: true };
|
|
11178
|
+
}
|
|
11179
|
+
__name(validateAssetContent, "validateAssetContent");
|
|
11042
11180
|
var MAX_ASSET_BYTES = 10 * 1024 * 1024;
|
|
11043
11181
|
var MAX_TOTAL_ASSET_BYTES = 40 * 1024 * 1024;
|
|
11044
11182
|
function assetsBranch(pr) {
|
|
@@ -11073,12 +11211,9 @@ function parseAssetsRepo(value) {
|
|
|
11073
11211
|
}
|
|
11074
11212
|
__name(parseAssetsRepo, "parseAssetsRepo");
|
|
11075
11213
|
function validateAssetFile(basename6, bytes) {
|
|
11076
|
-
const ext =
|
|
11214
|
+
const ext = claimedExtension(basename6);
|
|
11077
11215
|
if (!ASSET_EXTENSIONS.has(ext)) {
|
|
11078
|
-
return
|
|
11079
|
-
ok: false,
|
|
11080
|
-
reason: `${basename6}: extension ${JSON.stringify(ext)} is not an allowed evidence image type (${[...ASSET_EXTENSIONS].join(", ")})`
|
|
11081
|
-
};
|
|
11216
|
+
return refusedExtension(basename6, ext);
|
|
11082
11217
|
}
|
|
11083
11218
|
if (bytes <= 0) {
|
|
11084
11219
|
return { ok: false, reason: `${basename6}: empty file` };
|
|
@@ -11279,7 +11414,7 @@ function runPublishAssets(args) {
|
|
|
11279
11414
|
for (const file of unique) {
|
|
11280
11415
|
const abs = resolve10(file);
|
|
11281
11416
|
try {
|
|
11282
|
-
const st =
|
|
11417
|
+
const st = statSync7(abs);
|
|
11283
11418
|
if (!st.isFile()) throw new Error("not a regular file");
|
|
11284
11419
|
stats.push({ file, abs, basename: basename5(abs), bytes: st.size });
|
|
11285
11420
|
} catch (err) {
|
|
@@ -11305,6 +11440,14 @@ function runPublishAssets(args) {
|
|
|
11305
11440
|
);
|
|
11306
11441
|
return;
|
|
11307
11442
|
}
|
|
11443
|
+
const contentRuling = validateAssetContent(
|
|
11444
|
+
st.basename,
|
|
11445
|
+
content.subarray(0, ASSET_HEADER_BYTES)
|
|
11446
|
+
);
|
|
11447
|
+
if (!contentRuling.ok) {
|
|
11448
|
+
refuse(`${JSON.stringify(st.file)}: ${contentRuling.reason}`);
|
|
11449
|
+
return;
|
|
11450
|
+
}
|
|
11308
11451
|
const sha256 = createHash2("sha256").update(content).digest("hex");
|
|
11309
11452
|
prepared.push({
|
|
11310
11453
|
file: st.file,
|
|
@@ -11430,13 +11573,13 @@ import { dirname as dirname12, resolve as resolve11 } from "node:path";
|
|
|
11430
11573
|
// packages/cli/src/commands/review/lib/anchors.ts
|
|
11431
11574
|
init_esbuild_shims();
|
|
11432
11575
|
function collectNewSideLines(diffText, file) {
|
|
11433
|
-
const
|
|
11576
|
+
const lines = diffText.split("\n");
|
|
11434
11577
|
const out = [];
|
|
11435
11578
|
for (const hunk of file.hunks) {
|
|
11436
11579
|
if (hunk.newCount === 0) continue;
|
|
11437
11580
|
let newCursor = hunk.newStart;
|
|
11438
11581
|
for (let n = hunk.diffStart + 1; n <= hunk.diffEnd; n++) {
|
|
11439
|
-
const raw =
|
|
11582
|
+
const raw = lines[n - 1];
|
|
11440
11583
|
if (raw === void 0) break;
|
|
11441
11584
|
if (raw.startsWith("+")) {
|
|
11442
11585
|
out.push({ newLine: newCursor, text: raw.slice(1), added: true });
|
|
@@ -11464,20 +11607,20 @@ function normalizeLoose(s) {
|
|
|
11464
11607
|
}
|
|
11465
11608
|
__name(normalizeLoose, "normalizeLoose");
|
|
11466
11609
|
function anchorVariants(anchor) {
|
|
11467
|
-
const
|
|
11468
|
-
while (
|
|
11469
|
-
while (
|
|
11470
|
-
if (
|
|
11471
|
-
const variants = [
|
|
11472
|
-
const meaningful =
|
|
11610
|
+
const lines = anchor.replace(/\r\n/g, "\n").split("\n");
|
|
11611
|
+
while (lines.length > 0 && lines[0].trim() === "") lines.shift();
|
|
11612
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
|
|
11613
|
+
if (lines.length === 0) return [];
|
|
11614
|
+
const variants = [lines];
|
|
11615
|
+
const meaningful = lines.filter((l) => l.trim() !== "");
|
|
11473
11616
|
if (meaningful.length > 0 && meaningful.every((l) => /^\+/.test(l))) {
|
|
11474
|
-
variants.push(
|
|
11617
|
+
variants.push(lines.map((l) => l.startsWith("+") ? l.slice(1) : l));
|
|
11475
11618
|
}
|
|
11476
11619
|
const NO_NEWLINE = /^\$/;
|
|
11477
|
-
const marked =
|
|
11620
|
+
const marked = lines.filter((l) => l !== "" && !NO_NEWLINE.test(l));
|
|
11478
11621
|
if (marked.length > 0 && marked.every((l) => /^[+\- ]/.test(l)) && marked.some((l) => l.startsWith("+"))) {
|
|
11479
11622
|
variants.push(
|
|
11480
|
-
|
|
11623
|
+
lines.filter((l) => !l.startsWith("-") && !NO_NEWLINE.test(l)).map((l) => l.slice(1))
|
|
11481
11624
|
);
|
|
11482
11625
|
}
|
|
11483
11626
|
return variants;
|
|
@@ -11856,6 +11999,170 @@ import { createHash as createHash3 } from "node:crypto";
|
|
|
11856
11999
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
11857
12000
|
import { dirname as dirname14, join as join13, resolve as resolve13 } from "node:path";
|
|
11858
12001
|
|
|
12002
|
+
// packages/cli/src/commands/review/lib/retirement.ts
|
|
12003
|
+
init_esbuild_shims();
|
|
12004
|
+
import { statSync as statSync8 } from "node:fs";
|
|
12005
|
+
var REVERSE_AUDIT_MAX_ROUNDS = 5;
|
|
12006
|
+
var RECORD_KEY_RE = /^reverse-audit--chunk-(\d+)--round-(\d+)--[0-9a-f]+$/;
|
|
12007
|
+
var REVERSE_AUDIT_MARKER = "reverse-audit";
|
|
12008
|
+
function bakedRanges(prompt, diffPath) {
|
|
12009
|
+
const out = [];
|
|
12010
|
+
if (diffPath === void 0) return out;
|
|
12011
|
+
for (const m of prompt.matchAll(
|
|
12012
|
+
/read_file\(\s*file_path="([^"]*)",\s*offset=(\d+),\s*limit=(\d+)/gi
|
|
12013
|
+
)) {
|
|
12014
|
+
if (m[1] !== diffPath) continue;
|
|
12015
|
+
const offset = Number(m[2]);
|
|
12016
|
+
const limit = Number(m[3]);
|
|
12017
|
+
if (limit > 0) out.push([offset + 1, offset + limit]);
|
|
12018
|
+
}
|
|
12019
|
+
return out;
|
|
12020
|
+
}
|
|
12021
|
+
__name(bakedRanges, "bakedRanges");
|
|
12022
|
+
var FILE_LINE_RE = /\*\*File:\*\*\s*([^\n]*)/g;
|
|
12023
|
+
var SEVERITY_LINE_RE = /\*\*Severity:\*\*/;
|
|
12024
|
+
var DRY_RECEIPT_RE = new RegExp(
|
|
12025
|
+
'(?:\\bno (?:new )?(?:issues?|findings?|gaps?)[ \\w()]{0,32}?|\u672A\u53D1\u73B0(?:\u65B0\u7684?)?(?:\u95EE\u9898|\u53D1\u73B0)|\u65E0\u65B0\u7684?(?:\u95EE\u9898|\u53D1\u73B0)|\u6CA1\u6709(?:\u53D1\u73B0)?(?:\u65B0\u7684?)?\u95EE\u9898)\\s*[*_)\\]"\u201D\u2019]*\\s*(?:[\u2014\u2013]+|[:\uFF1A]|--+|-+\\s)\\s*([\\s\\S]*)',
|
|
12026
|
+
"i"
|
|
12027
|
+
);
|
|
12028
|
+
var CJK_RE = /[一-鿿]/g;
|
|
12029
|
+
var EXAMPLE_RECEIPT_CLAUSE = (DRY_RECEIPT_RE.exec(REVERSE_AUDIT_EXAMPLE_RECEIPT)?.[1] ?? "").trim();
|
|
12030
|
+
function substantiveClause(clause) {
|
|
12031
|
+
const c = clause.replace(/\s+/g, " ").trim();
|
|
12032
|
+
if (c.length === 0) return false;
|
|
12033
|
+
if (EXAMPLE_RECEIPT_CLAUSE.length > 0 && c.includes(EXAMPLE_RECEIPT_CLAUSE)) {
|
|
12034
|
+
return false;
|
|
12035
|
+
}
|
|
12036
|
+
if (/`[^`]+`/.test(c)) return true;
|
|
12037
|
+
if (/\w[\w.-]+\/[\w.$-]+\/\w/.test(c)) return true;
|
|
12038
|
+
if (/\w[\w.-]+\/[\w$-]+\.\w+/.test(c)) return true;
|
|
12039
|
+
if ((c.match(CJK_RE) ?? []).length >= 4) return true;
|
|
12040
|
+
return c.length >= 20;
|
|
12041
|
+
}
|
|
12042
|
+
__name(substantiveClause, "substantiveClause");
|
|
12043
|
+
function classifyReturn(rec, territory) {
|
|
12044
|
+
const text = rec.finalText.trim();
|
|
12045
|
+
if (SEVERITY_LINE_RE.test(text)) {
|
|
12046
|
+
for (const m of text.matchAll(FILE_LINE_RE)) {
|
|
12047
|
+
const file = (m[1] ?? "").trim();
|
|
12048
|
+
if (file === "" || /^N\/A\b/i.test(file)) continue;
|
|
12049
|
+
if (rec.launchPrompt.includes(`**File:** ${file}`)) continue;
|
|
12050
|
+
return "yielded";
|
|
12051
|
+
}
|
|
12052
|
+
}
|
|
12053
|
+
const receipt = DRY_RECEIPT_RE.exec(text);
|
|
12054
|
+
if (rec.successfulToolCalls > 0 && rec.diffToolCalls > 0 && openedTheTerritory(rec.diffReads, territory) && receipt !== null && substantiveClause(receipt[1] ?? "")) {
|
|
12055
|
+
return "dry";
|
|
12056
|
+
}
|
|
12057
|
+
return "unknown";
|
|
12058
|
+
}
|
|
12059
|
+
__name(classifyReturn, "classifyReturn");
|
|
12060
|
+
function openedTheTerritory(diffReads, territory) {
|
|
12061
|
+
if (territory.length === 0) return true;
|
|
12062
|
+
return diffReads.some(
|
|
12063
|
+
([s, e]) => territory.some(([ts, te]) => s <= te && ts <= e)
|
|
12064
|
+
);
|
|
12065
|
+
}
|
|
12066
|
+
__name(openedTheTerritory, "openedTheTerritory");
|
|
12067
|
+
function mergeOutcomes(outcomes) {
|
|
12068
|
+
if (outcomes.includes("yielded")) return "yielded";
|
|
12069
|
+
if (outcomes.includes("dry")) return "dry";
|
|
12070
|
+
return "unknown";
|
|
12071
|
+
}
|
|
12072
|
+
__name(mergeOutcomes, "mergeOutcomes");
|
|
12073
|
+
function scheduleReverseAuditRound(planPath, chunkIds, round, env = process.env, diffPath) {
|
|
12074
|
+
if (round < 3) {
|
|
12075
|
+
return {
|
|
12076
|
+
due: [...chunkIds],
|
|
12077
|
+
coldChecks: [],
|
|
12078
|
+
skipped: [],
|
|
12079
|
+
converged: false
|
|
12080
|
+
};
|
|
12081
|
+
}
|
|
12082
|
+
const since = statSync8(planPath).mtimeMs;
|
|
12083
|
+
const transcripts = readTranscripts(since, env, diffPath);
|
|
12084
|
+
const built = readRecordedPrompts(planPath, since);
|
|
12085
|
+
const records = [];
|
|
12086
|
+
for (const [key, prompt] of built) {
|
|
12087
|
+
const m = RECORD_KEY_RE.exec(key);
|
|
12088
|
+
if (!m) continue;
|
|
12089
|
+
const r = Number(m[2]);
|
|
12090
|
+
if (r >= round) continue;
|
|
12091
|
+
records.push({
|
|
12092
|
+
chunkId: Number(m[1]),
|
|
12093
|
+
round: r,
|
|
12094
|
+
// Flattened ONCE per record, beside the once-per-transcript flatten
|
|
12095
|
+
// below: the pairing walk pays neither half per (record, transcript)
|
|
12096
|
+
// pair.
|
|
12097
|
+
lines: promptLines(prompt),
|
|
12098
|
+
territory: bakedRanges(prompt, diffPath)
|
|
12099
|
+
});
|
|
12100
|
+
}
|
|
12101
|
+
const candidates = transcripts.filter((t2) => t2.launchPrompt.includes(REVERSE_AUDIT_MARKER)).map((t2) => ({ transcript: t2, flat: flattenPrompt(t2.launchPrompt) }));
|
|
12102
|
+
const matchesByRecord = records.map(
|
|
12103
|
+
(rec) => candidates.filter((c) => deliveredVerbatimLines(c.flat, rec.lines)).map((c) => c.transcript)
|
|
12104
|
+
);
|
|
12105
|
+
const recordsPerTranscript = /* @__PURE__ */ new Map();
|
|
12106
|
+
for (const matches of matchesByRecord) {
|
|
12107
|
+
for (const t2 of matches) {
|
|
12108
|
+
recordsPerTranscript.set(t2, (recordsPerTranscript.get(t2) ?? 0) + 1);
|
|
12109
|
+
}
|
|
12110
|
+
}
|
|
12111
|
+
const outcomesByRecord = matchesByRecord.map(
|
|
12112
|
+
(matches, i) => matches.filter((t2) => recordsPerTranscript.get(t2) === 1).map((t2) => classifyReturn(t2, records[i].territory))
|
|
12113
|
+
);
|
|
12114
|
+
const history = /* @__PURE__ */ new Map();
|
|
12115
|
+
records.forEach((rec, i) => {
|
|
12116
|
+
let byRound = history.get(rec.chunkId);
|
|
12117
|
+
if (!byRound) {
|
|
12118
|
+
byRound = /* @__PURE__ */ new Map();
|
|
12119
|
+
history.set(rec.chunkId, byRound);
|
|
12120
|
+
}
|
|
12121
|
+
byRound.set(rec.round, [
|
|
12122
|
+
...byRound.get(rec.round) ?? [],
|
|
12123
|
+
...outcomesByRecord[i]
|
|
12124
|
+
]);
|
|
12125
|
+
});
|
|
12126
|
+
const due = [];
|
|
12127
|
+
const coldChecks = [];
|
|
12128
|
+
const skipped = [];
|
|
12129
|
+
for (const chunkId of chunkIds) {
|
|
12130
|
+
const audits = [...history.get(chunkId)?.entries() ?? []].map(([r, outcomes]) => ({ round: r, outcome: mergeOutcomes(outcomes) })).sort((a, b) => a.round - b.round);
|
|
12131
|
+
const lastTwo = audits.slice(-2);
|
|
12132
|
+
const retired = lastTwo.length === 2 && lastTwo.every((a) => a.outcome === "dry");
|
|
12133
|
+
if (!retired) {
|
|
12134
|
+
due.push(chunkId);
|
|
12135
|
+
continue;
|
|
12136
|
+
}
|
|
12137
|
+
if (round % 2 === 0) {
|
|
12138
|
+
due.push(chunkId);
|
|
12139
|
+
coldChecks.push(chunkId);
|
|
12140
|
+
} else {
|
|
12141
|
+
skipped.push({
|
|
12142
|
+
chunkId,
|
|
12143
|
+
dryRounds: [lastTwo[0].round, lastTwo[1].round],
|
|
12144
|
+
// The next even round — this branch only runs on odd rounds, so
|
|
12145
|
+
// that is always round + 1. Whether the cap allows it is the note
|
|
12146
|
+
// composer's question, not the schedule's (see
|
|
12147
|
+
// REVERSE_AUDIT_MAX_ROUNDS).
|
|
12148
|
+
nextColdCheck: round + 1
|
|
12149
|
+
});
|
|
12150
|
+
}
|
|
12151
|
+
}
|
|
12152
|
+
return {
|
|
12153
|
+
due,
|
|
12154
|
+
coldChecks,
|
|
12155
|
+
skipped,
|
|
12156
|
+
// An empty `chunkIds` empties `due` vacuously — nothing was ever under
|
|
12157
|
+
// audit, so nothing has proven itself cold. `runAllChunks` refuses a
|
|
12158
|
+
// chunkless plan long before scheduling, but this function is exported,
|
|
12159
|
+
// and convergence is an exit-5 termination rule: it must not be
|
|
12160
|
+
// reachable from nothing.
|
|
12161
|
+
converged: chunkIds.length > 0 && due.length === 0
|
|
12162
|
+
};
|
|
12163
|
+
}
|
|
12164
|
+
__name(scheduleReverseAuditRound, "scheduleReverseAuditRound");
|
|
12165
|
+
|
|
11859
12166
|
// packages/cli/src/commands/review/lib/path-rules.ts
|
|
11860
12167
|
init_esbuild_shims();
|
|
11861
12168
|
var GITHUB_ACTIONS = {
|
|
@@ -12579,11 +12886,57 @@ function requireAuditableChunks(report) {
|
|
|
12579
12886
|
return chunks;
|
|
12580
12887
|
}
|
|
12581
12888
|
__name(requireAuditableChunks, "requireAuditableChunks");
|
|
12889
|
+
function admitReverseAuditRound(planPath, round) {
|
|
12890
|
+
const spent = reverseAuditBudgetExhausted(
|
|
12891
|
+
process.env,
|
|
12892
|
+
expectedRoundSeconds(planPath, round)
|
|
12893
|
+
);
|
|
12894
|
+
if (spent !== null) {
|
|
12895
|
+
writeBudgetStop(planPath, spent, round);
|
|
12896
|
+
writeStderrLine(reverseAuditBudgetMessage(spent, round));
|
|
12897
|
+
process.exitCode = 4;
|
|
12898
|
+
return false;
|
|
12899
|
+
}
|
|
12900
|
+
return true;
|
|
12901
|
+
}
|
|
12902
|
+
__name(admitReverseAuditRound, "admitReverseAuditRound");
|
|
12903
|
+
function refuseConverged() {
|
|
12904
|
+
writeStderrLine(
|
|
12905
|
+
"CONVERGED: every chunk holds two consecutive substantive dry audits; the reverse audit has converged \u2014 stop the loop and proceed to Step 6. This is a clean convergence, not a gap: no unreviewedDimensions entry is owed."
|
|
12906
|
+
);
|
|
12907
|
+
process.exitCode = 5;
|
|
12908
|
+
}
|
|
12909
|
+
__name(refuseConverged, "refuseConverged");
|
|
12582
12910
|
function runAllChunks(report, planPath, role, findingsContent, rules, round) {
|
|
12583
12911
|
const chunks = requireAuditableChunks(report);
|
|
12912
|
+
let schedule = null;
|
|
12913
|
+
if (role === "reverse-audit" && round !== void 0 && round >= 3) {
|
|
12914
|
+
try {
|
|
12915
|
+
schedule = scheduleReverseAuditRound(
|
|
12916
|
+
planPath,
|
|
12917
|
+
chunks.map((c) => c.id),
|
|
12918
|
+
round,
|
|
12919
|
+
process.env,
|
|
12920
|
+
typeof report.diffPathAbsolute === "string" ? report.diffPathAbsolute : void 0
|
|
12921
|
+
);
|
|
12922
|
+
} catch {
|
|
12923
|
+
schedule = null;
|
|
12924
|
+
}
|
|
12925
|
+
}
|
|
12926
|
+
if (schedule !== null && schedule.converged) {
|
|
12927
|
+
refuseConverged();
|
|
12928
|
+
return;
|
|
12929
|
+
}
|
|
12930
|
+
if (role === "reverse-audit" && !admitReverseAuditRound(planPath, round)) {
|
|
12931
|
+
return;
|
|
12932
|
+
}
|
|
12933
|
+
const dueSet = schedule === null ? null : new Set(schedule.due);
|
|
12934
|
+
const dueChunks = dueSet === null ? chunks : chunks.filter((c) => dueSet.has(c.id));
|
|
12935
|
+
const coldSet = new Set(schedule?.coldChecks ?? []);
|
|
12936
|
+
const skipped = schedule?.skipped ?? [];
|
|
12584
12937
|
const digest = findingsDigest(findingsContent, rules);
|
|
12585
12938
|
const roundPart = round !== void 0 ? `--round-${round}` : "";
|
|
12586
|
-
const blocks =
|
|
12939
|
+
const blocks = dueChunks.map((c, i) => {
|
|
12587
12940
|
const key = `${role}--chunk-${c.id}${roundPart}--${digest}`;
|
|
12588
12941
|
const { prompt } = buildLaunch(
|
|
12589
12942
|
report,
|
|
@@ -12593,17 +12946,29 @@ function runAllChunks(report, planPath, role, findingsContent, rules, round) {
|
|
|
12593
12946
|
);
|
|
12594
12947
|
const printed = foldFindings(role, findingsContent, prompt);
|
|
12595
12948
|
recordPrompt(planPath, key, printed);
|
|
12596
|
-
|
|
12949
|
+
const cold = coldSet.has(c.id) ? " (cold check)" : "";
|
|
12950
|
+
return `\u2500\u2500\u2500\u2500\u2500 auditor ${i + 1} of ${dueChunks.length} \u2014 chunk ${c.id}${cold} \u2500\u2500\u2500\u2500\u2500
|
|
12597
12951
|
|
|
12598
12952
|
` + printed;
|
|
12599
12953
|
});
|
|
12954
|
+
const scope = skipped.length === 0 ? "one per chunk" : `one per chunk still under audit (${skipped.length} retired chunk(s) skipped; the retirement note after the end-of-round line says which \u2014 relay it to the terminal)`;
|
|
12955
|
+
const retirementNote = skipped.length === 0 ? [] : [
|
|
12956
|
+
`retirement: a chunk whose two most recent audits are substantive dry receipts is cold-checked on alternating rounds instead of audited on every one; a cold check that yields returns it to every-round auditing. Skipped this round:
|
|
12957
|
+
` + skipped.map(
|
|
12958
|
+
(s) => `chunk ${s.chunkId} \u2014 retired: dry in rounds ${s.dryRounds[0]} and ${s.dryRounds[1]}, ` + (s.nextColdCheck > REVERSE_AUDIT_MAX_ROUNDS ? `certificate final \u2014 the ${REVERSE_AUDIT_MAX_ROUNDS}-round hard cap leaves the loop no round for a cold check` : `next cold check round ${s.nextColdCheck}`)
|
|
12959
|
+
).join("\n")
|
|
12960
|
+
];
|
|
12600
12961
|
writeStdoutLine(
|
|
12601
12962
|
[
|
|
12602
|
-
`${
|
|
12963
|
+
`${dueChunks.length} auditors required this round \u2014 ${scope}. Launch one agent per block below, passing its block VERBATIM \u2014 copy, do not retype, and NEVER sample this output (no \`| head\`): the text IS the deliverable, and a launch reconstructed from a sample matches no record. Blocks are numbered \`auditor k of ${dueChunks.length}\`, and the output ends with an end-of-round line \u2014 followed by the retirement note, when there is one. If either the numbering or the end-of-round line is missing, the output was truncated in transit; rebuild just the missing chunks with --chunk <id>. Write each Agent call's \`description\` (the task name the user watches) in your output language, translating the separator label \u2014 display only; the prompt stays the block VERBATIM.`,
|
|
12603
12964
|
...blocks,
|
|
12604
|
-
`\u2500\u2500\u2500\u2500\u2500 end of round \u2014 ${
|
|
12965
|
+
`\u2500\u2500\u2500\u2500\u2500 end of round \u2014 ${dueChunks.length} auditors \u2500\u2500\u2500\u2500\u2500`,
|
|
12966
|
+
...retirementNote
|
|
12605
12967
|
].join("\n\n")
|
|
12606
12968
|
);
|
|
12969
|
+
if (role === "reverse-audit") {
|
|
12970
|
+
stampRound(planPath, round);
|
|
12971
|
+
}
|
|
12607
12972
|
}
|
|
12608
12973
|
__name(runAllChunks, "runAllChunks");
|
|
12609
12974
|
function runAgentPrompt(args) {
|
|
@@ -12757,20 +13122,29 @@ function runAgentPrompt(args) {
|
|
|
12757
13122
|
);
|
|
12758
13123
|
}
|
|
12759
13124
|
}
|
|
12760
|
-
if (args.
|
|
12761
|
-
|
|
13125
|
+
if (args.role === "reverse-audit" && !hasChunk && !args.allChunks && !admitReverseAuditRound(args.plan, args.round)) {
|
|
13126
|
+
return;
|
|
12762
13127
|
}
|
|
12763
|
-
if (args.role === "reverse-audit") {
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
13128
|
+
if (args.role === "reverse-audit" && hasChunk && !readRoundStamps(args.plan).some((s) => s.round === (args.round ?? null))) {
|
|
13129
|
+
if (args.round !== void 0) {
|
|
13130
|
+
let schedule = null;
|
|
13131
|
+
try {
|
|
13132
|
+
schedule = scheduleReverseAuditRound(
|
|
13133
|
+
args.plan,
|
|
13134
|
+
(Array.isArray(report.chunks) ? report.chunks : []).map((c) => c?.id).filter((id) => typeof id === "number"),
|
|
13135
|
+
args.round,
|
|
13136
|
+
process.env,
|
|
13137
|
+
typeof report.diffPathAbsolute === "string" ? report.diffPathAbsolute : void 0
|
|
13138
|
+
);
|
|
13139
|
+
} catch {
|
|
13140
|
+
schedule = null;
|
|
13141
|
+
}
|
|
13142
|
+
if (schedule !== null && schedule.converged) {
|
|
13143
|
+
refuseConverged();
|
|
13144
|
+
return;
|
|
13145
|
+
}
|
|
12773
13146
|
}
|
|
13147
|
+
if (!admitReverseAuditRound(args.plan, args.round)) return;
|
|
12774
13148
|
}
|
|
12775
13149
|
if (args.allChunks && args.role && findingsContent !== void 0) {
|
|
12776
13150
|
runAllChunks(
|
|
@@ -12781,9 +13155,6 @@ function runAgentPrompt(args) {
|
|
|
12781
13155
|
rules,
|
|
12782
13156
|
args.round
|
|
12783
13157
|
);
|
|
12784
|
-
if (args.role === "reverse-audit") {
|
|
12785
|
-
stampRound(args.plan, args.round);
|
|
12786
|
-
}
|
|
12787
13158
|
return;
|
|
12788
13159
|
}
|
|
12789
13160
|
let prompt;
|
|
@@ -12821,7 +13192,7 @@ function runAgentPrompt(args) {
|
|
|
12821
13192
|
__name(runAgentPrompt, "runAgentPrompt");
|
|
12822
13193
|
var agentPromptCommand = {
|
|
12823
13194
|
command: "agent-prompt",
|
|
12824
|
-
describe: "Build a review agent's launch prompt from the plan (the diff path, its line ranges and the agent's own brief are welded in, not left to the caller to remember). Exit codes: 0 built; 4 the review time budget refused another reverse-audit round (a termination rule, not an error \u2014 see the BUDGET line on stderr); anything else is a bad call or a broken plan.",
|
|
13195
|
+
describe: "Build a review agent's launch prompt from the plan (the diff path, its line ranges and the agent's own brief are welded in, not left to the caller to remember). Exit codes: 0 built; 4 the review time budget refused another reverse-audit round (a termination rule, not an error \u2014 see the BUDGET line on stderr); 5 the reverse audit CONVERGED \u2014 every chunk holds two consecutive substantive dry audits and none is due a cold check, so stop the loop and proceed to Step 6 (also a termination rule, and a clean one: no disclosure is owed); anything else is a bad call or a broken plan.",
|
|
12825
13196
|
builder: /* @__PURE__ */ __name((yargs) => yargs.option("plan", {
|
|
12826
13197
|
type: "string",
|
|
12827
13198
|
demandOption: true,
|
|
@@ -12832,13 +13203,13 @@ var agentPromptCommand = {
|
|
|
12832
13203
|
describe: "The dimension this agent owns. Builds its WHOLE prompt \u2014 the diff's line ranges, the brief, the finding format, the severity definitions and the project rules. Pass it to the agent verbatim."
|
|
12833
13204
|
}).option("chunk", {
|
|
12834
13205
|
type: "number",
|
|
12835
|
-
describe: "Which chunk id this agent owns (a Step 3B territory agent)"
|
|
13206
|
+
describe: "Which chunk id this agent owns (a Step 3B territory agent). With --role reverse-audit --round N it rebuilds ONE auditor of that round: a round already admitted is repaired without gates; a round never admitted answers to the same convergence and budget gates as --all-chunks."
|
|
12836
13207
|
}).option("file", {
|
|
12837
13208
|
type: "string",
|
|
12838
13209
|
describe: "The heavily-rewritten file an invariant agent owns (--role invariant-a|invariant-b|invariant-c)"
|
|
12839
13210
|
}).option("all-chunks", {
|
|
12840
13211
|
type: "boolean",
|
|
12841
|
-
describe: "With --role reverse-audit --findings: build one block per chunk in one call, labelled and separated (Step 5, 3B). Never sample the output; each block is pasted verbatim to its own agent."
|
|
13212
|
+
describe: "With --role reverse-audit --findings: build one block per chunk in one call, labelled and separated (Step 5, 3B). Never sample the output; each block is pasted verbatim to its own agent. From --round 3 on, a chunk whose two most recent audits were both substantive dry receipts is retired to alternating-round cold checks (the retirement note after the end-of-round line says which); a round where every chunk is retired and none is due exits 5 \u2014 the audit has converged."
|
|
12842
13213
|
}).option("roster", {
|
|
12843
13214
|
type: "boolean",
|
|
12844
13215
|
describe: "Build EVERY prompt the plan requires \u2014 chunk, dimension and invariant agents alike \u2014 in one call, each labelled and separated. The list is the same one check-coverage reads out of the plan."
|
|
@@ -12894,9 +13265,10 @@ __name(isWorkspaceMember, "isWorkspaceMember");
|
|
|
12894
13265
|
function workspaceDirFor(filePath, workspaceGlobs) {
|
|
12895
13266
|
const norm = filePath.replace(/^\.\//, "");
|
|
12896
13267
|
let owner = null;
|
|
13268
|
+
const previous = [];
|
|
12897
13269
|
for (const glob of workspaceGlobs) {
|
|
12898
13270
|
const negated = glob.startsWith("!");
|
|
12899
|
-
const g = glob.replace(/^!/, "").replace(/\/$/, "");
|
|
13271
|
+
const g = glob.replace(/^!/, "").replace(/^\.\//, "").replace(/\/$/, "");
|
|
12900
13272
|
let dir = null;
|
|
12901
13273
|
if (g.endsWith("/*")) {
|
|
12902
13274
|
const base = g.slice(0, -2);
|
|
@@ -12908,14 +13280,27 @@ function workspaceDirFor(filePath, workspaceGlobs) {
|
|
|
12908
13280
|
dir = g;
|
|
12909
13281
|
}
|
|
12910
13282
|
if (dir === null) continue;
|
|
12911
|
-
|
|
13283
|
+
if (!negated) {
|
|
13284
|
+
if (dir !== owner) {
|
|
13285
|
+
previous.push(owner);
|
|
13286
|
+
owner = dir;
|
|
13287
|
+
}
|
|
13288
|
+
} else if (dir === owner) {
|
|
13289
|
+
owner = previous.pop() ?? null;
|
|
13290
|
+
}
|
|
12912
13291
|
}
|
|
12913
13292
|
return owner;
|
|
12914
13293
|
}
|
|
12915
13294
|
__name(workspaceDirFor, "workspaceDirFor");
|
|
13295
|
+
function isNegationExcluded(filePath, workspaceGlobs) {
|
|
13296
|
+
if (workspaceDirFor(filePath, workspaceGlobs) !== null) return false;
|
|
13297
|
+
const positives = workspaceGlobs.filter((g) => !g.startsWith("!"));
|
|
13298
|
+
return workspaceDirFor(filePath, positives) !== null;
|
|
13299
|
+
}
|
|
13300
|
+
__name(isNegationExcluded, "isNegationExcluded");
|
|
12916
13301
|
function hasUnmodeledWorkspaceGlob(globs) {
|
|
12917
13302
|
return globs.some((glob) => {
|
|
12918
|
-
const g = glob.replace(/^!/, "");
|
|
13303
|
+
const g = glob.replace(/^!/, "").replace(/^\.\//, "");
|
|
12919
13304
|
if (!g.includes("*")) return false;
|
|
12920
13305
|
return !/^[^*]+\/\*$/.test(g);
|
|
12921
13306
|
});
|
|
@@ -12941,27 +13326,47 @@ function readRootPackage(root) {
|
|
|
12941
13326
|
} catch {
|
|
12942
13327
|
return null;
|
|
12943
13328
|
}
|
|
13329
|
+
if (pkg === null) return null;
|
|
12944
13330
|
const scripts = Object.keys(pkg.scripts ?? {});
|
|
12945
13331
|
if (!scripts.includes("build") && !scripts.includes("test")) return null;
|
|
13332
|
+
const scriptsText = {};
|
|
13333
|
+
for (const [k, v] of Object.entries(pkg.scripts ?? {})) {
|
|
13334
|
+
if (typeof v === "string") scriptsText[k] = v;
|
|
13335
|
+
}
|
|
12946
13336
|
return {
|
|
12947
13337
|
dir: ".",
|
|
12948
13338
|
name: typeof pkg.name === "string" && pkg.name ? pkg.name : "root",
|
|
12949
13339
|
scripts,
|
|
12950
|
-
deps:
|
|
13340
|
+
deps: declaredDeps(pkg),
|
|
13341
|
+
scriptsText
|
|
12951
13342
|
};
|
|
12952
13343
|
}
|
|
12953
13344
|
__name(readRootPackage, "readRootPackage");
|
|
12954
|
-
function
|
|
12955
|
-
|
|
13345
|
+
function scriptFansOut(text) {
|
|
13346
|
+
return typeof text === "string" && /(^|\s)(--workspaces(?=\s|$)|--?ws(?=\s|$))/.test(text);
|
|
13347
|
+
}
|
|
13348
|
+
__name(scriptFansOut, "scriptFansOut");
|
|
13349
|
+
function declaredDeps(pkg) {
|
|
13350
|
+
return [
|
|
13351
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
13352
|
+
...Object.keys(pkg.devDependencies ?? {}),
|
|
13353
|
+
...Object.keys(pkg.peerDependencies ?? {}),
|
|
13354
|
+
...Object.keys(pkg.optionalDependencies ?? {})
|
|
13355
|
+
];
|
|
13356
|
+
}
|
|
13357
|
+
__name(declaredDeps, "declaredDeps");
|
|
13358
|
+
function workspaceDirCandidates(root, globs) {
|
|
12956
13359
|
const dirs = /* @__PURE__ */ new Set();
|
|
12957
13360
|
for (const glob of globs) {
|
|
12958
13361
|
if (glob.startsWith("!")) continue;
|
|
12959
|
-
const g = glob.replace(/\/$/, "");
|
|
13362
|
+
const g = glob.replace(/^\.\//, "").replace(/\/$/, "");
|
|
12960
13363
|
if (g.endsWith("/*")) {
|
|
12961
13364
|
const base = g.slice(0, -2);
|
|
12962
13365
|
let entries;
|
|
12963
13366
|
try {
|
|
12964
|
-
entries = readdirSync4(join14(root, base), { withFileTypes: true }).filter(
|
|
13367
|
+
entries = readdirSync4(join14(root, base), { withFileTypes: true }).filter(
|
|
13368
|
+
(e) => e.isDirectory() || e.isSymbolicLink() && existsSync6(join14(root, base, e.name, "package.json"))
|
|
13369
|
+
).map((e) => e.name);
|
|
12965
13370
|
} catch {
|
|
12966
13371
|
continue;
|
|
12967
13372
|
}
|
|
@@ -12970,30 +13375,43 @@ function readWorkspacePackages(root) {
|
|
|
12970
13375
|
dirs.add(g);
|
|
12971
13376
|
}
|
|
12972
13377
|
}
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
13378
|
+
return [...dirs].sort();
|
|
13379
|
+
}
|
|
13380
|
+
__name(workspaceDirCandidates, "workspaceDirCandidates");
|
|
13381
|
+
function readWorkspacePackages(root) {
|
|
13382
|
+
const globs = readWorkspaceGlobs(root);
|
|
13383
|
+
const packages = [];
|
|
13384
|
+
const skipped = [];
|
|
13385
|
+
for (const dir of workspaceDirCandidates(root, globs)) {
|
|
12976
13386
|
const manifest = join14(root, dir, "package.json");
|
|
12977
13387
|
if (!existsSync6(manifest)) continue;
|
|
13388
|
+
if (workspaceDirFor(`${dir}/package.json`, globs) !== dir) {
|
|
13389
|
+
const positives = globs.filter((g) => !g.startsWith("!"));
|
|
13390
|
+
if (workspaceDirFor(`${dir}/package.json`, positives) === dir) continue;
|
|
13391
|
+
skipped.push(dir);
|
|
13392
|
+
continue;
|
|
13393
|
+
}
|
|
12978
13394
|
let pkg;
|
|
12979
13395
|
try {
|
|
12980
13396
|
pkg = JSON.parse(readFileSync19(manifest, "utf8"));
|
|
12981
13397
|
} catch {
|
|
13398
|
+
skipped.push(dir);
|
|
13399
|
+
continue;
|
|
13400
|
+
}
|
|
13401
|
+
if (pkg === null || typeof pkg.name !== "string" || !pkg.name) {
|
|
13402
|
+
skipped.push(dir);
|
|
12982
13403
|
continue;
|
|
12983
13404
|
}
|
|
12984
|
-
|
|
12985
|
-
pkgs.push({
|
|
13405
|
+
packages.push({
|
|
12986
13406
|
dir,
|
|
12987
13407
|
name: pkg.name,
|
|
12988
13408
|
scripts: Object.keys(pkg.scripts ?? {}),
|
|
12989
|
-
deps:
|
|
12990
|
-
...Object.keys(pkg.dependencies ?? {}),
|
|
12991
|
-
...Object.keys(pkg.devDependencies ?? {}),
|
|
12992
|
-
...Object.keys(pkg.peerDependencies ?? {})
|
|
12993
|
-
]
|
|
13409
|
+
deps: declaredDeps(pkg)
|
|
12994
13410
|
});
|
|
12995
13411
|
}
|
|
12996
|
-
|
|
13412
|
+
packages.sort((a, b) => a.dir.localeCompare(b.dir));
|
|
13413
|
+
skipped.sort();
|
|
13414
|
+
return { packages, skipped };
|
|
12997
13415
|
}
|
|
12998
13416
|
__name(readWorkspacePackages, "readWorkspacePackages");
|
|
12999
13417
|
function affectedWorkspaces(changedFiles, workspaceGlobs) {
|
|
@@ -13005,8 +13423,7 @@ function affectedWorkspaces(changedFiles, workspaceGlobs) {
|
|
|
13005
13423
|
return [...dirs].sort();
|
|
13006
13424
|
}
|
|
13007
13425
|
__name(affectedWorkspaces, "affectedWorkspaces");
|
|
13008
|
-
function
|
|
13009
|
-
const byDir = new Map(packages.map((p) => [p.dir, p]));
|
|
13426
|
+
function dependencyEdges(packages) {
|
|
13010
13427
|
const byName = new Map(packages.map((p) => [p.name, p]));
|
|
13011
13428
|
const dependsOn = /* @__PURE__ */ new Map();
|
|
13012
13429
|
for (const p of packages) {
|
|
@@ -13015,6 +13432,12 @@ function buildSetFor(affected, packages, alsoBuild = []) {
|
|
|
13015
13432
|
p.deps.map((d) => byName.get(d)?.dir).filter((d) => !!d && d !== p.dir)
|
|
13016
13433
|
);
|
|
13017
13434
|
}
|
|
13435
|
+
return dependsOn;
|
|
13436
|
+
}
|
|
13437
|
+
__name(dependencyEdges, "dependencyEdges");
|
|
13438
|
+
function reverseDependencyClosure(affected, packages) {
|
|
13439
|
+
const byDir = new Map(packages.map((p) => [p.dir, p]));
|
|
13440
|
+
const dependsOn = dependencyEdges(packages);
|
|
13018
13441
|
const consumers = new Set(affected.filter((a) => byDir.has(a)));
|
|
13019
13442
|
let grew = true;
|
|
13020
13443
|
while (grew) {
|
|
@@ -13027,6 +13450,13 @@ function buildSetFor(affected, packages, alsoBuild = []) {
|
|
|
13027
13450
|
}
|
|
13028
13451
|
}
|
|
13029
13452
|
}
|
|
13453
|
+
return [...consumers].sort();
|
|
13454
|
+
}
|
|
13455
|
+
__name(reverseDependencyClosure, "reverseDependencyClosure");
|
|
13456
|
+
function buildSetFor(affected, packages, alsoBuild = []) {
|
|
13457
|
+
const byDir = new Map(packages.map((p) => [p.dir, p]));
|
|
13458
|
+
const dependsOn = dependencyEdges(packages);
|
|
13459
|
+
const consumers = reverseDependencyClosure(affected, packages);
|
|
13030
13460
|
const wanted = /* @__PURE__ */ new Set();
|
|
13031
13461
|
const addDeps = /* @__PURE__ */ __name((dir) => {
|
|
13032
13462
|
if (wanted.has(dir)) return;
|
|
@@ -13051,13 +13481,81 @@ function buildSetFor(affected, packages, alsoBuild = []) {
|
|
|
13051
13481
|
}
|
|
13052
13482
|
__name(buildSetFor, "buildSetFor");
|
|
13053
13483
|
|
|
13484
|
+
// packages/cli/src/commands/review/lib/workspace-scope.ts
|
|
13485
|
+
init_esbuild_shims();
|
|
13486
|
+
var LICENSE_LIKE_RE = /(^|\/)(LICEN[CS]ES?|COPYING|NOTICES?)(-[^/.]+)?(\.(md|txt|rst))?$/;
|
|
13487
|
+
function isInertLicense(path3) {
|
|
13488
|
+
return LICENSE_LIKE_RE.test(path3);
|
|
13489
|
+
}
|
|
13490
|
+
__name(isInertLicense, "isInertLicense");
|
|
13491
|
+
var INERT_OUTSIDE_RE = /^(\.github\/|CHANGELOG\.md$|\.gitignore$|\.gitattributes$|\.editorconfig$|\.idea\/|\.vscode\/)/;
|
|
13492
|
+
function resolveTestScope(input) {
|
|
13493
|
+
const { changed, globs, packages, skipped } = input;
|
|
13494
|
+
const affected = affectedWorkspaces(changed, globs);
|
|
13495
|
+
const graph = input.rootPackage ? [input.rootPackage, ...packages] : packages;
|
|
13496
|
+
const scriptsOf = new Map(graph.map((p) => [p.dir, p.scripts]));
|
|
13497
|
+
const caveats = [];
|
|
13498
|
+
if (skipped.length > 0) {
|
|
13499
|
+
caveats.push(
|
|
13500
|
+
`the workspace graph could not be fully computed: ${skipped.join(", ")} ${skipped.length === 1 ? "has" : "have"} a package.json that does not parse, has no usable \`name\`, or is shadowed by a later workspace glob, so a reverse dependency may be missing from the scoped set`
|
|
13501
|
+
);
|
|
13502
|
+
}
|
|
13503
|
+
const unmapped = affected.filter(
|
|
13504
|
+
(d) => d !== "." && !scriptsOf.has(d) && !skipped.includes(d)
|
|
13505
|
+
);
|
|
13506
|
+
const outside = changed.filter((f) => workspaceDirFor(f, globs) === null);
|
|
13507
|
+
const excluded = outside.filter((f) => isNegationExcluded(f, globs));
|
|
13508
|
+
const influential = outside.filter(
|
|
13509
|
+
(f) => !isInertLicense(f) && !f.startsWith("docs/") && !INERT_OUTSIDE_RE.test(f) && !isNegationExcluded(f, globs)
|
|
13510
|
+
);
|
|
13511
|
+
if (unmapped.length > 0) {
|
|
13512
|
+
caveats.push(
|
|
13513
|
+
`the workspace globs claim ${unmapped.join(", ")}, but no readable package.json there makes a graph member \u2014 no suite covers a change inside, and a dependent of the diff may be missing from the scoped set`
|
|
13514
|
+
);
|
|
13515
|
+
}
|
|
13516
|
+
if (influential.length > 0) {
|
|
13517
|
+
caveats.push(
|
|
13518
|
+
`${influential.length} changed file(s) sit outside every workspace and are not inert (e.g. ${influential.slice(0, 3).join(", ")}); a root script or config can affect any package's tests, and the scoped set cannot cover them`
|
|
13519
|
+
);
|
|
13520
|
+
}
|
|
13521
|
+
if (excluded.length > 0) {
|
|
13522
|
+
caveats.push(
|
|
13523
|
+
`${excluded.length} changed file(s) sit in negated workspaces (e.g. ${excluded.slice(0, 3).join(", ")}) \u2014 excluded from the npm workspace graph (a separate toolchain and lockfile); their own toolchain's suites were not run`
|
|
13524
|
+
);
|
|
13525
|
+
}
|
|
13526
|
+
const closure = reverseDependencyClosure(affected, graph);
|
|
13527
|
+
let workspaces = closure.filter((d) => scriptsOf.get(d)?.includes("test"));
|
|
13528
|
+
let fanOutCaveat;
|
|
13529
|
+
if (input.rootTestFansOut && workspaces.includes(".")) {
|
|
13530
|
+
workspaces = workspaces.filter((d) => d !== ".");
|
|
13531
|
+
fanOutCaveat = "the root's `test` script fans out over every workspace (`--workspaces`), so the root suite did not run \u2014 it cannot finish inside one command deadline; the scoped member suites are the coverage";
|
|
13532
|
+
}
|
|
13533
|
+
{
|
|
13534
|
+
const rootRuns = input.rootPackage?.scripts.includes("test") && !input.rootTestFansOut ? 1 : 0;
|
|
13535
|
+
const testable = packages.filter((p) => p.scripts.includes("test")).length + rootRuns;
|
|
13536
|
+
const scoped = workspaces.length;
|
|
13537
|
+
if (scoped * 2 > testable) {
|
|
13538
|
+
caveats.push(
|
|
13539
|
+
`the diff's reverse-dependency closure covers ${scoped} of ${testable} testable ${rootRuns ? "suites (including the root)" : "workspaces"} \u2014 more than half, so the scoped set is not a meaningful narrowing`
|
|
13540
|
+
);
|
|
13541
|
+
}
|
|
13542
|
+
}
|
|
13543
|
+
if (fanOutCaveat) caveats.push(fanOutCaveat);
|
|
13544
|
+
return caveats.length > 0 ? { workspaces, caveat: caveats.join("; ") } : { workspaces };
|
|
13545
|
+
}
|
|
13546
|
+
__name(resolveTestScope, "resolveTestScope");
|
|
13547
|
+
|
|
13054
13548
|
// packages/cli/src/commands/review/build-test.ts
|
|
13549
|
+
function shellArg(dir) {
|
|
13550
|
+
return `"${dir.replace(/[\\"$`]/g, "\\$&")}"`;
|
|
13551
|
+
}
|
|
13552
|
+
__name(shellArg, "shellArg");
|
|
13055
13553
|
function buildCommand(dir) {
|
|
13056
|
-
return dir === "." ? "npm run build" : `npm run build --workspace
|
|
13554
|
+
return dir === "." ? "npm run build" : `npm run build --workspace=${shellArg(dir)}`;
|
|
13057
13555
|
}
|
|
13058
13556
|
__name(buildCommand, "buildCommand");
|
|
13059
13557
|
function testCommand(dir) {
|
|
13060
|
-
return dir === "." ? "npm test" : `npm test --workspace
|
|
13558
|
+
return dir === "." ? "npm test" : `npm test --workspace=${shellArg(dir)}`;
|
|
13061
13559
|
}
|
|
13062
13560
|
__name(testCommand, "testCommand");
|
|
13063
13561
|
var KEEP_HEAD = 2e3;
|
|
@@ -13092,6 +13590,7 @@ ${rescued.join("\n")}
|
|
|
13092
13590
|
__name(trimOutput, "trimOutput");
|
|
13093
13591
|
var INSTALL_MIN_FREE_BYTES = 3 * 1024 ** 3;
|
|
13094
13592
|
var BUILD_MIN_FREE_BYTES = 1024 ** 3;
|
|
13593
|
+
var BUDGET_MIN_ATTEMPT_MS = 15e3;
|
|
13095
13594
|
function freeDiskBytes(dir) {
|
|
13096
13595
|
try {
|
|
13097
13596
|
const s = statfsSync(dir);
|
|
@@ -13129,7 +13628,8 @@ function run(command, cwd, timeoutMs) {
|
|
|
13129
13628
|
exitCode: r.status,
|
|
13130
13629
|
seconds: Math.round((Date.now() - started) / 1e3),
|
|
13131
13630
|
timedOut,
|
|
13132
|
-
output: trimOutput(`${r.stdout ?? ""}${r.stderr ?? ""}`)
|
|
13631
|
+
output: trimOutput(`${r.stdout ?? ""}${r.stderr ?? ""}`),
|
|
13632
|
+
deadlineMs: timeoutMs
|
|
13133
13633
|
};
|
|
13134
13634
|
}
|
|
13135
13635
|
__name(run, "run");
|
|
@@ -13169,6 +13669,10 @@ __name(changedFilesFrom, "changedFilesFrom");
|
|
|
13169
13669
|
function runBuildTest(args) {
|
|
13170
13670
|
const root = resolve14(args.worktree);
|
|
13171
13671
|
const perCommandMs = args.timeout * 1e3;
|
|
13672
|
+
const callBudgetMs = (args.budget ?? Math.max(args.timeout, args.timeout * 2 - 30)) * 1e3;
|
|
13673
|
+
const runStarted = Date.now();
|
|
13674
|
+
const remainingMs = /* @__PURE__ */ __name(() => callBudgetMs - (Date.now() - runStarted), "remainingMs");
|
|
13675
|
+
const deadlineSecs = /* @__PURE__ */ __name((r) => Math.round((r.deadlineMs ?? perCommandMs) / 1e3), "deadlineSecs");
|
|
13172
13676
|
const exec = args.exec ?? run;
|
|
13173
13677
|
const changed = changedFilesFrom(args.plan);
|
|
13174
13678
|
const unsupportedReport = /* @__PURE__ */ __name((note) => ({
|
|
@@ -13184,15 +13688,13 @@ function runBuildTest(args) {
|
|
|
13184
13688
|
note
|
|
13185
13689
|
}), "unsupportedReport");
|
|
13186
13690
|
const globs = readWorkspaceGlobs(root);
|
|
13187
|
-
let packages = readWorkspacePackages(root);
|
|
13691
|
+
let { packages, skipped } = readWorkspacePackages(root);
|
|
13692
|
+
const rootPkg = readRootPackage(root);
|
|
13188
13693
|
let singleRoot = false;
|
|
13189
13694
|
const unmodeled = globs.length > 0 && hasUnmodeledWorkspaceGlob(globs);
|
|
13190
|
-
if (!unmodeled && globs.length === 0) {
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
packages = [rootPkg];
|
|
13194
|
-
singleRoot = true;
|
|
13195
|
-
}
|
|
13695
|
+
if (!unmodeled && globs.length === 0 && rootPkg) {
|
|
13696
|
+
packages = [rootPkg];
|
|
13697
|
+
singleRoot = true;
|
|
13196
13698
|
}
|
|
13197
13699
|
if (unmodeled || !singleRoot && (globs.length === 0 || packages.length === 0)) {
|
|
13198
13700
|
return unsupportedReport(
|
|
@@ -13200,6 +13702,15 @@ function runBuildTest(args) {
|
|
|
13200
13702
|
);
|
|
13201
13703
|
}
|
|
13202
13704
|
const affected = singleRoot ? changed.length > 0 ? ["."] : [] : affectedWorkspaces(changed, globs);
|
|
13705
|
+
let testScope = singleRoot || args.buildOnly ? void 0 : resolveTestScope({
|
|
13706
|
+
changed,
|
|
13707
|
+
globs,
|
|
13708
|
+
packages,
|
|
13709
|
+
skipped,
|
|
13710
|
+
rootPackage: rootPkg,
|
|
13711
|
+
rootTestFansOut: rootPkg?.scripts.includes("test") ? scriptFansOut(rootPkg.scriptsText["test"]) : false
|
|
13712
|
+
});
|
|
13713
|
+
const scopeGraph = !singleRoot && rootPkg ? [rootPkg, ...packages] : packages;
|
|
13203
13714
|
if (affected.length === 0) {
|
|
13204
13715
|
return {
|
|
13205
13716
|
toolchain: "npm",
|
|
@@ -13209,12 +13720,13 @@ function runBuildTest(args) {
|
|
|
13209
13720
|
install: null,
|
|
13210
13721
|
build: [],
|
|
13211
13722
|
test: [],
|
|
13723
|
+
...testScope ? { testScope } : {},
|
|
13212
13724
|
ok: true,
|
|
13213
13725
|
timedOut: [],
|
|
13214
|
-
note: `The diff changes ${changed.length} file(s), none of them inside a workspace (
|
|
13726
|
+
note: args.buildOnly ? `The diff changes ${changed.length} file(s), none of them inside a workspace. There is no package to build, and tests are out of scope for a build-only probe.` : testScope?.caveat ? `The diff changes ${changed.length} file(s), none of them inside a workspace. There is no package to build and no test to run, but the scope decision recorded a caveat: ${testScope.caveat}.` : `The diff changes ${changed.length} file(s), none of them inside a workspace (nothing the workspaces' tests can feel). There is no package to build and no test to run \u2014 this is a complete answer, not a skipped step.`
|
|
13215
13727
|
};
|
|
13216
13728
|
}
|
|
13217
|
-
const byDir = new Map(
|
|
13729
|
+
const byDir = new Map(scopeGraph.map((p) => [p.dir, p]));
|
|
13218
13730
|
const unmapped = affected.filter((d) => d !== "." && !byDir.has(d));
|
|
13219
13731
|
if (unmapped.length > 0) {
|
|
13220
13732
|
return unsupportedReport(
|
|
@@ -13254,7 +13766,16 @@ function runBuildTest(args) {
|
|
|
13254
13766
|
results.note = `Insufficient disk space (${gib(free)}G free, need ~${gib(INSTALL_MIN_FREE_BYTES)}G): skipped \`${installCmd}\`, so nothing could be built or tested. This is an environment issue, not a code finding \u2014 report it as informational.`;
|
|
13255
13767
|
return results;
|
|
13256
13768
|
}
|
|
13257
|
-
|
|
13769
|
+
if (remainingMs() < BUDGET_MIN_ATTEMPT_MS) {
|
|
13770
|
+
results.ok = false;
|
|
13771
|
+
results.note = `The whole-call budget was spent before the install could start (${args.budget != null ? `--budget ${args.budget}s` : "default budget"}), so nothing could be built or tested. This is an infrastructure result, not a defect in the diff \u2014 report it as informational.`;
|
|
13772
|
+
return results;
|
|
13773
|
+
}
|
|
13774
|
+
const install = exec(
|
|
13775
|
+
installCmd,
|
|
13776
|
+
root,
|
|
13777
|
+
Math.min(perCommandMs, remainingMs())
|
|
13778
|
+
);
|
|
13258
13779
|
results.install = install;
|
|
13259
13780
|
if (install.timedOut) results.timedOut.push(install.command);
|
|
13260
13781
|
if (install.timedOut) {
|
|
@@ -13269,7 +13790,7 @@ function runBuildTest(args) {
|
|
|
13269
13790
|
}
|
|
13270
13791
|
if (install.timedOut || !installComplete()) {
|
|
13271
13792
|
results.ok = false;
|
|
13272
|
-
results.note = install.timedOut ? `\`${install.command}\` ran out of time (${
|
|
13793
|
+
results.note = install.timedOut ? `\`${install.command}\` ran out of time (${deadlineSecs(install)}s) and left an incomplete \`node_modules\`, so nothing could be built or tested against it. This is an infrastructure result, not a defect in the diff \u2014 report it as informational.` : "The install failed and left no usable `node_modules`, so nothing could be built or tested. This is an environment failure, not a defect in the diff \u2014 report it as informational.";
|
|
13273
13794
|
return results;
|
|
13274
13795
|
}
|
|
13275
13796
|
}
|
|
@@ -13280,9 +13801,12 @@ function runBuildTest(args) {
|
|
|
13280
13801
|
return results;
|
|
13281
13802
|
}
|
|
13282
13803
|
const alsoBuild = [];
|
|
13283
|
-
let set = buildSetFor(affected,
|
|
13804
|
+
let set = buildSetFor(affected, scopeGraph);
|
|
13284
13805
|
const built = /* @__PURE__ */ new Set();
|
|
13285
13806
|
const widened = /* @__PURE__ */ new Set();
|
|
13807
|
+
const rootBuildRuns = !!rootPkg?.scripts.includes("build") && !scriptFansOut(rootPkg.scriptsText["build"]);
|
|
13808
|
+
const rootBuildSkipped = !singleRoot && !rootBuildRuns;
|
|
13809
|
+
const notBuilt = [];
|
|
13286
13810
|
for (let attempt = 0; attempt <= 3; attempt++) {
|
|
13287
13811
|
let failure = null;
|
|
13288
13812
|
for (const dir of set) {
|
|
@@ -13292,7 +13816,23 @@ function runBuildTest(args) {
|
|
|
13292
13816
|
built.add(dir);
|
|
13293
13817
|
continue;
|
|
13294
13818
|
}
|
|
13295
|
-
|
|
13819
|
+
if (dir === "." && rootBuildSkipped) {
|
|
13820
|
+
built.add(dir);
|
|
13821
|
+
continue;
|
|
13822
|
+
}
|
|
13823
|
+
if (remainingMs() < BUDGET_MIN_ATTEMPT_MS) {
|
|
13824
|
+
notBuilt.push(
|
|
13825
|
+
...set.filter(
|
|
13826
|
+
(d) => !built.has(d) && byDir.get(d)?.scripts.includes("build")
|
|
13827
|
+
)
|
|
13828
|
+
);
|
|
13829
|
+
break;
|
|
13830
|
+
}
|
|
13831
|
+
const r = exec(
|
|
13832
|
+
buildCommand(dir),
|
|
13833
|
+
root,
|
|
13834
|
+
Math.min(perCommandMs, remainingMs())
|
|
13835
|
+
);
|
|
13296
13836
|
results.build.push(r);
|
|
13297
13837
|
if (r.timedOut) results.timedOut.push(r.command);
|
|
13298
13838
|
if (r.exitCode !== 0) {
|
|
@@ -13308,8 +13848,8 @@ function runBuildTest(args) {
|
|
|
13308
13848
|
});
|
|
13309
13849
|
if (missing.length === 0 || failure.timedOut || attempt === 3) {
|
|
13310
13850
|
results.ok = false;
|
|
13311
|
-
results.note = failure.timedOut ? `\`${failure.command}\` ran out of time (${
|
|
13312
|
-
results.buildSet = set;
|
|
13851
|
+
results.note = failure.timedOut ? `\`${failure.command}\` ran out of time (${deadlineSecs(failure)}s). That is an infrastructure result, not a defect in the diff \u2014 report it as informational.` : `\`${failure.command}\` failed. Correlate the errors below with the diff: a compile error in a file the PR changed is a Critical; one in a file it did not touch is a pre-existing failure, and belongs in the terminal, not on the PR.`;
|
|
13852
|
+
results.buildSet = (rootBuildSkipped ? set.filter((d) => d !== ".") : set).filter((d) => !notBuilt.includes(d));
|
|
13313
13853
|
results.widenedWith = [...widened];
|
|
13314
13854
|
return results;
|
|
13315
13855
|
}
|
|
@@ -13319,31 +13859,85 @@ function runBuildTest(args) {
|
|
|
13319
13859
|
const dir = packages.find((p) => p.name === name)?.dir;
|
|
13320
13860
|
if (dir) alsoBuild.push(dir);
|
|
13321
13861
|
}
|
|
13322
|
-
set = buildSetFor(affected,
|
|
13862
|
+
set = buildSetFor(affected, scopeGraph, alsoBuild);
|
|
13323
13863
|
}
|
|
13324
|
-
results.buildSet = set;
|
|
13864
|
+
results.buildSet = (rootBuildSkipped ? set.filter((d) => d !== ".") : set).filter((d) => !notBuilt.includes(d));
|
|
13325
13865
|
results.widenedWith = [...widened];
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13866
|
+
if (notBuilt.length > 0) results.notBuilt = [...notBuilt].sort();
|
|
13867
|
+
const rootHasTest = !!rootPkg?.scripts.includes("test");
|
|
13868
|
+
const testDirs = args.buildOnly ? [] : !testScope ? affected : testScope.workspaces;
|
|
13869
|
+
const runnable = /* @__PURE__ */ __name((dir) => dir === "." ? rootHasTest : !!byDir.get(dir)?.scripts.includes("test"), "runnable");
|
|
13870
|
+
const affectedSet = new Set(affected);
|
|
13871
|
+
const runnableDirs = [
|
|
13872
|
+
...testDirs.filter((d) => affectedSet.has(d) && runnable(d)),
|
|
13873
|
+
...testDirs.filter((d) => !affectedSet.has(d) && runnable(d))
|
|
13874
|
+
];
|
|
13875
|
+
const untestable = notBuilt.length > 0 ? new Set(reverseDependencyClosure(notBuilt, scopeGraph)) : /* @__PURE__ */ new Set();
|
|
13876
|
+
const notRun = [];
|
|
13877
|
+
for (let i = 0; i < runnableDirs.length; i++) {
|
|
13878
|
+
const dir = runnableDirs[i];
|
|
13879
|
+
if (untestable.has(dir)) {
|
|
13880
|
+
notRun.push(dir);
|
|
13881
|
+
continue;
|
|
13882
|
+
}
|
|
13883
|
+
const remaining = remainingMs();
|
|
13884
|
+
if (remaining < BUDGET_MIN_ATTEMPT_MS) {
|
|
13885
|
+
notRun.push(...runnableDirs.slice(i).filter((d) => !untestable.has(d)));
|
|
13886
|
+
break;
|
|
13887
|
+
}
|
|
13888
|
+
const r = exec(testCommand(dir), root, Math.min(perCommandMs, remaining));
|
|
13330
13889
|
results.test.push(r);
|
|
13331
13890
|
if (r.timedOut) results.timedOut.push(r.command);
|
|
13332
13891
|
if (r.exitCode !== 0) results.ok = false;
|
|
13333
13892
|
}
|
|
13893
|
+
notRun.sort();
|
|
13894
|
+
const partialNote = [
|
|
13895
|
+
notBuilt.length > 0 ? `the build phase reached the whole-call budget \u2014 not built: ` + notBuilt.join(", ") : "",
|
|
13896
|
+
notRun.length > 0 ? `the whole-call budget (${Math.round(callBudgetMs / 1e3)}s) was spent with ${notRun.length} suite(s) still to run \u2014 not run: ` + notRun.join(", ") : ""
|
|
13897
|
+
].filter(Boolean).join("; ") || void 0;
|
|
13898
|
+
if (testScope && partialNote) {
|
|
13899
|
+
const ran = testScope.workspaces.filter((d) => !notRun.includes(d));
|
|
13900
|
+
testScope = {
|
|
13901
|
+
workspaces: ran,
|
|
13902
|
+
...notRun.length > 0 ? { notRun } : {},
|
|
13903
|
+
caveat: testScope.caveat ? `${testScope.caveat}; ${partialNote}` : partialNote
|
|
13904
|
+
};
|
|
13905
|
+
}
|
|
13906
|
+
if (testScope) results.testScope = testScope;
|
|
13334
13907
|
if (!results.note) {
|
|
13335
13908
|
const failed = [...results.build, ...results.test].filter(
|
|
13336
13909
|
(r) => r.exitCode !== 0
|
|
13337
13910
|
);
|
|
13338
13911
|
const realFailures = failed.filter((r) => !r.timedOut);
|
|
13339
13912
|
if (results.ok) {
|
|
13340
|
-
|
|
13913
|
+
let testsClause;
|
|
13914
|
+
if (args.buildOnly) {
|
|
13915
|
+
testsClause = ". Tests were not run (build-only).";
|
|
13916
|
+
} else if (!testScope) {
|
|
13917
|
+
testsClause = results.test.length === 0 ? ", but the package defines no test script, so no tests ran." : " and ran the tests of the changed ones. Everything passed.";
|
|
13918
|
+
} else if (testScope.workspaces.length === 0) {
|
|
13919
|
+
testsClause = testScope.notRun?.length ? ", but the whole-call budget was spent before any suite could run." : ", but no workspace in scope defines a test script, so no tests ran.";
|
|
13920
|
+
} else {
|
|
13921
|
+
testsClause = ` and ran the tests scoped to ${testScope.workspaces.join(", ")} \u2014 the changed workspaces and every workspace declared to depend on them that defines a test script. Everything passed.`;
|
|
13922
|
+
}
|
|
13923
|
+
if (testScope?.caveat) testsClause += ` Caveat: ${testScope.caveat}.`;
|
|
13924
|
+
const builtWorkspaces = results.buildSet.filter(
|
|
13925
|
+
(d) => singleRoot || d !== "."
|
|
13926
|
+
).length;
|
|
13927
|
+
const rootSuffix = !singleRoot && results.buildSet.includes(".") && !rootBuildSkipped ? " (plus the root package)" : "";
|
|
13928
|
+
results.note = `Built ${builtWorkspaces} of ${packages.length} workspaces${rootSuffix} (the ${affected.length} the diff changes, plus what they compile against${widened.size ? `, plus ${[...widened].join(", ")} the compiler asked for` : ""})${testsClause}`;
|
|
13341
13929
|
} else if (realFailures.length === 0) {
|
|
13342
|
-
results.note = `${failed.length} command(s) ran out of time (${
|
|
13930
|
+
results.note = `${failed.length} command(s) ran out of time (${deadlineSecs(failed[0])}s). A timeout is an infrastructure result, not a defect in the diff \u2014 report it as informational.`;
|
|
13343
13931
|
} else {
|
|
13344
13932
|
results.note = `${realFailures.length} command(s) failed. Correlate each error with the diff: a failure in a file the PR changed is a Critical; one in a file it did not touch is pre-existing.` + (failed.length > realFailures.length ? " (Commands that timed out are infrastructure, not findings.)" : "");
|
|
13345
13933
|
}
|
|
13346
13934
|
}
|
|
13935
|
+
if (results.testScope?.caveat && !results.note.includes("Caveat:")) {
|
|
13936
|
+
results.note += ` Caveat: ${results.testScope.caveat}.`;
|
|
13937
|
+
}
|
|
13938
|
+
if (partialNote && !results.testScope) {
|
|
13939
|
+
results.note = results.note ? `${results.note} ${partialNote}.` : partialNote;
|
|
13940
|
+
}
|
|
13347
13941
|
if (results.install && results.install.exitCode !== 0) {
|
|
13348
13942
|
results.note = `\`${results.install.command}\` exited ${results.install.exitCode} but left a usable \`node_modules\`, so the build and test below ran anyway and their results stand. The install failure is an environment/infrastructure result \u2014 report it as informational, never as a Critical, and never against this PR. ` + results.note;
|
|
13349
13943
|
}
|
|
@@ -13352,7 +13946,7 @@ function runBuildTest(args) {
|
|
|
13352
13946
|
__name(runBuildTest, "runBuildTest");
|
|
13353
13947
|
var buildTestCommand = {
|
|
13354
13948
|
command: "build-test",
|
|
13355
|
-
describe: "Build
|
|
13949
|
+
describe: "Build the workspaces the diff changes (and what they compile against), test those plus their dependents, with a deadline the commands can actually meet",
|
|
13356
13950
|
builder: /* @__PURE__ */ __name((yargs) => yargs.option("plan", {
|
|
13357
13951
|
type: "string",
|
|
13358
13952
|
demandOption: true,
|
|
@@ -13367,7 +13961,10 @@ var buildTestCommand = {
|
|
|
13367
13961
|
}).option("timeout", {
|
|
13368
13962
|
type: "number",
|
|
13369
13963
|
default: 300,
|
|
13370
|
-
describe: "Per-command deadline in seconds. Kept strictly below the 600s (600000ms) tool timeout the agent's brief welds onto the whole call, so a single hung command's own deadline fires \u2014 and build-test reports it as data \u2014 before the outer shell kill would discard the report.
|
|
13964
|
+
describe: "Per-command deadline in seconds. Kept strictly below the 600s (600000ms) tool timeout the agent's brief welds onto the whole call, so a single hung command's own deadline fires \u2014 and build-test reports it as data \u2014 before the outer shell kill would discard the report. Commands that would SUM past the whole call are stopped and disclosed instead \u2014 see --budget."
|
|
13965
|
+
}).option("budget", {
|
|
13966
|
+
type: "number",
|
|
13967
|
+
describe: "Whole-call wall-clock budget in seconds, measured from the top of the call \u2014 install and build time count against it (default: 2\xD7 --timeout minus 30s of headroom for process startup and the report write). Each suite is attempted with whatever of the budget remains \u2014 a suite killed at the boundary is a timeout, reported as infrastructure \u2014 and only suites never attempted are named notRun. A partial report survives where the outer shell kill would discard the whole one."
|
|
13371
13968
|
}).option("install", {
|
|
13372
13969
|
type: "boolean",
|
|
13373
13970
|
default: true,
|
|
@@ -13400,7 +13997,7 @@ import {
|
|
|
13400
13997
|
mkdirSync as mkdirSync18,
|
|
13401
13998
|
readFileSync as readFileSync21,
|
|
13402
13999
|
rmSync as rmSync7,
|
|
13403
|
-
statSync as
|
|
14000
|
+
statSync as statSync9,
|
|
13404
14001
|
writeFileSync as writeFileSync19
|
|
13405
14002
|
} from "node:fs";
|
|
13406
14003
|
import { dirname as dirname15, join as join16, resolve as resolve15 } from "node:path";
|
|
@@ -13500,7 +14097,7 @@ function runBaseTree(args) {
|
|
|
13500
14097
|
}
|
|
13501
14098
|
const lock = `${tree}.lock`;
|
|
13502
14099
|
try {
|
|
13503
|
-
const age = Date.now() -
|
|
14100
|
+
const age = Date.now() - statSync9(lock).mtimeMs;
|
|
13504
14101
|
if (age > 30 * 60 * 1e3) {
|
|
13505
14102
|
rmSync7(lock, { recursive: true, force: true });
|
|
13506
14103
|
}
|
|
@@ -13543,6 +14140,15 @@ function runBaseTree(args) {
|
|
|
13543
14140
|
// tree to run against.
|
|
13544
14141
|
buildOnly: true
|
|
13545
14142
|
});
|
|
14143
|
+
if ((build.notBuilt?.length ?? 0) > 0) {
|
|
14144
|
+
return {
|
|
14145
|
+
available: false,
|
|
14146
|
+
path: tree,
|
|
14147
|
+
baseSha: baseSha2,
|
|
14148
|
+
build,
|
|
14149
|
+
note: `the base tree build at ${baseSha2.slice(0, 9)} was cut short by the whole-call budget (${build.notBuilt.join(", ")} not built), so a rerun against it would manufacture pre-existing failures; an A/B is not available for this review (this is an infrastructure result, never a finding against the PR)`
|
|
14150
|
+
};
|
|
14151
|
+
}
|
|
13546
14152
|
if (!build.ok || build.toolchain !== "npm" || build.build.length === 0) {
|
|
13547
14153
|
try {
|
|
13548
14154
|
writeFileSync19(failedMarker(), `${baseSha2}
|
|
@@ -13846,7 +14452,7 @@ import {
|
|
|
13846
14452
|
readFileSync as readFileSync23,
|
|
13847
14453
|
existsSync as existsSync10,
|
|
13848
14454
|
rmSync as rmSync8,
|
|
13849
|
-
statSync as
|
|
14455
|
+
statSync as statSync10
|
|
13850
14456
|
} from "node:fs";
|
|
13851
14457
|
import { dirname as dirname17, join as join17, resolve as resolve17 } from "node:path";
|
|
13852
14458
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
@@ -13860,7 +14466,7 @@ var LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
|
13860
14466
|
var POLL_MS = 250;
|
|
13861
14467
|
function logBytes(p) {
|
|
13862
14468
|
try {
|
|
13863
|
-
return
|
|
14469
|
+
return statSync10(p).size;
|
|
13864
14470
|
} catch {
|
|
13865
14471
|
return 0;
|
|
13866
14472
|
}
|
|
@@ -15271,7 +15877,7 @@ import {
|
|
|
15271
15877
|
rmSync as rmSync9,
|
|
15272
15878
|
lstatSync as lstatSync4,
|
|
15273
15879
|
existsSync as existsSync11,
|
|
15274
|
-
statSync as
|
|
15880
|
+
statSync as statSync11,
|
|
15275
15881
|
symlinkSync
|
|
15276
15882
|
} from "node:fs";
|
|
15277
15883
|
import { createRequire } from "node:module";
|
|
@@ -15472,8 +16078,8 @@ function insideClassBody(codeLines, idx) {
|
|
|
15472
16078
|
return false;
|
|
15473
16079
|
}
|
|
15474
16080
|
__name(insideClassBody, "insideClassBody");
|
|
15475
|
-
function isRemovableStatement(
|
|
15476
|
-
const t2 = (
|
|
16081
|
+
function isRemovableStatement(lines, codeLines, idx) {
|
|
16082
|
+
const t2 = (lines[idx] ?? "").trim();
|
|
15477
16083
|
if (!(codeLines[idx] ?? "").endsWith(";")) return false;
|
|
15478
16084
|
if ((codeLines[idx] ?? "").slice(0, -1).includes(";")) return false;
|
|
15479
16085
|
if (!/^(?:await\s+)?[A-Za-z_$]/.test(t2)) return false;
|
|
@@ -15542,19 +16148,19 @@ function selectMutants(files, cap = MAX_MUTANTS) {
|
|
|
15542
16148
|
const replRest = [];
|
|
15543
16149
|
const derailed = [];
|
|
15544
16150
|
for (const f of files) {
|
|
15545
|
-
const
|
|
16151
|
+
const lines = f.content.split("\n");
|
|
15546
16152
|
const { inLiteral, codeLines, endState } = scanFileLines(f.content);
|
|
15547
16153
|
if (endState !== "code") {
|
|
15548
16154
|
derailed.push(f.file);
|
|
15549
16155
|
continue;
|
|
15550
16156
|
}
|
|
15551
16157
|
for (const n of [...f.addedLines].sort((a, b) => a - b)) {
|
|
15552
|
-
const raw =
|
|
16158
|
+
const raw = lines[n - 1];
|
|
15553
16159
|
if (raw === void 0) continue;
|
|
15554
16160
|
const t2 = raw.trim();
|
|
15555
16161
|
if (inLiteral[n - 1]) continue;
|
|
15556
16162
|
const code = codeLines[n - 1] ?? "";
|
|
15557
|
-
if (SAFETY_VERB_RE.test(code) && isRemovableStatement(
|
|
16163
|
+
if (SAFETY_VERB_RE.test(code) && isRemovableStatement(lines, codeLines, n - 1)) {
|
|
15558
16164
|
(f.hasNewTests ? preferred : rest).push({
|
|
15559
16165
|
file: f.file,
|
|
15560
16166
|
line: n,
|
|
@@ -15884,7 +16490,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
15884
16490
|
}
|
|
15885
16491
|
if (sourceStats.isSymbolicLink()) {
|
|
15886
16492
|
try {
|
|
15887
|
-
if (!
|
|
16493
|
+
if (!statSync11(sourceEntry).isDirectory()) continue;
|
|
15888
16494
|
} catch {
|
|
15889
16495
|
continue;
|
|
15890
16496
|
}
|
|
@@ -15958,34 +16564,34 @@ function runProbeSuite(probeTree, probes, deadlineAt, now = Date.now, dependency
|
|
|
15958
16564
|
}
|
|
15959
16565
|
__name(runProbeSuite, "runProbeSuite");
|
|
15960
16566
|
function splitDiffIntoHunks(diffText) {
|
|
15961
|
-
const
|
|
15962
|
-
const first =
|
|
16567
|
+
const lines = diffText.split("\n");
|
|
16568
|
+
const first = lines.findIndex((l) => l.startsWith("@@"));
|
|
15963
16569
|
if (first < 0) return [];
|
|
15964
16570
|
let headerStart = 0;
|
|
15965
16571
|
for (let k = first - 1; k >= 0; k--) {
|
|
15966
|
-
if (
|
|
16572
|
+
if (lines[k].startsWith("diff --git ")) {
|
|
15967
16573
|
headerStart = k;
|
|
15968
16574
|
break;
|
|
15969
16575
|
}
|
|
15970
16576
|
}
|
|
15971
|
-
let fileHeader =
|
|
16577
|
+
let fileHeader = lines.slice(headerStart, first);
|
|
15972
16578
|
const out = [];
|
|
15973
16579
|
let i = first;
|
|
15974
|
-
while (i <
|
|
15975
|
-
if (
|
|
16580
|
+
while (i < lines.length) {
|
|
16581
|
+
if (lines[i].startsWith("diff --git ")) {
|
|
15976
16582
|
const start = i;
|
|
15977
|
-
while (i <
|
|
16583
|
+
while (i < lines.length && !lines[i].startsWith("@@") && !(i > start && lines[i].startsWith("diff --git ")))
|
|
15978
16584
|
i++;
|
|
15979
|
-
fileHeader =
|
|
16585
|
+
fileHeader = lines.slice(start, i);
|
|
15980
16586
|
continue;
|
|
15981
16587
|
}
|
|
15982
|
-
if (!
|
|
16588
|
+
if (!lines[i].startsWith("@@")) {
|
|
15983
16589
|
i++;
|
|
15984
16590
|
continue;
|
|
15985
16591
|
}
|
|
15986
|
-
const header =
|
|
16592
|
+
const header = lines[i];
|
|
15987
16593
|
let j = i + 1;
|
|
15988
|
-
while (j <
|
|
16594
|
+
while (j < lines.length && !lines[j].startsWith("@@") && !lines[j].startsWith("diff --git ")) {
|
|
15989
16595
|
j++;
|
|
15990
16596
|
}
|
|
15991
16597
|
let startLine = Number(
|
|
@@ -15993,18 +16599,18 @@ function splitDiffIntoHunks(diffText) {
|
|
|
15993
16599
|
);
|
|
15994
16600
|
let offset = 0;
|
|
15995
16601
|
for (let k = i + 1; k < j; k++) {
|
|
15996
|
-
if (
|
|
16602
|
+
if (lines[k].startsWith("+")) {
|
|
15997
16603
|
startLine += offset;
|
|
15998
16604
|
break;
|
|
15999
16605
|
}
|
|
16000
|
-
if (!
|
|
16606
|
+
if (!lines[k].startsWith("-") && !lines[k].startsWith("\\")) offset++;
|
|
16001
16607
|
}
|
|
16002
16608
|
out.push({
|
|
16003
16609
|
header: header.trim(),
|
|
16004
16610
|
startLine,
|
|
16005
16611
|
// `git apply` requires the trailing newline; a patch that ends mid-line is
|
|
16006
16612
|
// rejected with `corrupt patch`.
|
|
16007
|
-
patch: `${[...fileHeader, ...
|
|
16613
|
+
patch: `${[...fileHeader, ...lines.slice(i, j)].join("\n").replace(/\n+$/, "")}
|
|
16008
16614
|
`
|
|
16009
16615
|
});
|
|
16010
16616
|
i = j;
|
|
@@ -16111,8 +16717,8 @@ __name(runControlMutant, "runControlMutant");
|
|
|
16111
16717
|
function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
16112
16718
|
const abs = join18(probeTree, mutant.file);
|
|
16113
16719
|
const original = readFileSync26(abs, "utf8");
|
|
16114
|
-
const
|
|
16115
|
-
if ((
|
|
16720
|
+
const lines = original.split("\n");
|
|
16721
|
+
if ((lines[mutant.line - 1] ?? "").trim() !== mutant.statement) {
|
|
16116
16722
|
return {
|
|
16117
16723
|
...mutant,
|
|
16118
16724
|
verdict: "inconclusive",
|
|
@@ -16121,12 +16727,12 @@ function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dep
|
|
|
16121
16727
|
}
|
|
16122
16728
|
const what = mutant.operator === "coalesce" ? "with its `?? fallback` dropped" : mutant.operator === "guard-true" ? "with its guard condition replaced by `true`" : mutant.operator === "term-drop" ? "with its `+ CONSTANT` term dropped" : "deleted";
|
|
16123
16729
|
if (mutant.mutated !== void 0) {
|
|
16124
|
-
|
|
16730
|
+
lines[mutant.line - 1] = mutant.mutated;
|
|
16125
16731
|
} else {
|
|
16126
|
-
|
|
16732
|
+
lines.splice(mutant.line - 1, 1);
|
|
16127
16733
|
}
|
|
16128
16734
|
try {
|
|
16129
|
-
writeFileSync24(abs,
|
|
16735
|
+
writeFileSync24(abs, lines.join("\n"), "utf8");
|
|
16130
16736
|
const { perFile } = runProbeSuite(
|
|
16131
16737
|
probeTree,
|
|
16132
16738
|
probes,
|
|
@@ -16643,11 +17249,11 @@ var PLAN_NAME_RE = /(test\s*plan|\btesting\b|how\s+(?:has\s+this|to)\s+(?:been\s
|
|
|
16643
17249
|
var HEADING_LINE_RE = /^(#{1,6})(?:[ \t](.*))?$/;
|
|
16644
17250
|
var BOLD_LINE_RE = /^\*\*([^*\n]+)\*\*:?\s*$/;
|
|
16645
17251
|
function extractTestPlanSection(body) {
|
|
16646
|
-
const
|
|
16647
|
-
const fenced = new Array(
|
|
17252
|
+
const lines = body.split(/\r?\n/);
|
|
17253
|
+
const fenced = new Array(lines.length).fill(false);
|
|
16648
17254
|
let fenceMarker = null;
|
|
16649
|
-
for (let i = 0; i <
|
|
16650
|
-
const m = /^\s*(```|~~~)/.exec(
|
|
17255
|
+
for (let i = 0; i < lines.length; i++) {
|
|
17256
|
+
const m = /^\s*(```|~~~)/.exec(lines[i]);
|
|
16651
17257
|
if (m) {
|
|
16652
17258
|
fenced[i] = true;
|
|
16653
17259
|
if (!fenceMarker) fenceMarker = m[1];
|
|
@@ -16656,27 +17262,27 @@ function extractTestPlanSection(body) {
|
|
|
16656
17262
|
}
|
|
16657
17263
|
fenced[i] = fenceMarker !== null;
|
|
16658
17264
|
}
|
|
16659
|
-
for (let i = 0; i <
|
|
17265
|
+
for (let i = 0; i < lines.length; i++) {
|
|
16660
17266
|
if (fenced[i]) continue;
|
|
16661
|
-
const hash = HEADING_LINE_RE.exec(
|
|
16662
|
-
const bold = BOLD_LINE_RE.exec(
|
|
17267
|
+
const hash = HEADING_LINE_RE.exec(lines[i]);
|
|
17268
|
+
const bold = BOLD_LINE_RE.exec(lines[i]);
|
|
16663
17269
|
const name = (hash?.[2] ?? bold?.[1])?.trim();
|
|
16664
17270
|
if (!name || !PLAN_NAME_RE.test(name)) continue;
|
|
16665
17271
|
const level = hash ? hash[1].length : Infinity;
|
|
16666
17272
|
const out = [];
|
|
16667
|
-
for (let j = i + 1; j <
|
|
17273
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
16668
17274
|
if (!fenced[j]) {
|
|
16669
|
-
const next = HEADING_LINE_RE.exec(
|
|
17275
|
+
const next = HEADING_LINE_RE.exec(lines[j]);
|
|
16670
17276
|
if (next && !next[2]?.trim()) {
|
|
16671
|
-
out.push(
|
|
17277
|
+
out.push(lines[j]);
|
|
16672
17278
|
continue;
|
|
16673
17279
|
}
|
|
16674
17280
|
if (next && next[1].length <= level) break;
|
|
16675
|
-
if (!hash && (next || BOLD_LINE_RE.test(
|
|
17281
|
+
if (!hash && (next || BOLD_LINE_RE.test(lines[j]))) break;
|
|
16676
17282
|
}
|
|
16677
|
-
out.push(
|
|
17283
|
+
out.push(lines[j]);
|
|
16678
17284
|
}
|
|
16679
|
-
return { heading:
|
|
17285
|
+
return { heading: lines[i].trim(), content: out.join("\n").trim() };
|
|
16680
17286
|
}
|
|
16681
17287
|
return null;
|
|
16682
17288
|
}
|
|
@@ -16918,9 +17524,21 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
16918
17524
|
} catch {
|
|
16919
17525
|
}
|
|
16920
17526
|
const defined = new Set(rootScripts);
|
|
16921
|
-
|
|
17527
|
+
const { packages, skipped } = readWorkspacePackages(worktree);
|
|
17528
|
+
for (const pkg of packages) {
|
|
16922
17529
|
for (const s of pkg.scripts) defined.add(s);
|
|
16923
17530
|
}
|
|
17531
|
+
const unreadable = [];
|
|
17532
|
+
for (const dir of skipped) {
|
|
17533
|
+
try {
|
|
17534
|
+
const pkg = JSON.parse(
|
|
17535
|
+
readFileSync27(join19(worktree, dir, "package.json"), "utf8")
|
|
17536
|
+
);
|
|
17537
|
+
for (const s of Object.keys(pkg?.scripts ?? {})) defined.add(s);
|
|
17538
|
+
} catch {
|
|
17539
|
+
unreadable.push(dir);
|
|
17540
|
+
}
|
|
17541
|
+
}
|
|
16924
17542
|
if (defined.size === 0) {
|
|
16925
17543
|
return {
|
|
16926
17544
|
kind: "command",
|
|
@@ -16929,12 +17547,31 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
16929
17547
|
note: "no package manifest could be read"
|
|
16930
17548
|
};
|
|
16931
17549
|
}
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
17550
|
+
if (defined.has(script)) {
|
|
17551
|
+
return {
|
|
17552
|
+
kind: "command",
|
|
17553
|
+
text,
|
|
17554
|
+
verdict: "reproduces",
|
|
17555
|
+
note: `\`${script}\` is a defined script`
|
|
17556
|
+
};
|
|
17557
|
+
}
|
|
17558
|
+
if (hasUnmodeledWorkspaceGlob(readWorkspaceGlobs(worktree))) {
|
|
17559
|
+
return {
|
|
17560
|
+
kind: "command",
|
|
17561
|
+
text,
|
|
17562
|
+
verdict: "unchecked",
|
|
17563
|
+
note: "the workspace globs use a shape this check does not model, so the script table may be incomplete"
|
|
17564
|
+
};
|
|
17565
|
+
}
|
|
17566
|
+
if (unreadable.length > 0) {
|
|
17567
|
+
return {
|
|
17568
|
+
kind: "command",
|
|
17569
|
+
text,
|
|
17570
|
+
verdict: "unchecked",
|
|
17571
|
+
note: `${unreadable.join(", ")} ${unreadable.length === 1 ? "has" : "have"} a package.json this check could not read, so the script table may be incomplete`
|
|
17572
|
+
};
|
|
17573
|
+
}
|
|
17574
|
+
return {
|
|
16938
17575
|
kind: "command",
|
|
16939
17576
|
text,
|
|
16940
17577
|
verdict: "contradicted",
|
|
@@ -17342,11 +17979,324 @@ var cleanupCommand = {
|
|
|
17342
17979
|
}, "handler")
|
|
17343
17980
|
};
|
|
17344
17981
|
|
|
17982
|
+
// packages/cli/src/commands/review/cost-ledger.ts
|
|
17983
|
+
init_esbuild_shims();
|
|
17984
|
+
import { mkdirSync as mkdirSync26, readFileSync as readFileSync29, statSync as statSync12, writeFileSync as writeFileSync26 } from "node:fs";
|
|
17985
|
+
import { dirname as dirname22, join as join21, resolve as resolve21 } from "node:path";
|
|
17986
|
+
function readUsage(file, floorMs) {
|
|
17987
|
+
const raw = readFileSync29(file, "utf8");
|
|
17988
|
+
const events = [];
|
|
17989
|
+
let launch = "";
|
|
17990
|
+
for (const line of raw.split("\n")) {
|
|
17991
|
+
if (line.trim() === "") continue;
|
|
17992
|
+
for (const rec of parseLineTolerant(line, file)) {
|
|
17993
|
+
if (launch === "" && rec["type"] === "user") {
|
|
17994
|
+
launch = textOf(rec);
|
|
17995
|
+
}
|
|
17996
|
+
if (rec["type"] !== "assistant") continue;
|
|
17997
|
+
const usage = rec["usageMetadata"];
|
|
17998
|
+
if (usage === null || typeof usage !== "object") continue;
|
|
17999
|
+
if (Array.isArray(usage)) continue;
|
|
18000
|
+
const u = usage;
|
|
18001
|
+
const ts = rec["timestamp"];
|
|
18002
|
+
if (typeof ts !== "string") continue;
|
|
18003
|
+
const tsMs = Date.parse(ts);
|
|
18004
|
+
if (!Number.isFinite(tsMs) || tsMs < floorMs) continue;
|
|
18005
|
+
const rawCount = /* @__PURE__ */ __name((k) => {
|
|
18006
|
+
const v = u[k];
|
|
18007
|
+
return typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : null;
|
|
18008
|
+
}, "rawCount");
|
|
18009
|
+
const rawPrompt = rawCount("promptTokenCount");
|
|
18010
|
+
const rawTotal = rawCount("totalTokenCount");
|
|
18011
|
+
const prompt = rawPrompt ?? 0;
|
|
18012
|
+
const candidates = rawCount("candidatesTokenCount") ?? 0;
|
|
18013
|
+
events.push({
|
|
18014
|
+
timestampMs: tsMs,
|
|
18015
|
+
timestamp: ts,
|
|
18016
|
+
input: prompt,
|
|
18017
|
+
// Cached is part of the prompt it is reported with; a broken proxy
|
|
18018
|
+
// can report the pair inverted, and the inversion would otherwise
|
|
18019
|
+
// land in BOTH the rendered share and the archived --out JSON.
|
|
18020
|
+
cached: Math.min(rawCount("cachedContentTokenCount") ?? 0, prompt),
|
|
18021
|
+
// `total − prompt` is the output including thinking under BOTH usage
|
|
18022
|
+
// conventions — reasoning inside candidates, and thoughts disjoint
|
|
18023
|
+
// from them — the same derivation tokenEstimation uses. Candidates
|
|
18024
|
+
// alone is the fallback when the provider reported no total; it stays
|
|
18025
|
+
// correct for the providers this CLI converts, which clamp thoughts
|
|
18026
|
+
// inside candidates. Derive it only when BOTH operands survived the
|
|
18027
|
+
// provider intact: a mixed-sign record coerces prompt to 0 while
|
|
18028
|
+
// keeping a positive total, and the subtraction would bill the
|
|
18029
|
+
// call's whole total as output.
|
|
18030
|
+
output: rawPrompt !== null && rawTotal !== null && rawTotal > rawPrompt ? rawTotal - rawPrompt : candidates,
|
|
18031
|
+
thoughts: rawCount("thoughtsTokenCount") ?? 0
|
|
18032
|
+
});
|
|
18033
|
+
}
|
|
18034
|
+
}
|
|
18035
|
+
return { events, launch };
|
|
18036
|
+
}
|
|
18037
|
+
__name(readUsage, "readUsage");
|
|
18038
|
+
var AUDIT_BRIEF_RE = /read_file\(file_path="[^"]*reverse-audit--chunk-(\d+)--round-(\d+)--[0-9a-f][^"]*\.brief\.md"\)/g;
|
|
18039
|
+
function labelOf(launch, fallback) {
|
|
18040
|
+
const nl = launch.indexOf("\n");
|
|
18041
|
+
const identity = nl === -1 ? launch : launch.slice(0, nl);
|
|
18042
|
+
if (!identity.startsWith("You are review agent `")) return fallback;
|
|
18043
|
+
let auditChunk = null;
|
|
18044
|
+
for (const m of launch.matchAll(AUDIT_BRIEF_RE)) auditChunk = m;
|
|
18045
|
+
if (auditChunk) {
|
|
18046
|
+
return `audit chunk ${auditChunk[1]} (round ${auditChunk[2]})`;
|
|
18047
|
+
}
|
|
18048
|
+
const role = /^You are review agent `([^`]+)`/.exec(identity);
|
|
18049
|
+
if (!role) return fallback;
|
|
18050
|
+
const round = /\(round (\d+)\)/.exec(identity);
|
|
18051
|
+
const chunk2 = CHUNK_RE.exec(role[1]);
|
|
18052
|
+
if (chunk2) return `chunk ${chunk2[1]}`;
|
|
18053
|
+
if (round) {
|
|
18054
|
+
return `agent ${role[1]} (round ${round[1]})`;
|
|
18055
|
+
}
|
|
18056
|
+
const file = /Your file: `([^`]+)`/.exec(identity);
|
|
18057
|
+
if (file) return `agent ${role[1]} (${file[1]})`;
|
|
18058
|
+
return `agent ${role[1]}`;
|
|
18059
|
+
}
|
|
18060
|
+
__name(labelOf, "labelOf");
|
|
18061
|
+
function foldEvents(id, label2, events) {
|
|
18062
|
+
const s = {
|
|
18063
|
+
id,
|
|
18064
|
+
label: label2,
|
|
18065
|
+
calls: 0,
|
|
18066
|
+
inputTokens: 0,
|
|
18067
|
+
cachedTokens: 0,
|
|
18068
|
+
outputTokens: 0,
|
|
18069
|
+
thoughtsTokens: 0,
|
|
18070
|
+
firstAt: null,
|
|
18071
|
+
lastAt: null
|
|
18072
|
+
};
|
|
18073
|
+
let firstMs = Number.POSITIVE_INFINITY;
|
|
18074
|
+
let lastMs = Number.NEGATIVE_INFINITY;
|
|
18075
|
+
for (const e of events) {
|
|
18076
|
+
s.calls += 1;
|
|
18077
|
+
s.inputTokens += e.input;
|
|
18078
|
+
s.cachedTokens += e.cached;
|
|
18079
|
+
s.outputTokens += e.output;
|
|
18080
|
+
s.thoughtsTokens += e.thoughts;
|
|
18081
|
+
if (e.timestampMs < firstMs) {
|
|
18082
|
+
firstMs = e.timestampMs;
|
|
18083
|
+
s.firstAt = e.timestamp;
|
|
18084
|
+
}
|
|
18085
|
+
if (e.timestampMs > lastMs) {
|
|
18086
|
+
lastMs = e.timestampMs;
|
|
18087
|
+
s.lastAt = e.timestamp;
|
|
18088
|
+
}
|
|
18089
|
+
}
|
|
18090
|
+
return s;
|
|
18091
|
+
}
|
|
18092
|
+
__name(foldEvents, "foldEvents");
|
|
18093
|
+
function human(n) {
|
|
18094
|
+
if (n >= 9995e5) return `${(n / 1e9).toFixed(1)}B`;
|
|
18095
|
+
if (n >= 999500) return `${(n / 1e6).toFixed(1)}M`;
|
|
18096
|
+
if (n >= 1e3) return `${Math.round(n / 1e3)}k`;
|
|
18097
|
+
return String(n);
|
|
18098
|
+
}
|
|
18099
|
+
__name(human, "human");
|
|
18100
|
+
var plural = /* @__PURE__ */ __name((n, word) => `${n} ${word}${n === 1 ? "" : "s"}`, "plural");
|
|
18101
|
+
function planFloorMs(planPath) {
|
|
18102
|
+
let raw;
|
|
18103
|
+
let floorMs;
|
|
18104
|
+
try {
|
|
18105
|
+
raw = readFileSync29(planPath, "utf8");
|
|
18106
|
+
floorMs = statSync12(planPath).mtimeMs;
|
|
18107
|
+
} catch (err) {
|
|
18108
|
+
throw new Error(
|
|
18109
|
+
`could not read the plan report ${planPath}: ${err.message}`
|
|
18110
|
+
);
|
|
18111
|
+
}
|
|
18112
|
+
let parsed;
|
|
18113
|
+
try {
|
|
18114
|
+
parsed = JSON.parse(raw);
|
|
18115
|
+
} catch {
|
|
18116
|
+
parsed = null;
|
|
18117
|
+
}
|
|
18118
|
+
const plan = parsed !== null && typeof parsed === "object" ? parsed : void 0;
|
|
18119
|
+
if (typeof plan?.["diffLines"] !== "number" || !Array.isArray(plan?.["chunks"])) {
|
|
18120
|
+
throw new Error(`not a review plan report: ${planPath}`);
|
|
18121
|
+
}
|
|
18122
|
+
return floorMs;
|
|
18123
|
+
}
|
|
18124
|
+
__name(planFloorMs, "planFloorMs");
|
|
18125
|
+
function computeLedger(planPath, env = process.env) {
|
|
18126
|
+
const floorMs = planFloorMs(planPath);
|
|
18127
|
+
const { projectDir, sessionId, dir } = transcriptPaths(env);
|
|
18128
|
+
const chatFile = join21(projectDir, "chats", `${sessionId}.jsonl`);
|
|
18129
|
+
let mainEvents;
|
|
18130
|
+
try {
|
|
18131
|
+
mainEvents = readUsage(chatFile, floorMs).events;
|
|
18132
|
+
} catch (err) {
|
|
18133
|
+
throw new Error(
|
|
18134
|
+
`could not read the chat transcript ${chatFile}: ${err.message}`
|
|
18135
|
+
);
|
|
18136
|
+
}
|
|
18137
|
+
const main = mainEvents.length > 0 ? foldEvents("main", "main loop", mainEvents) : null;
|
|
18138
|
+
let files;
|
|
18139
|
+
try {
|
|
18140
|
+
files = listAgentTranscriptFiles(dir);
|
|
18141
|
+
} catch (err) {
|
|
18142
|
+
if (err.code === "ENOENT") {
|
|
18143
|
+
files = [];
|
|
18144
|
+
} else {
|
|
18145
|
+
throw new Error(
|
|
18146
|
+
`could not list the subagent transcripts at ${dir}: ${err.message}`
|
|
18147
|
+
);
|
|
18148
|
+
}
|
|
18149
|
+
}
|
|
18150
|
+
const agents = [];
|
|
18151
|
+
const agentEvents = [];
|
|
18152
|
+
for (const f of files) {
|
|
18153
|
+
const full = join21(dir, f);
|
|
18154
|
+
let mtimeMs;
|
|
18155
|
+
try {
|
|
18156
|
+
mtimeMs = statSync12(full).mtimeMs;
|
|
18157
|
+
} catch {
|
|
18158
|
+
continue;
|
|
18159
|
+
}
|
|
18160
|
+
if (mtimeMs < floorMs) continue;
|
|
18161
|
+
let read;
|
|
18162
|
+
try {
|
|
18163
|
+
read = readUsage(full, floorMs);
|
|
18164
|
+
} catch {
|
|
18165
|
+
continue;
|
|
18166
|
+
}
|
|
18167
|
+
if (read.events.length === 0) continue;
|
|
18168
|
+
const id = f.replace(/^agent-/, "").replace(/\.jsonl$/, "");
|
|
18169
|
+
agents.push(foldEvents(id, labelOf(read.launch, id), read.events));
|
|
18170
|
+
agentEvents.push(...read.events);
|
|
18171
|
+
}
|
|
18172
|
+
agents.sort((a, b) => b.inputTokens - a.inputTokens);
|
|
18173
|
+
if (mainEvents.length === 0) {
|
|
18174
|
+
throw new Error(
|
|
18175
|
+
`could not read the chat transcript ${chatFile}: no main-loop usage records at or after the plan`
|
|
18176
|
+
);
|
|
18177
|
+
}
|
|
18178
|
+
const totals = foldEvents("totals", "totals", [
|
|
18179
|
+
...mainEvents,
|
|
18180
|
+
...agentEvents
|
|
18181
|
+
]);
|
|
18182
|
+
const wallSeconds = totals.firstAt !== null && totals.lastAt !== null ? Math.max(
|
|
18183
|
+
0,
|
|
18184
|
+
Math.round(
|
|
18185
|
+
(Date.parse(totals.lastAt) - Date.parse(totals.firstAt)) / 1e3
|
|
18186
|
+
)
|
|
18187
|
+
) : 0;
|
|
18188
|
+
const { id: _i, label: _l, ...totalsRest } = totals;
|
|
18189
|
+
return { totals: { ...totalsRest, wallSeconds }, main, agents };
|
|
18190
|
+
}
|
|
18191
|
+
__name(computeLedger, "computeLedger");
|
|
18192
|
+
function renderLedger(ledger) {
|
|
18193
|
+
const t2 = ledger.totals;
|
|
18194
|
+
const cachedPct = t2.inputTokens > 0 ? Math.round(t2.cachedTokens / t2.inputTokens * 100) : 0;
|
|
18195
|
+
const lines = [];
|
|
18196
|
+
lines.push(
|
|
18197
|
+
`Cost ledger: ${plural(t2.calls, "model call")} \xB7 ${human(t2.inputTokens)} input (${cachedPct}% cached) \xB7 ${human(t2.outputTokens)} output (${human(t2.thoughtsTokens)} thinking) \xB7 ${Math.round(t2.wallSeconds / 60)} min wall`
|
|
18198
|
+
);
|
|
18199
|
+
if (ledger.main !== null) {
|
|
18200
|
+
const m = ledger.main;
|
|
18201
|
+
lines.push(
|
|
18202
|
+
` main loop: ${plural(m.calls, "call")} \xB7 ${human(m.inputTokens)} in \xB7 ${human(m.outputTokens)} out`
|
|
18203
|
+
);
|
|
18204
|
+
}
|
|
18205
|
+
if (ledger.agents.length > 0) {
|
|
18206
|
+
const rows = [];
|
|
18207
|
+
for (const a of ledger.agents) {
|
|
18208
|
+
const row = rows.find((r) => r.label === a.label);
|
|
18209
|
+
if (row) {
|
|
18210
|
+
row.calls += a.calls;
|
|
18211
|
+
row.inputTokens += a.inputTokens;
|
|
18212
|
+
row.outputTokens += a.outputTokens;
|
|
18213
|
+
row.count += 1;
|
|
18214
|
+
} else {
|
|
18215
|
+
rows.push({
|
|
18216
|
+
label: a.label,
|
|
18217
|
+
calls: a.calls,
|
|
18218
|
+
inputTokens: a.inputTokens,
|
|
18219
|
+
outputTokens: a.outputTokens,
|
|
18220
|
+
count: 1
|
|
18221
|
+
});
|
|
18222
|
+
}
|
|
18223
|
+
}
|
|
18224
|
+
rows.sort((a, b) => b.inputTokens - a.inputTokens);
|
|
18225
|
+
lines.push(` agent runs: ${ledger.agents.length}`);
|
|
18226
|
+
for (const r of rows.slice(0, 8)) {
|
|
18227
|
+
const label2 = r.count > 1 ? `${r.label} (\xD7${r.count})` : r.label;
|
|
18228
|
+
lines.push(
|
|
18229
|
+
` ${label2}: ${plural(r.calls, "call")} \xB7 ${human(r.inputTokens)} in \xB7 ${human(r.outputTokens)} out`
|
|
18230
|
+
);
|
|
18231
|
+
}
|
|
18232
|
+
if (rows.length > 8) {
|
|
18233
|
+
const rest = rows.slice(8);
|
|
18234
|
+
const restIn = rest.reduce((n, r) => n + r.inputTokens, 0);
|
|
18235
|
+
const restAgents = rest.reduce((n, r) => n + r.count, 0);
|
|
18236
|
+
lines.push(
|
|
18237
|
+
` \u2026and ${plural(restAgents, "more agent")} \xB7 ${human(restIn)} in combined`
|
|
18238
|
+
);
|
|
18239
|
+
}
|
|
18240
|
+
}
|
|
18241
|
+
return lines.join("\n");
|
|
18242
|
+
}
|
|
18243
|
+
__name(renderLedger, "renderLedger");
|
|
18244
|
+
function runCostLedger(args) {
|
|
18245
|
+
const stdoutErrorHandler = /* @__PURE__ */ __name((err) => {
|
|
18246
|
+
if (err.code === "EPIPE") process.stdout.destroy();
|
|
18247
|
+
}, "stdoutErrorHandler");
|
|
18248
|
+
const stderrErrorHandler = /* @__PURE__ */ __name((err) => {
|
|
18249
|
+
if (err.code === "EPIPE") process.stderr.destroy();
|
|
18250
|
+
}, "stderrErrorHandler");
|
|
18251
|
+
process.stdout.on("error", stdoutErrorHandler);
|
|
18252
|
+
process.stderr.on("error", stderrErrorHandler);
|
|
18253
|
+
try {
|
|
18254
|
+
let ledger;
|
|
18255
|
+
try {
|
|
18256
|
+
ledger = computeLedger(args.plan, process.env);
|
|
18257
|
+
} catch (err) {
|
|
18258
|
+
const why = err instanceof TranscriptsUnavailableError ? err.message : err.message;
|
|
18259
|
+
writeStderrLineSafe(`cost-ledger unavailable \u2014 ${why}`);
|
|
18260
|
+
return;
|
|
18261
|
+
}
|
|
18262
|
+
if (args.out !== void 0 && args.out.length > 0) {
|
|
18263
|
+
try {
|
|
18264
|
+
mkdirSync26(dirname22(resolve21(args.out)), { recursive: true });
|
|
18265
|
+
writeFileSync26(args.out, JSON.stringify(ledger, null, 2));
|
|
18266
|
+
} catch (err) {
|
|
18267
|
+
writeStderrLineSafe(
|
|
18268
|
+
`cost-ledger: could not write ${args.out} \u2014 ${err.message}`
|
|
18269
|
+
);
|
|
18270
|
+
}
|
|
18271
|
+
}
|
|
18272
|
+
writeStdoutLineSafe(renderLedger(ledger));
|
|
18273
|
+
} finally {
|
|
18274
|
+
process.stdout.removeListener("error", stdoutErrorHandler);
|
|
18275
|
+
process.stderr.removeListener("error", stderrErrorHandler);
|
|
18276
|
+
}
|
|
18277
|
+
}
|
|
18278
|
+
__name(runCostLedger, "runCostLedger");
|
|
18279
|
+
var costLedgerCommand = {
|
|
18280
|
+
command: "cost-ledger",
|
|
18281
|
+
describe: "Aggregate this review's model-call cost from the harness's usage records",
|
|
18282
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.option("plan", {
|
|
18283
|
+
type: "string",
|
|
18284
|
+
demandOption: true,
|
|
18285
|
+
describe: "The plan report from Step 1 \u2014 its mtime marks the review start"
|
|
18286
|
+
}).option("out", {
|
|
18287
|
+
type: "string",
|
|
18288
|
+
describe: "Also write the full ledger as JSON to this path"
|
|
18289
|
+
}), "builder"),
|
|
18290
|
+
handler: /* @__PURE__ */ __name((args) => {
|
|
18291
|
+
runCostLedger(args);
|
|
18292
|
+
}, "handler")
|
|
18293
|
+
};
|
|
18294
|
+
|
|
17345
18295
|
// packages/cli/src/commands/review/run.ts
|
|
17346
18296
|
init_esbuild_shims();
|
|
17347
18297
|
import { spawn, execFileSync as execFileSync6 } from "node:child_process";
|
|
17348
|
-
import { readdirSync as readdirSync7, readFileSync as
|
|
17349
|
-
import { dirname as
|
|
18298
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync30, realpathSync as realpathSync3, statSync as statSync13 } from "node:fs";
|
|
18299
|
+
import { dirname as dirname23, join as join22, resolve as resolve22 } from "node:path";
|
|
17350
18300
|
var COMPOSED_PATTERN = /^qwen-review-.*composed\.json$/;
|
|
17351
18301
|
var COMPOSED_POLL_MS = 250;
|
|
17352
18302
|
var SIGNAL_EXIT_CODES = {
|
|
@@ -17380,10 +18330,10 @@ function newestArtifactSince(dir, pattern, startMs) {
|
|
|
17380
18330
|
}
|
|
17381
18331
|
for (const name of names) {
|
|
17382
18332
|
if (!pattern.test(name)) continue;
|
|
17383
|
-
const path3 =
|
|
18333
|
+
const path3 = join22(dir, name);
|
|
17384
18334
|
let mtime;
|
|
17385
18335
|
try {
|
|
17386
|
-
mtime =
|
|
18336
|
+
mtime = statSync13(path3).mtimeMs;
|
|
17387
18337
|
} catch {
|
|
17388
18338
|
continue;
|
|
17389
18339
|
}
|
|
@@ -17401,7 +18351,7 @@ function exitCodeFor(completed, event2, failOn) {
|
|
|
17401
18351
|
__name(exitCodeFor, "exitCodeFor");
|
|
17402
18352
|
function readComposed(path3) {
|
|
17403
18353
|
try {
|
|
17404
|
-
const parsed = JSON.parse(
|
|
18354
|
+
const parsed = JSON.parse(readFileSync30(path3, "utf8"));
|
|
17405
18355
|
return typeof parsed.event === "string" ? parsed : null;
|
|
17406
18356
|
} catch {
|
|
17407
18357
|
return null;
|
|
@@ -17432,7 +18382,7 @@ function childEnv() {
|
|
|
17432
18382
|
return env;
|
|
17433
18383
|
}
|
|
17434
18384
|
try {
|
|
17435
|
-
if (
|
|
18385
|
+
if (dirname23(realpathSync3(inherited)) === dirname23(realpathSync3(ownEntry))) {
|
|
17436
18386
|
return env;
|
|
17437
18387
|
}
|
|
17438
18388
|
} catch {
|
|
@@ -17554,8 +18504,8 @@ async function runReview(args) {
|
|
|
17554
18504
|
downgraded: composed?.downgraded ?? false,
|
|
17555
18505
|
downgradedFrom: composed?.downgradedFrom ?? null,
|
|
17556
18506
|
remediation: composed?.remediation ?? [],
|
|
17557
|
-
composedPath: composedPath ?
|
|
17558
|
-
reportPath: reportPath ?
|
|
18507
|
+
composedPath: composedPath ? resolve22(composedPath) : null,
|
|
18508
|
+
reportPath: reportPath ? resolve22(reportPath) : null,
|
|
17559
18509
|
childExitCode,
|
|
17560
18510
|
childSignal,
|
|
17561
18511
|
timedOut,
|
|
@@ -17569,7 +18519,7 @@ async function runReview(args) {
|
|
|
17569
18519
|
writeStdoutLine(result.verdictLine ?? `Event: ${result.event}`);
|
|
17570
18520
|
if (result.reportPath) writeStdoutLine(`Report: ${result.reportPath}`);
|
|
17571
18521
|
} else {
|
|
17572
|
-
const detail = composedPath !== null ? `a composed verdict was found at ${
|
|
18522
|
+
const detail = composedPath !== null ? `a composed verdict was found at ${resolve22(composedPath)} but could not be parsed` : "no composed verdict was produced";
|
|
17573
18523
|
writeStdoutLine(
|
|
17574
18524
|
timedOut ? "Review did not complete: timed out." : `Review did not complete: ${detail}${childExitCode !== null ? ` (CLI exit ${childExitCode})` : ""}${childSignal !== null ? ` (killed by ${childSignal})` : ""}.`
|
|
17575
18525
|
);
|
|
@@ -17637,22 +18587,22 @@ init_esbuild_shims();
|
|
|
17637
18587
|
import {
|
|
17638
18588
|
existsSync as existsSync14,
|
|
17639
18589
|
lstatSync as lstatSync5,
|
|
17640
|
-
mkdirSync as
|
|
17641
|
-
readFileSync as
|
|
17642
|
-
statSync as
|
|
18590
|
+
mkdirSync as mkdirSync27,
|
|
18591
|
+
readFileSync as readFileSync31,
|
|
18592
|
+
statSync as statSync14
|
|
17643
18593
|
} from "node:fs";
|
|
17644
18594
|
import {
|
|
17645
|
-
dirname as
|
|
18595
|
+
dirname as dirname24,
|
|
17646
18596
|
isAbsolute as isAbsolute4,
|
|
17647
|
-
join as
|
|
18597
|
+
join as join23,
|
|
17648
18598
|
relative as relative3,
|
|
17649
|
-
resolve as
|
|
18599
|
+
resolve as resolve23,
|
|
17650
18600
|
sep as sep4,
|
|
17651
18601
|
toNamespacedPath
|
|
17652
18602
|
} from "node:path";
|
|
17653
18603
|
import { isDeepStrictEqual } from "node:util";
|
|
17654
18604
|
function workspaceRoot() {
|
|
17655
|
-
return
|
|
18605
|
+
return resolve23(process.env["QWEN_CODE_PROJECT_DIR"] ?? process.cwd());
|
|
17656
18606
|
}
|
|
17657
18607
|
__name(workspaceRoot, "workspaceRoot");
|
|
17658
18608
|
function isWithin(parent, child) {
|
|
@@ -17661,7 +18611,7 @@ function isWithin(parent, child) {
|
|
|
17661
18611
|
}
|
|
17662
18612
|
__name(isWithin, "isWithin");
|
|
17663
18613
|
function workspacePath(root, value, label2) {
|
|
17664
|
-
const absolute =
|
|
18614
|
+
const absolute = resolve23(root, value);
|
|
17665
18615
|
if (!isWithin(root, absolute)) {
|
|
17666
18616
|
throw new Error(
|
|
17667
18617
|
`${label2} must be inside the workspace: ${JSON.stringify(value)}.`
|
|
@@ -17674,7 +18624,7 @@ function rejectSymlinkPath(root, path3, label2) {
|
|
|
17674
18624
|
const rel = relative3(root, path3);
|
|
17675
18625
|
let current = root;
|
|
17676
18626
|
for (const segment of rel.split(sep4)) {
|
|
17677
|
-
current =
|
|
18627
|
+
current = join23(current, segment);
|
|
17678
18628
|
if (existsSync14(current) && lstatSync5(current).isSymbolicLink()) {
|
|
17679
18629
|
throw new Error(`${label2} must not traverse a symbolic link.`);
|
|
17680
18630
|
}
|
|
@@ -17684,14 +18634,14 @@ __name(rejectSymlinkPath, "rejectSymlinkPath");
|
|
|
17684
18634
|
function sameFile(left, right) {
|
|
17685
18635
|
if (left === right) return true;
|
|
17686
18636
|
if (!existsSync14(left) || !existsSync14(right)) return false;
|
|
17687
|
-
const leftStat =
|
|
17688
|
-
const rightStat =
|
|
18637
|
+
const leftStat = statSync14(left);
|
|
18638
|
+
const rightStat = statSync14(right);
|
|
17689
18639
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
17690
18640
|
}
|
|
17691
18641
|
__name(sameFile, "sameFile");
|
|
17692
18642
|
function readText(path3, label2) {
|
|
17693
18643
|
try {
|
|
17694
|
-
return
|
|
18644
|
+
return readFileSync31(path3, "utf8");
|
|
17695
18645
|
} catch (error) {
|
|
17696
18646
|
throw new Error(
|
|
17697
18647
|
`Could not read the ${label2} file at ${JSON.stringify(path3)}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -17817,7 +18767,7 @@ function saveReviewArtifact(args) {
|
|
|
17817
18767
|
const composedPath = workspacePath(root, args.composed, "Composed input");
|
|
17818
18768
|
const reportPath = workspacePath(root, args.report, "Markdown report");
|
|
17819
18769
|
const outputPath = workspacePath(root, args.out, "Output");
|
|
17820
|
-
const reviewsRoot =
|
|
18770
|
+
const reviewsRoot = resolve23(root, REVIEWS_DIR);
|
|
17821
18771
|
if (!isWithin(reviewsRoot, reportPath) || reportPath === reviewsRoot) {
|
|
17822
18772
|
throw new Error(
|
|
17823
18773
|
`Markdown report must be a file under ${JSON.stringify(REVIEWS_DIR)}: ${JSON.stringify(args.report)}.`
|
|
@@ -17858,7 +18808,7 @@ function saveReviewArtifact(args) {
|
|
|
17858
18808
|
const verdict = validateVerdict(readJson2(composedPath, "composed verdict"));
|
|
17859
18809
|
let reportIsFile;
|
|
17860
18810
|
try {
|
|
17861
|
-
reportIsFile =
|
|
18811
|
+
reportIsFile = statSync14(reportPath).isFile();
|
|
17862
18812
|
} catch {
|
|
17863
18813
|
}
|
|
17864
18814
|
if (reportIsFile === false) {
|
|
@@ -17878,7 +18828,7 @@ function saveReviewArtifact(args) {
|
|
|
17878
18828
|
outcomesRecorded: findings.outcomesRecorded,
|
|
17879
18829
|
markdownReportPath
|
|
17880
18830
|
};
|
|
17881
|
-
|
|
18831
|
+
mkdirSync27(dirname24(outputPath), { recursive: true });
|
|
17882
18832
|
atomicWriteFileSync(
|
|
17883
18833
|
toNamespacedPath(outputPath),
|
|
17884
18834
|
`${JSON.stringify(document, null, 2)}
|
|
@@ -17931,9 +18881,9 @@ var saveArtifactCommand = {
|
|
|
17931
18881
|
var reviewCommand = {
|
|
17932
18882
|
command: "review",
|
|
17933
18883
|
describe: "Run a review non-interactively (`run`), plus the internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)",
|
|
17934
|
-
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(saveArtifactCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
18884
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(costLedgerCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(saveArtifactCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
17935
18885
|
1,
|
|
17936
|
-
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, save-artifact, submit, or cleanup."
|
|
18886
|
+
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, cost-ledger, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, save-artifact, submit, or cleanup."
|
|
17937
18887
|
).version(false), "builder"),
|
|
17938
18888
|
handler: /* @__PURE__ */ __name(() => {
|
|
17939
18889
|
}, "handler")
|
|
@@ -18133,11 +19083,11 @@ var updateCommand3 = {
|
|
|
18133
19083
|
stdioHelpers,
|
|
18134
19084
|
{ updateEventEmitter }
|
|
18135
19085
|
] = await Promise.all([
|
|
18136
|
-
import("./settings-
|
|
18137
|
-
import("./updateCheck-
|
|
18138
|
-
import("./installationInfo-
|
|
18139
|
-
import("./standalone-update-
|
|
18140
|
-
import("./stdioHelpers-
|
|
19086
|
+
import("./settings-AI2BTBOZ.js"),
|
|
19087
|
+
import("./updateCheck-UOVZSTP7.js"),
|
|
19088
|
+
import("./installationInfo-PO4Z3ES7.js"),
|
|
19089
|
+
import("./standalone-update-WVINHRNS.js"),
|
|
19090
|
+
import("./stdioHelpers-7A2EE64Z.js"),
|
|
18141
19091
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
18142
19092
|
]);
|
|
18143
19093
|
const { formatUpdateInstructions, getInstallationInfo } = installationInfoModule;
|
|
@@ -19303,7 +20253,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
19303
20253
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
19304
20254
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
19305
20255
|
terminalImageRenderSupportProvider: interactive ? async () => {
|
|
19306
|
-
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-
|
|
20256
|
+
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-II74TFVW.js");
|
|
19307
20257
|
return getTerminalImageRenderSupport();
|
|
19308
20258
|
} : void 0,
|
|
19309
20259
|
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|