@qwen-code/qwen-code 0.21.7 → 0.21.8-nightly.20260810.55e20db328
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bundled/qc-helper/docs/configuration/settings.md +73 -59
- package/bundled/qc-helper/docs/extension/introduction.md +15 -1
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +40 -2
- package/bundled/qc-helper/docs/features/channels/feishu.md +13 -2
- package/bundled/qc-helper/docs/features/channels/github.md +13 -11
- package/bundled/qc-helper/docs/features/channels/gitlab.md +13 -11
- package/bundled/qc-helper/docs/features/channels/overview.md +49 -31
- package/bundled/qc-helper/docs/features/channels/plugins.md +2 -2
- package/bundled/qc-helper/docs/features/channels/qqbot.md +4 -2
- package/bundled/qc-helper/docs/features/channels/telegram.md +4 -2
- package/bundled/qc-helper/docs/features/channels/wecom.md +1 -1
- package/bundled/qc-helper/docs/features/code-review.md +4 -0
- package/bundled/qc-helper/docs/features/commands.md +1 -1
- package/bundled/qc-helper/docs/features/hooks.md +52 -0
- package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +10 -5
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
- package/bundled/review/SKILL.md +32 -5
- package/chunks/{MaxSizedBox-ANWZBPTS.js → MaxSizedBox-A52T4GEU.js} +29 -25
- package/chunks/{StandaloneSessionPicker-XKS3VU3A.js → StandaloneSessionPicker-4J654SOB.js} +48 -44
- package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
- package/chunks/{acpAgent-KUAZ3GCZ.js → acpAgent-65AM4AOR.js} +1833 -843
- package/chunks/{agent-T6PTGX5R.js → agent-SVQ7U7NJ.js} +28 -24
- package/chunks/{agent-headless-PR7YCB7S.js → agent-headless-XXGY2SQO.js} +28 -24
- package/chunks/{artifact-tool-U4VOZIK5.js → artifact-tool-N652YE4L.js} +1 -1
- package/chunks/{askUserQuestion-XOBQLPFA.js → askUserQuestion-ONW74PKJ.js} +1 -1
- package/chunks/{bridge-NU6YEEHK.js → bridge-Y32B5S3G.js} +34 -30
- package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
- package/chunks/{channel-management-service-FSQ7SHYI.js → channel-management-service-PHELKOW2.js} +19 -10
- package/chunks/{channel-settings-store-35VQVUVV.js → channel-settings-store-OW43U6VB.js} +36 -32
- package/chunks/{channel-worker-group-JWQK224X.js → channel-worker-group-MSHT6CWR.js} +7 -7
- package/chunks/{channel-worker-manager-77E3OXRQ.js → channel-worker-manager-XXD3GDSK.js} +7 -7
- package/chunks/{channel-worker-supervisor-62YWUGP2.js → channel-worker-supervisor-IVSDIMI4.js} +4 -4
- package/chunks/{chunk-HYRDKNUY.js → chunk-2545EHZR.js} +1 -1
- package/chunks/{chunk-SPMY6CX6.js → chunk-2ASQDZSJ.js} +3 -3
- package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
- package/chunks/{chunk-CNIID3TV.js → chunk-2UUMVNYT.js} +1 -1
- package/chunks/{chunk-KXSDEOFU.js → chunk-3KJQZEN3.js} +1 -1
- package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
- package/chunks/{chunk-Y7E5LNLO.js → chunk-47ZUMGGY.js} +2634 -2114
- package/chunks/{chunk-LA7YLSR6.js → chunk-4EOURKA4.js} +839 -153
- package/chunks/chunk-4JRM2BSM.js +48 -0
- package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
- package/chunks/{chunk-L4N6TIP7.js → chunk-4TRQPFDP.js} +4 -2
- package/chunks/{chunk-6XJMFJ4D.js → chunk-5WZL724W.js} +177 -120
- package/chunks/{chunk-23RZCH76.js → chunk-5ZTS3OQ3.js} +3 -3
- package/chunks/{chunk-VWOVHOTT.js → chunk-67EWJE77.js} +1 -1
- package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
- package/chunks/{chunk-CXE7E23H.js → chunk-6Q5ABMTU.js} +45 -17
- package/chunks/{chunk-NG2R4N5O.js → chunk-6ZRFAKXK.js} +1 -1
- package/chunks/{chunk-RERATVSK.js → chunk-7XX5IBXL.js} +145 -10
- package/chunks/{chunk-S7CV4KO6.js → chunk-AKJQSWV4.js} +4 -4
- package/chunks/{chunk-5KH532V7.js → chunk-AUWN7BAG.js} +1 -1
- package/chunks/{chunk-DBOFL3LQ.js → chunk-BL65MO72.js} +10 -10
- package/chunks/{chunk-AKA24BGO.js → chunk-BT6GQIEJ.js} +1 -1
- package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
- package/chunks/{chunk-2M5N3DHY.js → chunk-CMOBWHWW.js} +1 -1
- package/chunks/chunk-COBO5EBO.js +135 -0
- package/chunks/chunk-CPG6P4GG.js +82 -0
- package/chunks/{chunk-3NB7TSE2.js → chunk-D2D7J3EW.js} +1 -1
- package/chunks/{chunk-NLREQJFK.js → chunk-DA4HRSBW.js} +15 -0
- package/chunks/{chunk-RNVQB725.js → chunk-DPMJLKUP.js} +2 -2
- package/chunks/{chunk-DIEFUBV6.js → chunk-DX3RGJMS.js} +218 -37
- package/chunks/{chunk-33ACCIIY.js → chunk-DZUO626D.js} +1 -1
- package/chunks/chunk-E2FPSSKP.js +244 -0
- package/chunks/{chunk-72LNFGUY.js → chunk-E2N554HK.js} +3 -3
- package/chunks/{chunk-6EOI4HOK.js → chunk-E2T7FLDU.js} +12 -17
- package/chunks/{chunk-EUQTXRKZ.js → chunk-EISUQQPS.js} +6 -6
- package/chunks/{chunk-H2UQ2M5Z.js → chunk-EUVOKP6Y.js} +96 -22
- package/chunks/{chunk-RMH5OWLD.js → chunk-F3II4BTZ.js} +1 -1
- package/chunks/{chunk-P3LEG54R.js → chunk-F6TUUA2U.js} +3 -3
- package/chunks/chunk-F6WFNA7U.js +22 -0
- package/chunks/{chunk-RZHU3ILK.js → chunk-FAD7OC7V.js} +4 -4
- package/chunks/{chunk-OMKQH5C5.js → chunk-FWWQIFDT.js} +6 -23
- package/chunks/{chunk-TLV2IMHR.js → chunk-FYB4GIDW.js} +3 -3
- package/chunks/{chunk-ZJ3VGYHK.js → chunk-GY24H6IA.js} +40 -22
- package/chunks/{chunk-P2AJ7FTI.js → chunk-H4JC7LZX.js} +1 -1
- package/chunks/{chunk-55LYDVPU.js → chunk-HDYQYYWB.js} +1 -1
- package/chunks/{chunk-PQBHU2IA.js → chunk-HKI3KHAO.js} +11 -11
- package/chunks/{chunk-Y4NGLFGJ.js → chunk-HUWENAHO.js} +1 -1
- package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
- package/chunks/{chunk-CSZEXZBE.js → chunk-HWXGX534.js} +3 -3
- package/chunks/{chunk-E33LOKRA.js → chunk-I5VM3SKY.js} +22 -5
- package/chunks/{chunk-LZC3B5N2.js → chunk-IA7TGCN2.js} +2 -2
- package/chunks/{chunk-RGSBTHSU.js → chunk-KMS57JDD.js} +137 -7
- package/chunks/{chunk-VOARQPTA.js → chunk-KP25NJNM.js} +65 -21
- package/chunks/{chunk-6M26GBKX.js → chunk-L2AFWWJE.js} +42 -3
- package/chunks/{chunk-ZXU5UHMI.js → chunk-LHEC5V6G.js} +2 -2
- package/chunks/{chunk-J26HHFI5.js → chunk-LP2QGNSP.js} +32 -2
- package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
- package/chunks/{chunk-MKVZE4ZJ.js → chunk-MFDYOYZZ.js} +3 -2
- package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
- package/chunks/{chunk-YHEEE624.js → chunk-NV3F44FL.js} +7 -3
- package/chunks/{chunk-6GONZVLS.js → chunk-NZMXUSKS.js} +1 -1
- package/chunks/{chunk-HQB2KUAN.js → chunk-O277O7U6.js} +1 -1
- package/chunks/{chunk-Y4EWSQF7.js → chunk-OBP6QWD5.js} +2 -2
- package/chunks/{chunk-CYR3HI5X.js → chunk-OQTXYMKW.js} +2 -2
- package/chunks/{chunk-TYKC75AX.js → chunk-OR6R3IUW.js} +2 -2
- package/chunks/{chunk-TRLYP7OF.js → chunk-OSVH4SMN.js} +16 -141
- package/chunks/{chunk-FPM27XN4.js → chunk-OW2BWT2P.js} +4 -4
- package/chunks/{chunk-TDXGKHDN.js → chunk-P5ULXPK5.js} +2 -2
- package/chunks/{chunk-24ER7UV4.js → chunk-PBRVUF5B.js} +1 -1
- package/chunks/{chunk-LKRMNRSN.js → chunk-PDPFQ2FO.js} +2 -0
- package/chunks/{chunk-2VSTGY6M.js → chunk-PJRW65JO.js} +1 -1
- package/chunks/{chunk-6HVUFDS2.js → chunk-PNVPFARW.js} +22 -13
- package/chunks/{chunk-IC4Z6LX6.js → chunk-PYQADEFD.js} +5 -0
- package/chunks/chunk-R4ZA6GBK.js +208 -0
- package/chunks/{chunk-KR4ZSC7K.js → chunk-RMPLEWF3.js} +3 -3
- package/chunks/{chunk-EORNAQDT.js → chunk-RQ6U2JJQ.js} +1 -1
- package/chunks/{chunk-AE77C5ZU.js → chunk-RYQMJCUO.js} +1 -1
- package/chunks/{chunk-6UWFTUQL.js → chunk-S5CULOHB.js} +75 -31
- package/chunks/{chunk-7UFKAV7Y.js → chunk-S6HYI3MF.js} +2 -2
- package/chunks/chunk-SAH4BD2J.js +92 -0
- package/chunks/chunk-SR7RZ4MS.js +202 -0
- package/chunks/{chunk-QETYKPMG.js → chunk-T2O6NIOY.js} +1 -1
- package/chunks/chunk-TQOF5KBL.js +71 -0
- package/chunks/{chunk-OHJLEW5J.js → chunk-TWFFY5BP.js} +4 -4
- package/chunks/{chunk-SCI7K3GM.js → chunk-TXO5BMR2.js} +19 -10
- package/chunks/{chunk-YJQCUTT2.js → chunk-UAB6J2IE.js} +4 -4
- package/chunks/{chunk-OFI7IGST.js → chunk-UGUKH3SU.js} +10 -10
- package/chunks/{chunk-SHZYHGQH.js → chunk-V2226RFW.js} +1 -1
- package/chunks/{chunk-KKJJB5X6.js → chunk-V47QNK5W.js} +1526 -833
- package/chunks/{chunk-W4B7UBUS.js → chunk-VHXPSL57.js} +6 -6
- package/chunks/{chunk-WUC6ZFXO.js → chunk-VKJ4KTPJ.js} +1 -1
- package/chunks/{chunk-MAJS7AT4.js → chunk-VNNWAZSI.js} +2 -2
- package/chunks/{chunk-BVWVWGLE.js → chunk-WAUGQKUU.js} +4 -64
- package/chunks/{chunk-OH2VKQXH.js → chunk-WH6QMLUW.js} +37 -30
- package/chunks/{chunk-PJOBIWUG.js → chunk-WQYWK4DG.js} +1 -1
- package/chunks/{chunk-LEMXGVEP.js → chunk-YFRFZCIP.js} +3 -3
- package/chunks/{chunk-2U3WZGZG.js → chunk-YGT2AUJ7.js} +103 -135
- package/chunks/{chunk-6XU3PH66.js → chunk-YR7ZQ4RD.js} +22 -69
- package/chunks/{chunk-OA4JVLSA.js → chunk-Z7VOMGDC.js} +22 -1
- package/chunks/{chunk-RUL4S3K3.js → chunk-ZCJBCKL5.js} +175 -60
- package/chunks/{chunk-GSS34377.js → chunk-ZI5IH2HP.js} +2 -2
- package/chunks/{chunk-CB2464BK.js → chunk-ZIKTCMQF.js} +117 -10
- package/chunks/chunk-ZLBIFIMV.js +1099 -0
- package/chunks/{chunk-D3UEZIQH.js → chunk-ZSNBQXMZ.js} +48 -55
- package/chunks/{chunk-FZBZSYKU.js → chunk-ZV7LTLFE.js} +1 -1
- package/chunks/{computer-use-KEAPATUY.js → computer-use-SLN7DV2E.js} +28 -24
- package/chunks/{config-utils-K7SCOWHD.js → config-utils-ULCSRMWD.js} +4 -4
- package/chunks/{contextCommand-ZJA6A5K5.js → contextCommand-EHFYX6FW.js} +30 -26
- package/chunks/{core-runtime-QMJPWHCI.js → core-runtime-FBSP5IIG.js} +33 -29
- package/chunks/{create-sub-session-E4PBYXV5.js → create-sub-session-QIDZUOPU.js} +1 -1
- package/chunks/{create-sub-session-DJE6XICH.js → create-sub-session-WC7YGVSL.js} +29 -25
- package/chunks/{cron-create-GRBWYMIJ.js → cron-create-VONA5JYY.js} +1 -1
- package/chunks/{cron-delete-4CMKBR2M.js → cron-delete-5JXSP2MI.js} +1 -1
- package/chunks/{cron-list-W7K4ASOA.js → cron-list-KE4F2CIR.js} +1 -1
- package/chunks/{daemon-SCTQMM7Z.js → daemon-VSX3FHTY.js} +119 -4
- package/chunks/{daemon-status-provider-FSWDPE2G.js → daemon-status-provider-WW2AD2T7.js} +39 -35
- package/chunks/{daemon-trust-policy-P5L5VFAY.js → daemon-trust-policy-E4MAYWPI.js} +35 -31
- package/chunks/{daemon-trust-policy-monitor-73JYN6ET.js → daemon-trust-policy-monitor-XVIDV6T4.js} +35 -31
- package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
- package/chunks/{deferred-core-runtime-BWRCCFTE.js → deferred-core-runtime-5SVUC6UC.js} +28 -24
- package/chunks/{display-image-O2XFPQTC.js → display-image-NQRSIBXM.js} +2 -2
- package/chunks/{dist-HVBMEYWK.js → dist-3NTTUAHT.js} +1 -1
- package/chunks/{dist-7JGAAQSC.js → dist-6BMOAE3Z.js} +2 -2
- package/chunks/{dist-3BMEUGTG.js → dist-B2CGTW6T.js} +1 -1
- package/chunks/{dist-C5U4LJKW.js → dist-EWW3J4HQ.js} +5 -4
- package/chunks/{dist-K4WWQBHS.js → dist-EZE3V3Q7.js} +55 -15
- package/chunks/{dist-DPPHJAVL.js → dist-J47AXBZC.js} +918 -142
- package/chunks/{dist-SFQ34F4M.js → dist-OTUO3AS2.js} +8 -1091
- package/chunks/{dist-KS4O2NKE.js → dist-Z3CS4OVP.js} +14 -8
- package/chunks/{earlyInputCapture-L5ST23A6.js → earlyInputCapture-72FYHYRD.js} +28 -24
- package/chunks/{edit-LHHRFNFK.js → edit-SWVVWHXW.js} +28 -24
- package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
- package/chunks/{enter-worktree-6NXCRZPF.js → enter-worktree-2HF6WQEO.js} +28 -24
- package/chunks/{enterPlanMode-ZVQT4U7D.js → enterPlanMode-OW6S7L4P.js} +28 -24
- package/chunks/{environment-GJ2HWJOS.js → environment-LRTBTDXH.js} +32 -28
- package/chunks/{errors-6RLH3XXC.js → errors-4CO2DME6.js} +30 -26
- package/chunks/{exit-worktree-I2YLUHHY.js → exit-worktree-GHJEIRGL.js} +28 -24
- package/chunks/{exitPlanMode-7CCWKO7I.js → exitPlanMode-JVP4FNNK.js} +28 -24
- package/chunks/{fast-path-DVFD4HQD.js → fast-path-HCCY7GR2.js} +24 -3
- package/chunks/{fast-path-settings-WQJU2LAT.js → fast-path-settings-MN5QQQET.js} +6 -3
- package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
- package/chunks/{gemini-7FWGOYD4.js → gemini-V3YVRKXU.js} +85 -72
- package/chunks/{geminiContentGenerator-V2WVLIXU.js → geminiContentGenerator-LVPMQUWX.js} +1 -1
- package/chunks/{glob-3N6GGI75.js → glob-7HRXHYDR.js} +28 -24
- package/chunks/{goal-tools-APOW6UXL.js → goal-tools-PXWN5VK3.js} +4 -2
- package/chunks/{grep-V43ILZVX.js → grep-BITQUON5.js} +28 -24
- package/chunks/{handleAutoUpdate-A5WFVWIA.js → handleAutoUpdate-DKFY454S.js} +32 -28
- package/chunks/{i18n-PLVQ4FBZ.js → i18n-53BQIQSH.js} +29 -25
- package/chunks/{image-gen-7C6IK6DC.js → image-gen-H62FLDFB.js} +7 -5
- package/chunks/{initializer-CVAIKZYL.js → initializer-Q7NUQRSU.js} +35 -31
- package/chunks/{installationInfo-J6QDHNTK.js → installationInfo-BWFHT7WU.js} +29 -25
- package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
- package/chunks/{list-ZZ4OUUWV.js → list-OWQKR6JK.js} +38 -34
- package/chunks/{list-agents-KFFIIS2G.js → list-agents-Z4WABFDZ.js} +1 -1
- package/chunks/{loadedSettingsAdapter-QRYRJSWL.js → loadedSettingsAdapter-HNPKQMFA.js} +35 -31
- package/chunks/{loggingContentGenerator-OJCO75HM.js → loggingContentGenerator-A5I3VQUC.js} +10 -8
- package/chunks/{loop-wakeup-TLMJPMMP.js → loop-wakeup-UZ5RL5Y2.js} +2 -2
- package/chunks/{ls-UVVE2XGE.js → ls-TVHDGIES.js} +1 -1
- package/chunks/{lsp-QMEA2VLB.js → lsp-CVN6OQPI.js} +1 -1
- package/chunks/main-PXAUXNF2.js +8 -0
- package/chunks/{managed-npm-update-PCOSCP2N.js → managed-npm-update-CUUJGUTV.js} +29 -25
- package/chunks/{mcp-M3WKKWKY.js → mcp-GJSC7ZPO.js} +35 -31
- package/chunks/{monitor-GN24FH6C.js → monitor-TZ2II7JM.js} +38 -30
- package/chunks/{nonInteractiveCli-KPTU3VSQ.js → nonInteractiveCli-22RS4EVH.js} +72 -66
- package/chunks/{notebook-edit-4YM65BBO.js → notebook-edit-YZC3YPY2.js} +36 -24
- package/chunks/{openaiContentGenerator-EDQT6GTV.js → openaiContentGenerator-OIGO5XNF.js} +21 -11
- package/chunks/{pidfile-JOIIRN2C.js → pidfile-QJQ65RJ2.js} +28 -24
- package/chunks/{process-registry-2CHQBXH5.js → process-registry-PMJOA5CO.js} +15 -0
- package/chunks/{processUtils-5SV4MX3Q.js → processUtils-V5VSDIKS.js} +2 -2
- package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
- package/chunks/{qwenContentGenerator-ODRJSUGR.js → qwenContentGenerator-HXM25BGB.js} +35 -30
- package/chunks/{qwenOAuth2-NESCMZ47.js → qwenOAuth2-7MTMS2Z5.js} +7 -5
- package/chunks/{read-file-HPSODLPK.js → read-file-PMGXB3ZB.js} +8 -6
- package/chunks/{read-mcp-resource-2TNSJTC3.js → read-mcp-resource-PZ4ZF6YL.js} +1 -1
- package/chunks/{record-artifact-RAON52FC.js → record-artifact-P4HFMS7X.js} +2 -2
- package/chunks/{resumeHistoryUtils-TXCOFFMQ.js → resumeHistoryUtils-YUTPLHUH.js} +33 -29
- package/chunks/{ripGrep-ZKQGTQAO.js → ripGrep-XUS66YIV.js} +28 -24
- package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
- package/chunks/{run-qwen-serve-ZPKPKECF.js → run-qwen-serve-4NVSU75L.js} +261 -62
- package/chunks/{runtime-2FLNNM36.js → runtime-QLRVP6HM.js} +40 -36
- package/chunks/{scheduler-365PJHNR.js → scheduler-PBB2NSOP.js} +28 -24
- package/chunks/{sdk-exporters-http-KHAB5JSD.js → sdk-exporters-http-XVTZQRCE.js} +2 -2
- package/chunks/{sdk-impl-KD7FSTC3.js → sdk-impl-7W7AKCS4.js} +7 -3
- package/chunks/{send-message-ZM7MRUGP.js → send-message-CAMSLG2L.js} +4 -3
- package/chunks/{serve-QD2RNLKJ.js → serve-BWKTRX72.js} +37 -31
- package/chunks/{server-XLJVLTYM.js → server-E7CH7WPK.js} +1437 -593
- package/chunks/{session-3VTUHH4Q.js → session-QEKSJ6YU.js} +166 -105
- package/chunks/{settings-KULVPCQC.js → settings-BRAOSJIM.js} +34 -30
- package/chunks/{shell-3SWW22MH.js → shell-OF3CK4AT.js} +28 -24
- package/chunks/{skill-KDHWYS7W.js → skill-HLH2NO2H.js} +9 -7
- package/chunks/{skill-settings-NMY4JEJC.js → skill-settings-DRPU7YI5.js} +34 -30
- package/chunks/{spawnChannel-ZKS4Q5OU.js → spawnChannel-4KO7YTFM.js} +31 -27
- package/chunks/{standalone-update-7CXPGAQ4.js → standalone-update-DJN2R3YW.js} +30 -26
- package/chunks/{startInteractiveUI-2QQLEKM6.js → startInteractiveUI-O3WQQ2WC.js} +384 -173
- package/chunks/{syntheticOutput-ZLCUTKO2.js → syntheticOutput-PEBJQYJV.js} +2 -2
- package/chunks/{task-create-CQP5UEA3.js → task-create-5NWCQSJF.js} +5 -4
- package/chunks/{task-list-XLEZOJXP.js → task-list-53265TRZ.js} +1 -1
- package/chunks/{task-stop-7ZQM5CFF.js → task-stop-FPCOIRYX.js} +1 -1
- package/chunks/{task-update-JA75U2SN.js → task-update-5HN577LS.js} +5 -4
- package/chunks/{team-create-2WTNGAOX.js → team-create-2E4ACBJD.js} +28 -24
- package/chunks/{team-delete-MHY3UZGY.js → team-delete-MMQB4OSC.js} +1 -1
- package/chunks/{team-plan-approval-LZTYLEG4.js → team-plan-approval-LWIDXYOA.js} +28 -24
- package/chunks/{terminal-image-renderer-R5HHAFJN.js → terminal-image-renderer-PJM7663W.js} +30 -26
- package/chunks/{theme-manager-PAUCSJFF.js → theme-manager-FDQTM3RP.js} +28 -24
- package/chunks/{todoWrite-UPVOHYGD.js → todoWrite-JGV6VLOX.js} +1 -1
- package/chunks/{tool-search-2BFCGLI6.js → tool-search-TL5ZXBF4.js} +11 -8
- package/chunks/{total-session-admission-MK4SINFK.js → total-session-admission-LS6EY5KT.js} +37 -32
- package/chunks/{trustedFolders-TJ5S26N7.js → trustedFolders-5RWP5OB7.js} +32 -26
- package/chunks/{types-ML3TRJQ5.js → types-WYCFCEHR.js} +5 -3
- package/chunks/{update-relaunch-N7AYLARF.js → update-relaunch-HWQ4USKY.js} +5 -5
- package/chunks/{updateCheck-QRZ3DVT5.js → updateCheck-EZMBTEIR.js} +31 -27
- package/chunks/{useAutoAcceptIndicator-DBJ7Y5AF.js → useAutoAcceptIndicator-JDMI627A.js} +37 -33
- package/chunks/{validateNonInterActiveAuth-6ZQWUDS3.js → validateNonInterActiveAuth-RRUHC5RO.js} +67 -63
- package/chunks/{version-AJQGQWXC.js → version-XS4UTKUX.js} +1 -1
- package/chunks/{web-fetch-QWJYRXFL.js → web-fetch-2JV7H6OM.js} +14 -10
- package/chunks/{web-search-2AOXJGHU.js → web-search-RCTN2GAM.js} +10 -7
- package/chunks/{workflow-ERH3SJG2.js → workflow-6MKLKQ6R.js} +909 -273
- package/chunks/{workspace-providers-status-HZ474RA4.js → workspace-providers-status-YZ2IJ4DK.js} +38 -34
- package/chunks/{workspace-registration-store-6EUP4JXG.js → workspace-registration-store-IYN72LBS.js} +1 -1
- package/chunks/{workspace-registry-R4APRRNC.js → workspace-registry-7LFBZQLT.js} +37 -32
- package/chunks/{workspace-service-HFIFDMU7.js → workspace-service-2EHSPRJB.js} +45 -39
- package/chunks/{workspace-skills-status-HAHEIHGK.js → workspace-skills-status-5VJ2D5HN.js} +36 -32
- package/chunks/{workspace-trust-reconciler-65GTAGDK.js → workspace-trust-reconciler-X2LZ6XCI.js} +44 -39
- package/chunks/{write-file-B34CDELV.js → write-file-CJK6SCCF.js} +28 -24
- package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
- package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
- package/chunks/{zoom-image-HPRBZHSS.js → zoom-image-BVW4RFYW.js} +8 -6
- package/cli.js +13 -13
- package/locales/ca.js +10 -0
- package/locales/de.js +9 -0
- package/locales/en.js +10 -0
- package/locales/fr.js +9 -0
- package/locales/ja.js +9 -0
- package/locales/pt.js +9 -0
- package/locales/ru.js +9 -0
- package/locales/zh-TW.js +10 -0
- package/locales/zh.js +10 -0
- package/package.json +3 -3
- package/web-shell/assets/{arc-Ip-FFDJ0.js → arc-DDtoJrAW.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-CChqgwIb.js → architectureDiagram-3BPJPVTR-BAInIW4O.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BHN-Tfss.js → blockDiagram-GPEHLZMM-ChPDk7fP.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BhyjzDjN.js → c4Diagram-AAUBKEIU-Cd9BJuUy.js} +1 -1
- package/web-shell/assets/channel-0OQklTfP.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BB9eyHrx.js → chunk-2J33WTMH-COQkLp56.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BeV7ce_J.js → chunk-4BX2VUAB-GUJshQ_l.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DO7kXDiV.js → chunk-55IACEB6-Boaa7c10.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B27MPznD.js → chunk-727SXJPM-CcRXaly2.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DHIjqjD_.js → chunk-AQP2D5EJ-BY0OARHh.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DabMqyN2.js → chunk-FMBD7UC4-DLFQfv0S.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-Dw7Nnnxc.js → chunk-ND2GUHAM-C_S0u-D2.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-DdaZew1Q.js → chunk-QZHKN3VN-DP9m64hw.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CZ4-apsu.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CZ4-apsu.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-CgBpCYH5.js → cose-bilkent-S5V4N54A-CGY6zGE1.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-BB4IU8G0.js → dagre-BM42HDAG-yB7whKNn.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BcUTHU37.js → diagram-2AECGRRQ-Bdlc59La.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-B6Lyihyv.js → diagram-5GNKFQAL-BUClP18L.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CRIJOjpG.js → diagram-KO2AKTUF-aZm08kjn.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DdNiwWWT.js → diagram-LMA3HP47-7DGwEkxC.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Dz4b32Do.js → diagram-OG6HWLK6-CAGKayxx.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-D-8NGw77.js → erDiagram-TEJ5UH35-CptoHHQi.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-Dun26LyM.js → flowDiagram-I6XJVG4X-CNOH0s7Q.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-F10Hu1Gc.js → ganttDiagram-6RSMTGT7-CCQuCU3y.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bf8Ez6-D.js → gitGraphDiagram-PVQCEYII-B7gv9f4E.js} +1 -1
- package/web-shell/assets/{index-BXqw-nGq.js → index-BoUPVvpf.js} +1 -1
- package/web-shell/assets/index-D1YQXYsB.css +5 -0
- package/web-shell/assets/index-J4N7zCmU.js +1768 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DVgTMLvj.js → infoDiagram-5YYISTIA-Bb3KYEbR.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-uT-KepvK.js → ishikawaDiagram-YF4QCWOH-DWEzbAGi.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Vg_XadQf.js → journeyDiagram-JHISSGLW-CmxwEqeb.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-Dyv1ESBE.js → kanban-definition-UN3LZRKU-Ci0gDD8O.js} +1 -1
- package/web-shell/assets/{linear-BMIepYX3.js → linear-BqxZqGhS.js} +1 -1
- package/web-shell/assets/{mermaid.core-zA8pJ9ag.js → mermaid.core-BDAFffHv.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BCW_BZ_5.js → mindmap-definition-RKZ34NQL-Btvx-xvS.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DseNEGp2.js → pieDiagram-4H26LBE5-CKAg7yG7.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-6Z7wr1Fi.js → quadrantDiagram-W4KKPZXB-DIt8E1mC.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CVOlCRPf.js → requirementDiagram-4Y6WPE33-BA7mQWQJ.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CGhgrUJZ.js → sankeyDiagram-5OEKKPKP-D0JppnVU.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-dlqmpLuQ.js → sequenceDiagram-3UESZ5HK-29DIQFjB.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-B9EW10Xb.js → stateDiagram-AJRCARHV-iiXMdK--.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CEGK3l80.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-BBRh0mgZ.js → timeline-definition-PNZ67QCA-CeF7ngSW.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-B8Gs-REP.js → vennDiagram-CIIHVFJN-Beilq8D6.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-D_y80Ur7.js → wardley-L42UT6IY-DOYjY4zO.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-D-CNfHJ-.js → wardleyDiagram-YWT4CUSO-Dtqp8o18.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-DQ5CvELo.js → xychartDiagram-2RQKCTM6-cdAc0Dfv.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-6PEXNQTX.js +0 -68
- package/chunks/chunk-IUFV6FYU.js +0 -81
- package/chunks/chunk-RXFQM6FQ.js +0 -42
- package/web-shell/assets/channel-Cu8qd6OB.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BI3KrXhq.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BI3KrXhq.js +0 -1
- package/web-shell/assets/index-QQlUCJGg.css +0 -5
- package/web-shell/assets/index-hcgjV7vS.js +0 -1768
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CJTZJJ5X.js +0 -1
- package/chunks/{anthropicContentGenerator-DTMVEL5M.js → anthropicContentGenerator-SSFE2753.js} +9 -9
- /package/chunks/{chunk-VXZBKKQR.js → chunk-NTTBXH7U.js} +0 -0
- /package/chunks/{chunk-GRC5HGPI.js → chunk-OIBUG24X.js} +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import {
|
|
4
|
-
serveCommand
|
|
5
|
-
} from "./chunk-CB2464BK.js";
|
|
6
3
|
import {
|
|
7
4
|
listCommand
|
|
8
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OW2BWT2P.js";
|
|
6
|
+
import {
|
|
7
|
+
serveCommand
|
|
8
|
+
} from "./chunk-ZIKTCMQF.js";
|
|
9
9
|
import {
|
|
10
10
|
getErrorMessage as getErrorMessage2
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-P5ULXPK5.js";
|
|
12
12
|
import {
|
|
13
|
+
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
13
14
|
ObservedChannelContactStore
|
|
14
15
|
} from "./chunk-OWMAZHIX.js";
|
|
15
16
|
import {
|
|
@@ -22,16 +23,17 @@ import {
|
|
|
22
23
|
loadUndici
|
|
23
24
|
} from "./chunk-3Z43GZUQ.js";
|
|
24
25
|
import {
|
|
25
|
-
isLoopbackBind
|
|
26
|
-
|
|
26
|
+
isLoopbackBind,
|
|
27
|
+
isValidSessionId
|
|
28
|
+
} from "./chunk-TQOF5KBL.js";
|
|
29
|
+
import {
|
|
30
|
+
resolvePath
|
|
31
|
+
} from "./chunk-AOHJKPKL.js";
|
|
27
32
|
import {
|
|
28
33
|
collectProviderModelsForProtocol,
|
|
29
34
|
getAuthTypeFromEnv,
|
|
30
35
|
resolveCliGenerationConfig
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import {
|
|
33
|
-
resolvePath
|
|
34
|
-
} from "./chunk-AOHJKPKL.js";
|
|
36
|
+
} from "./chunk-HWXGX534.js";
|
|
35
37
|
import {
|
|
36
38
|
resolveSkillSettings
|
|
37
39
|
} from "./chunk-Z4X5MTRT.js";
|
|
@@ -51,17 +53,24 @@ import {
|
|
|
51
53
|
registerToolCallDispatch,
|
|
52
54
|
selectFirstModel,
|
|
53
55
|
sessionsPath
|
|
54
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-EISUQQPS.js";
|
|
55
57
|
import {
|
|
56
58
|
getExtensionManager,
|
|
57
59
|
requestChoicePluginNonInteractive,
|
|
58
60
|
requestConsentNonInteractive,
|
|
59
61
|
requestConsentOrFail,
|
|
60
62
|
resolveExtensionCommandScope
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-TWFFY5BP.js";
|
|
62
64
|
import {
|
|
63
65
|
parseChannelConfig
|
|
64
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-LHEC5V6G.js";
|
|
67
|
+
import {
|
|
68
|
+
DEFAULT_BASE_URL,
|
|
69
|
+
buildHeaders,
|
|
70
|
+
clearAccount,
|
|
71
|
+
loadAccount,
|
|
72
|
+
saveAccount
|
|
73
|
+
} from "./chunk-VKJ4KTPJ.js";
|
|
65
74
|
import {
|
|
66
75
|
findCliEntryPath
|
|
67
76
|
} from "./chunk-V6WHFGST.js";
|
|
@@ -92,16 +101,16 @@ import {
|
|
|
92
101
|
import {
|
|
93
102
|
normalizeWorkerDiagnostic,
|
|
94
103
|
sanitizeWorkerDiagnostic
|
|
95
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-PBRVUF5B.js";
|
|
96
105
|
import {
|
|
97
106
|
normalizeServeChannelSelection
|
|
98
107
|
} from "./chunk-ALMR3E6Q.js";
|
|
99
|
-
import {
|
|
100
|
-
EXTERNAL_TOOL_GUARD_TOKEN_ENV
|
|
101
|
-
} from "./chunk-BKHCW2BI.js";
|
|
102
108
|
import {
|
|
103
109
|
redactLogCredentials
|
|
104
110
|
} from "./chunk-M5GB774H.js";
|
|
111
|
+
import {
|
|
112
|
+
EXTERNAL_TOOL_GUARD_TOKEN_ENV
|
|
113
|
+
} from "./chunk-BKHCW2BI.js";
|
|
105
114
|
import {
|
|
106
115
|
readServiceInfo,
|
|
107
116
|
removeServiceInfo,
|
|
@@ -109,13 +118,6 @@ import {
|
|
|
109
118
|
waitForExit,
|
|
110
119
|
writeServiceInfo
|
|
111
120
|
} from "./chunk-UVX4Y6IN.js";
|
|
112
|
-
import {
|
|
113
|
-
DEFAULT_BASE_URL,
|
|
114
|
-
buildHeaders,
|
|
115
|
-
clearAccount,
|
|
116
|
-
loadAccount,
|
|
117
|
-
saveAccount
|
|
118
|
-
} from "./chunk-WUC6ZFXO.js";
|
|
119
121
|
import {
|
|
120
122
|
AcpBridge,
|
|
121
123
|
ChannelLoopScheduler,
|
|
@@ -126,37 +128,41 @@ import {
|
|
|
126
128
|
isChannelProactiveDeliveryError,
|
|
127
129
|
sanitizeLogText,
|
|
128
130
|
sanitizePromptText
|
|
129
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-DX3RGJMS.js";
|
|
130
132
|
import {
|
|
131
133
|
assembleMcpServers,
|
|
132
134
|
getPendingGatedMcpServers,
|
|
133
135
|
mcpCommand
|
|
134
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-PNVPFARW.js";
|
|
135
137
|
import {
|
|
136
138
|
loadSettings
|
|
137
|
-
} from "./chunk-
|
|
139
|
+
} from "./chunk-HKI3KHAO.js";
|
|
138
140
|
import {
|
|
139
141
|
detectSystemLanguage,
|
|
140
142
|
getCurrentLanguage,
|
|
141
143
|
initializeI18n,
|
|
142
144
|
resolveLanguageSetting,
|
|
143
145
|
t
|
|
144
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-BL65MO72.js";
|
|
145
147
|
import {
|
|
146
148
|
loadEnvironment
|
|
147
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-KP25NJNM.js";
|
|
150
|
+
import {
|
|
151
|
+
resolveAcpChannelFallback,
|
|
152
|
+
scrubAndReportInheritedLoaderEnv
|
|
153
|
+
} from "./chunk-R4ZA6GBK.js";
|
|
148
154
|
import {
|
|
149
155
|
getCliVersion
|
|
150
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-ZV7LTLFE.js";
|
|
151
157
|
import {
|
|
152
158
|
getPackageJson
|
|
153
159
|
} from "./chunk-VJNBRRZG.js";
|
|
154
160
|
import {
|
|
155
161
|
isWorkspaceTrusted
|
|
156
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-YR7ZQ4RD.js";
|
|
157
163
|
import {
|
|
158
164
|
require_strip_json_comments
|
|
159
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-NPQ5ZKRP.js";
|
|
160
166
|
import {
|
|
161
167
|
hideBin,
|
|
162
168
|
yargs_default
|
|
@@ -195,7 +201,7 @@ import {
|
|
|
195
201
|
unquoteCStylePath,
|
|
196
202
|
updateChannelMemoryEntry,
|
|
197
203
|
updateSetting
|
|
198
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-47ZUMGGY.js";
|
|
199
205
|
import {
|
|
200
206
|
nextFireTime,
|
|
201
207
|
parseCron
|
|
@@ -206,19 +212,19 @@ import {
|
|
|
206
212
|
import {
|
|
207
213
|
parseBooleanEnvFlag,
|
|
208
214
|
resolveTelemetrySettings
|
|
209
|
-
} from "./chunk-
|
|
215
|
+
} from "./chunk-4TRQPFDP.js";
|
|
210
216
|
import {
|
|
211
217
|
getAllGeminiMdFilenames,
|
|
212
218
|
parseLineTolerant,
|
|
213
219
|
setGeminiMdFilename
|
|
214
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-YGT2AUJ7.js";
|
|
215
221
|
import {
|
|
216
222
|
SchemaValidator,
|
|
217
223
|
ToolNames
|
|
218
|
-
} from "./chunk-
|
|
224
|
+
} from "./chunk-PYQADEFD.js";
|
|
219
225
|
import {
|
|
220
226
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
221
|
-
} from "./chunk-
|
|
227
|
+
} from "./chunk-F6WFNA7U.js";
|
|
222
228
|
import {
|
|
223
229
|
isTlsVerificationDisabled
|
|
224
230
|
} from "./chunk-KKBPOU75.js";
|
|
@@ -227,7 +233,7 @@ import {
|
|
|
227
233
|
} from "./chunk-FOGU3LJX.js";
|
|
228
234
|
import {
|
|
229
235
|
recordChannelMemoryRecallMetrics
|
|
230
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-L2AFWWJE.js";
|
|
231
237
|
import {
|
|
232
238
|
FatalConfigError,
|
|
233
239
|
FatalSandboxError,
|
|
@@ -364,9 +370,9 @@ var require_command_exists = __commonJS({
|
|
|
364
370
|
cleanInput = /* @__PURE__ */ __name(function(s) {
|
|
365
371
|
var isPathName = /[\\]/.test(s);
|
|
366
372
|
if (isPathName) {
|
|
367
|
-
var
|
|
368
|
-
var
|
|
369
|
-
return
|
|
373
|
+
var dirname27 = '"' + path3.dirname(s) + '"';
|
|
374
|
+
var basename7 = '"' + path3.basename(s) + '"';
|
|
375
|
+
return dirname27 + ":" + basename7;
|
|
370
376
|
}
|
|
371
377
|
return '"' + s + '"';
|
|
372
378
|
}, "cleanInput");
|
|
@@ -374,10 +380,10 @@ var require_command_exists = __commonJS({
|
|
|
374
380
|
module.exports = /* @__PURE__ */ __name(function commandExists2(commandName, callback) {
|
|
375
381
|
var cleanedCommandName = cleanInput(commandName);
|
|
376
382
|
if (!callback && typeof Promise !== "undefined") {
|
|
377
|
-
return new Promise(function(
|
|
383
|
+
return new Promise(function(resolve29, reject) {
|
|
378
384
|
commandExists2(commandName, function(error, output) {
|
|
379
385
|
if (output) {
|
|
380
|
-
|
|
386
|
+
resolve29(commandName);
|
|
381
387
|
} else {
|
|
382
388
|
reject(error);
|
|
383
389
|
}
|
|
@@ -2324,8 +2330,8 @@ function createBridgeReadinessGate() {
|
|
|
2324
2330
|
current: /* @__PURE__ */ __name(() => pending, "current"),
|
|
2325
2331
|
block: /* @__PURE__ */ __name(() => {
|
|
2326
2332
|
if (pending) return;
|
|
2327
|
-
pending = new Promise((
|
|
2328
|
-
releasePending =
|
|
2333
|
+
pending = new Promise((resolve29) => {
|
|
2334
|
+
releasePending = resolve29;
|
|
2329
2335
|
});
|
|
2330
2336
|
}, "block"),
|
|
2331
2337
|
release: /* @__PURE__ */ __name(() => {
|
|
@@ -2407,7 +2413,7 @@ function createBridgeRecovery(options) {
|
|
|
2407
2413
|
writeStderrLine(
|
|
2408
2414
|
`[Channel] Bridge crashed (${recentCrashCount}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2409
2415
|
);
|
|
2410
|
-
await new Promise((
|
|
2416
|
+
await new Promise((resolve29) => setTimeout(resolve29, RESTART_DELAY_MS));
|
|
2411
2417
|
const bridge = new AcpBridge(bridgeOpts);
|
|
2412
2418
|
setBridge(bridge);
|
|
2413
2419
|
attachDisconnectHandler(bridge);
|
|
@@ -2725,7 +2731,7 @@ var stopCommand = {
|
|
|
2725
2731
|
if (argv["daemon-url"]) {
|
|
2726
2732
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2727
2733
|
try {
|
|
2728
|
-
const sdk = await import("./daemon-
|
|
2734
|
+
const sdk = await import("./daemon-VSX3FHTY.js");
|
|
2729
2735
|
const client = new sdk.DaemonClient({
|
|
2730
2736
|
baseUrl: argv["daemon-url"],
|
|
2731
2737
|
...token ? { token } : {}
|
|
@@ -2911,7 +2917,7 @@ var statusCommand = {
|
|
|
2911
2917
|
if (argv["daemon-url"]) {
|
|
2912
2918
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2913
2919
|
try {
|
|
2914
|
-
const sdk = await import("./daemon-
|
|
2920
|
+
const sdk = await import("./daemon-VSX3FHTY.js");
|
|
2915
2921
|
const client = new sdk.DaemonClient({
|
|
2916
2922
|
baseUrl: argv["daemon-url"],
|
|
2917
2923
|
...token ? { token } : {}
|
|
@@ -3022,7 +3028,7 @@ var reloadCommand = {
|
|
|
3022
3028
|
const token = resolveToken(argv.token);
|
|
3023
3029
|
let sdk;
|
|
3024
3030
|
try {
|
|
3025
|
-
sdk = await import("./daemon-
|
|
3031
|
+
sdk = await import("./daemon-VSX3FHTY.js");
|
|
3026
3032
|
} catch (err) {
|
|
3027
3033
|
writeStderrLine(
|
|
3028
3034
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(err)}`
|
|
@@ -3102,7 +3108,7 @@ var setCommand2 = {
|
|
|
3102
3108
|
const selection = names[0] === "all" ? { mode: "all" } : { mode: "names", names };
|
|
3103
3109
|
let sdk;
|
|
3104
3110
|
try {
|
|
3105
|
-
sdk = await import("./daemon-
|
|
3111
|
+
sdk = await import("./daemon-VSX3FHTY.js");
|
|
3106
3112
|
} catch (error) {
|
|
3107
3113
|
writeStderrLine(
|
|
3108
3114
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(error)}`
|
|
@@ -3228,7 +3234,7 @@ function createDaemonChannelBridgeFacade(bridge, opts) {
|
|
|
3228
3234
|
}
|
|
3229
3235
|
__name(createDaemonChannelBridgeFacade, "createDaemonChannelBridgeFacade");
|
|
3230
3236
|
async function loadDaemonSdk() {
|
|
3231
|
-
return await import("./daemon-
|
|
3237
|
+
return await import("./daemon-VSX3FHTY.js");
|
|
3232
3238
|
}
|
|
3233
3239
|
__name(loadDaemonSdk, "loadDaemonSdk");
|
|
3234
3240
|
function selectedChannelNames(channelsConfig, selection) {
|
|
@@ -3275,12 +3281,12 @@ async function abortableStartup(value, signal) {
|
|
|
3275
3281
|
const promise = Promise.resolve(value);
|
|
3276
3282
|
if (!signal) return await promise;
|
|
3277
3283
|
if (signal.aborted) throw startupAbortError();
|
|
3278
|
-
return await new Promise((
|
|
3284
|
+
return await new Promise((resolve29, reject) => {
|
|
3279
3285
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3280
3286
|
reject(startupAbortError());
|
|
3281
3287
|
}, "onAbort");
|
|
3282
3288
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3283
|
-
promise.then(
|
|
3289
|
+
promise.then(resolve29, reject).finally(() => {
|
|
3284
3290
|
signal.removeEventListener("abort", onAbort);
|
|
3285
3291
|
});
|
|
3286
3292
|
});
|
|
@@ -3472,7 +3478,10 @@ async function runChannelDaemonWorker(opts) {
|
|
|
3472
3478
|
observedContacts: {
|
|
3473
3479
|
observe: /* @__PURE__ */ __name((channelName, observation) => {
|
|
3474
3480
|
observedContacts.observe(channelName, observation);
|
|
3475
|
-
}, "observe")
|
|
3481
|
+
}, "observe"),
|
|
3482
|
+
list: /* @__PURE__ */ __name(() => observedContacts.list({
|
|
3483
|
+
freshWithinSeconds: OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS
|
|
3484
|
+
}), "list")
|
|
3476
3485
|
},
|
|
3477
3486
|
...loopController ? { loopController } : {}
|
|
3478
3487
|
}),
|
|
@@ -3689,7 +3698,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3689
3698
|
if (!send) {
|
|
3690
3699
|
return Promise.reject(new Error("Channel worker IPC is unavailable."));
|
|
3691
3700
|
}
|
|
3692
|
-
return new Promise((
|
|
3701
|
+
return new Promise((resolve29, reject) => {
|
|
3693
3702
|
let settled = false;
|
|
3694
3703
|
let unsubscribeMessage = /* @__PURE__ */ __name(() => {
|
|
3695
3704
|
}, "unsubscribeMessage");
|
|
@@ -3703,7 +3712,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3703
3712
|
settled = true;
|
|
3704
3713
|
cleanup();
|
|
3705
3714
|
if (error) reject(error);
|
|
3706
|
-
else
|
|
3715
|
+
else resolve29();
|
|
3707
3716
|
}, "finish");
|
|
3708
3717
|
const onMessage = /* @__PURE__ */ __name((value) => {
|
|
3709
3718
|
if (isChannelStartupReportAckMessage(value)) {
|
|
@@ -3785,6 +3794,11 @@ var daemonWorkerCommand = {
|
|
|
3785
3794
|
try {
|
|
3786
3795
|
assertInternalDaemonWorkerInvocation();
|
|
3787
3796
|
const { daemonToken, daemonUrl, workspace } = readDaemonWorkerEnv();
|
|
3797
|
+
scrubAndReportInheritedLoaderEnv(
|
|
3798
|
+
process.env,
|
|
3799
|
+
"qwen channel daemon-worker",
|
|
3800
|
+
"channel daemon worker"
|
|
3801
|
+
);
|
|
3788
3802
|
const send = process.send;
|
|
3789
3803
|
channelLoopMcpHost = new ChannelLoopMcpWorkerHost(
|
|
3790
3804
|
(message, callback) => send.call(process, message, callback ?? (() => {
|
|
@@ -3951,8 +3965,8 @@ var daemonWorkerCommand = {
|
|
|
3951
3965
|
let shuttingDown = false;
|
|
3952
3966
|
let exitCode = 0;
|
|
3953
3967
|
let finish;
|
|
3954
|
-
const finished = new Promise((
|
|
3955
|
-
finish =
|
|
3968
|
+
const finished = new Promise((resolve29) => {
|
|
3969
|
+
finish = resolve29;
|
|
3956
3970
|
});
|
|
3957
3971
|
const shutdown = /* @__PURE__ */ __name(async (reason) => {
|
|
3958
3972
|
if (shuttingDown) {
|
|
@@ -3980,8 +3994,8 @@ var daemonWorkerCommand = {
|
|
|
3980
3994
|
...activeChannelDeliveries.values(),
|
|
3981
3995
|
...activeWebhookTasks.values()
|
|
3982
3996
|
]),
|
|
3983
|
-
new Promise((
|
|
3984
|
-
const timer = setTimeout(
|
|
3997
|
+
new Promise((resolve29) => {
|
|
3998
|
+
const timer = setTimeout(resolve29, WORKER_SHUTDOWN_DRAIN_MS);
|
|
3985
3999
|
timer.unref();
|
|
3986
4000
|
})
|
|
3987
4001
|
]);
|
|
@@ -4085,9 +4099,8 @@ var pairingListCommand = {
|
|
|
4085
4099
|
`);
|
|
4086
4100
|
for (const req of pending) {
|
|
4087
4101
|
const ago = Math.round((Date.now() - req.createdAt) / 6e4);
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
);
|
|
4102
|
+
const subject = req.subject.type === "group" ? `Group: ${req.subject.name} (${req.subject.id}) Requested by: ${req.senderName} (${req.senderId})` : `Sender: ${req.subject.name} (${req.subject.id})`;
|
|
4103
|
+
writeStdoutLine(` Code: ${req.code} ${subject} ${ago}m ago`);
|
|
4091
4104
|
}
|
|
4092
4105
|
}, "handler")
|
|
4093
4106
|
};
|
|
@@ -4113,8 +4126,9 @@ var pairingApproveCommand = {
|
|
|
4113
4126
|
process.exit(1);
|
|
4114
4127
|
return;
|
|
4115
4128
|
}
|
|
4129
|
+
const approved = request.subject.type === "group" ? `group ${request.subject.name} (${request.subject.id})` : `${request.subject.name} (${request.subject.id})`;
|
|
4116
4130
|
writeStdoutLine(
|
|
4117
|
-
`Approved: ${
|
|
4131
|
+
`Approved: ${approved} can now use channel "${argv.name}".`
|
|
4118
4132
|
);
|
|
4119
4133
|
}, "handler")
|
|
4120
4134
|
};
|
|
@@ -4265,7 +4279,7 @@ var configureWeixinCommand = {
|
|
|
4265
4279
|
// packages/cli/src/commands/channel.ts
|
|
4266
4280
|
var pairingCommand = {
|
|
4267
4281
|
command: "pairing",
|
|
4268
|
-
describe: "Manage DM pairing requests",
|
|
4282
|
+
describe: "Manage DM and group pairing requests",
|
|
4269
4283
|
builder: /* @__PURE__ */ __name((yargs) => yargs.command(pairingListCommand).command(pairingApproveCommand).demandCommand(1, "You need at least one command before continuing.").version(false), "builder"),
|
|
4270
4284
|
handler: /* @__PURE__ */ __name(() => {
|
|
4271
4285
|
}, "handler")
|
|
@@ -4336,8 +4350,211 @@ init_esbuild_shims();
|
|
|
4336
4350
|
|
|
4337
4351
|
// packages/cli/src/commands/review/parse-args.ts
|
|
4338
4352
|
init_esbuild_shims();
|
|
4339
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
4340
|
-
import { dirname } from "node:path";
|
|
4353
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4354
|
+
import { dirname as dirname2 } from "node:path";
|
|
4355
|
+
|
|
4356
|
+
// packages/cli/src/commands/review/lib/stale-bundle.ts
|
|
4357
|
+
init_esbuild_shims();
|
|
4358
|
+
import { createHash } from "node:crypto";
|
|
4359
|
+
import {
|
|
4360
|
+
existsSync as existsSync3,
|
|
4361
|
+
readFileSync as readFileSync3,
|
|
4362
|
+
readdirSync as readdirSync2,
|
|
4363
|
+
realpathSync,
|
|
4364
|
+
statSync
|
|
4365
|
+
} from "node:fs";
|
|
4366
|
+
import {
|
|
4367
|
+
basename as basename3,
|
|
4368
|
+
dirname,
|
|
4369
|
+
extname,
|
|
4370
|
+
join as join5,
|
|
4371
|
+
relative as relative2,
|
|
4372
|
+
resolve as resolve3,
|
|
4373
|
+
sep
|
|
4374
|
+
} from "node:path";
|
|
4375
|
+
var DIGEST_FILE = "review-sources.sha256";
|
|
4376
|
+
var NOT_BUNDLED_RE = /\.(?:test|spec)\.(?:d\.)?[cm]?[jt]sx?$/;
|
|
4377
|
+
var NOT_BUNDLED_DIR = /* @__PURE__ */ new Set(["__fixtures__", "__snapshots__"]);
|
|
4378
|
+
var NOT_BUNDLED_FILE = /* @__PURE__ */ new Set(["test-utils.ts"]);
|
|
4379
|
+
var NOT_BUNDLED_SKILL_FILE = /* @__PURE__ */ new Set(["DESIGN.md"]);
|
|
4380
|
+
var DIGESTED_EXTENSIONS = {
|
|
4381
|
+
code: /* @__PURE__ */ new Set([
|
|
4382
|
+
".ts",
|
|
4383
|
+
".tsx",
|
|
4384
|
+
".mts",
|
|
4385
|
+
".cts",
|
|
4386
|
+
".js",
|
|
4387
|
+
".mjs",
|
|
4388
|
+
".json",
|
|
4389
|
+
".jsx"
|
|
4390
|
+
]),
|
|
4391
|
+
skill: /* @__PURE__ */ new Set([".md"])
|
|
4392
|
+
};
|
|
4393
|
+
function isDigestedFile(kind, name) {
|
|
4394
|
+
if (!DIGESTED_EXTENSIONS[kind].has(extname(name))) return false;
|
|
4395
|
+
if (kind !== "code") return !NOT_BUNDLED_SKILL_FILE.has(name);
|
|
4396
|
+
return !NOT_BUNDLED_RE.test(name) && !NOT_BUNDLED_FILE.has(name);
|
|
4397
|
+
}
|
|
4398
|
+
__name(isDigestedFile, "isDigestedFile");
|
|
4399
|
+
function measureReviewSources(repoRoot, roots) {
|
|
4400
|
+
const state = { incomplete: false, absentRoots: 0 };
|
|
4401
|
+
const files = [];
|
|
4402
|
+
for (const root of roots) files.push(...sourceFilesUnder(root, state, false));
|
|
4403
|
+
const partial = state.absentRoots > 0 && state.absentRoots < roots.length;
|
|
4404
|
+
if (state.incomplete || files.length === 0) {
|
|
4405
|
+
return { digest: void 0, incomplete: state.incomplete, partial };
|
|
4406
|
+
}
|
|
4407
|
+
const hash = createHash("sha256");
|
|
4408
|
+
for (const file of files.sort()) {
|
|
4409
|
+
let content;
|
|
4410
|
+
try {
|
|
4411
|
+
content = readFileSync3(file);
|
|
4412
|
+
} catch {
|
|
4413
|
+
return { digest: void 0, incomplete: true, partial };
|
|
4414
|
+
}
|
|
4415
|
+
hash.update(relative2(repoRoot, file).split(sep).join("/"));
|
|
4416
|
+
hash.update("\0");
|
|
4417
|
+
hash.update(content);
|
|
4418
|
+
hash.update("\0");
|
|
4419
|
+
}
|
|
4420
|
+
return { digest: hash.digest("hex"), incomplete: false, partial };
|
|
4421
|
+
}
|
|
4422
|
+
__name(measureReviewSources, "measureReviewSources");
|
|
4423
|
+
function bundleStaleness(stampedDigest, currentDigest) {
|
|
4424
|
+
if (!stampedDigest) {
|
|
4425
|
+
return { stale: false, unmeasured: "the bundle carries no source digest" };
|
|
4426
|
+
}
|
|
4427
|
+
if (!currentDigest) {
|
|
4428
|
+
return {
|
|
4429
|
+
stale: false,
|
|
4430
|
+
unmeasured: "no review sources were found to compare"
|
|
4431
|
+
};
|
|
4432
|
+
}
|
|
4433
|
+
return { stale: stampedDigest !== currentDigest };
|
|
4434
|
+
}
|
|
4435
|
+
__name(bundleStaleness, "bundleStaleness");
|
|
4436
|
+
function* sourceFilesUnder(root, state, listed) {
|
|
4437
|
+
const { kind } = root;
|
|
4438
|
+
let entries;
|
|
4439
|
+
try {
|
|
4440
|
+
entries = readdirSync2(root.path, { withFileTypes: true });
|
|
4441
|
+
} catch {
|
|
4442
|
+
let stats;
|
|
4443
|
+
try {
|
|
4444
|
+
stats = statSync(root.path);
|
|
4445
|
+
} catch (err) {
|
|
4446
|
+
if (listed || err.code !== "ENOENT")
|
|
4447
|
+
state.incomplete = true;
|
|
4448
|
+
else state.absentRoots += 1;
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4451
|
+
if (stats.isDirectory()) {
|
|
4452
|
+
state.incomplete = true;
|
|
4453
|
+
return;
|
|
4454
|
+
}
|
|
4455
|
+
if (stats.isFile() && isDigestedFile(kind, basename3(root.path)))
|
|
4456
|
+
yield root.path;
|
|
4457
|
+
return;
|
|
4458
|
+
}
|
|
4459
|
+
for (const e of entries) {
|
|
4460
|
+
const full = join5(root.path, e.name);
|
|
4461
|
+
if (e.isDirectory()) {
|
|
4462
|
+
if (kind !== "code" || !NOT_BUNDLED_DIR.has(e.name))
|
|
4463
|
+
yield* sourceFilesUnder({ path: full, kind }, state, true);
|
|
4464
|
+
} else if (e.isFile() && isDigestedFile(kind, e.name)) {
|
|
4465
|
+
yield full;
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
__name(sourceFilesUnder, "sourceFilesUnder");
|
|
4470
|
+
function reviewSourceRoots(repoRoot) {
|
|
4471
|
+
const cli = join5(repoRoot, "packages", "cli", "src", "commands");
|
|
4472
|
+
return [
|
|
4473
|
+
{ path: join5(cli, "review"), kind: "code" },
|
|
4474
|
+
// The parent file, which is where every subcommand is registered — a new
|
|
4475
|
+
// command, or a changed dispatch, lives here and nowhere under `review/`.
|
|
4476
|
+
// A root may be a single file for exactly this reason.
|
|
4477
|
+
{ path: join5(cli, "review.ts"), kind: "code" },
|
|
4478
|
+
// The worktree lease is review-only code that lives outside `review/`:
|
|
4479
|
+
// `fetch-pr` and `cleanup` import it from `services/`, so an edit to it
|
|
4480
|
+
// with a skipped rebuild is the same silent failure this check exists
|
|
4481
|
+
// for. The two shared files the closure also reaches (`stdioHelpers.ts`,
|
|
4482
|
+
// `skill-args-file.ts`) stay out for the reason SCOPE gives.
|
|
4483
|
+
{
|
|
4484
|
+
path: join5(
|
|
4485
|
+
repoRoot,
|
|
4486
|
+
"packages",
|
|
4487
|
+
"cli",
|
|
4488
|
+
"src",
|
|
4489
|
+
"services",
|
|
4490
|
+
"review-worktree-lease.ts"
|
|
4491
|
+
),
|
|
4492
|
+
kind: "code"
|
|
4493
|
+
},
|
|
4494
|
+
{
|
|
4495
|
+
path: join5(
|
|
4496
|
+
repoRoot,
|
|
4497
|
+
"packages",
|
|
4498
|
+
"core",
|
|
4499
|
+
"src",
|
|
4500
|
+
"skills",
|
|
4501
|
+
"bundled",
|
|
4502
|
+
"review"
|
|
4503
|
+
),
|
|
4504
|
+
kind: "skill"
|
|
4505
|
+
}
|
|
4506
|
+
];
|
|
4507
|
+
}
|
|
4508
|
+
__name(reviewSourceRoots, "reviewSourceRoots");
|
|
4509
|
+
function bundleStalenessNotices(entryPath, brief) {
|
|
4510
|
+
try {
|
|
4511
|
+
if (!entryPath) return void 0;
|
|
4512
|
+
let entry = entryPath;
|
|
4513
|
+
try {
|
|
4514
|
+
entry = realpathSync(entryPath);
|
|
4515
|
+
} catch {
|
|
4516
|
+
}
|
|
4517
|
+
const distDir = dirname(resolve3(entry));
|
|
4518
|
+
if (basename3(distDir) !== "dist") return void 0;
|
|
4519
|
+
const repoRoot = dirname(distDir);
|
|
4520
|
+
let stamped;
|
|
4521
|
+
try {
|
|
4522
|
+
const raw = readFileSync3(join5(distDir, DIGEST_FILE), "utf8").trim();
|
|
4523
|
+
if (/^[0-9a-f]{64}$/.test(raw)) stamped = raw;
|
|
4524
|
+
} catch {
|
|
4525
|
+
}
|
|
4526
|
+
const roots = reviewSourceRoots(repoRoot);
|
|
4527
|
+
const measured = measureReviewSources(repoRoot, roots);
|
|
4528
|
+
const current = measured.digest;
|
|
4529
|
+
if (stamped && current && measured.partial) {
|
|
4530
|
+
return `review: could not check whether the bundle is current \u2014 only some of the review sources are present` + (brief ? " (a partial checkout)." : " (a sparse or partial checkout). The stamp covers the whole tree; materialize the missing sources to compare again.");
|
|
4531
|
+
}
|
|
4532
|
+
const staleness = bundleStaleness(stamped, current);
|
|
4533
|
+
const warning = staleBundleWarning(staleness, brief);
|
|
4534
|
+
if (warning) return warning;
|
|
4535
|
+
if (stamped && !current && (measured.incomplete || roots.some((r) => existsSync3(r.path)))) {
|
|
4536
|
+
const reason = measured.incomplete ? "a review source could not be read, so nothing was compared" + (brief ? "." : ". Re-run once the tree is settled.") : `${staleness.unmeasured}.`;
|
|
4537
|
+
return `review: could not check whether the bundle is current \u2014 ${reason}`;
|
|
4538
|
+
}
|
|
4539
|
+
if (!stamped && current) {
|
|
4540
|
+
return `review: could not check whether the bundle is current \u2014 ${staleness.unmeasured}. ` + (brief ? "Rebuild with `npm run bundle` to record one." : "Either it was built before this check existed, or the build declined to record one; rebuild with `npm run bundle` and, if the line persists, read that build's output for why it refused.");
|
|
4541
|
+
}
|
|
4542
|
+
return void 0;
|
|
4543
|
+
} catch {
|
|
4544
|
+
return void 0;
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
__name(bundleStalenessNotices, "bundleStalenessNotices");
|
|
4548
|
+
function staleBundleWarning(s, brief) {
|
|
4549
|
+
if (!s.stale) return void 0;
|
|
4550
|
+
if (brief) {
|
|
4551
|
+
return `review: the bundle these commands run from was NOT built from the review sources in this tree \u2014 rebuild with \`npm run bundle\` and start again, or read every result below as being about the older build.`;
|
|
4552
|
+
}
|
|
4553
|
+
return `review: the bundle these commands run from was NOT built from the review sources in this tree. Every \`qwen review \u2026\` step below runs the BUILT bundle, not the working tree, so a review source changed since that build will not take effect and this run will measure the old behaviour without saying so. Rebuild with \`npm run bundle\` and start again, or read every result below as being about the older build.`;
|
|
4554
|
+
}
|
|
4555
|
+
__name(staleBundleWarning, "staleBundleWarning");
|
|
4556
|
+
|
|
4557
|
+
// packages/cli/src/commands/review/parse-args.ts
|
|
4341
4558
|
var EFFORT_LEVELS = /* @__PURE__ */ new Set([
|
|
4342
4559
|
"low",
|
|
4343
4560
|
"medium",
|
|
@@ -4604,100 +4821,467 @@ var parseArgsCommand = {
|
|
|
4604
4821
|
`parse-args: unexpected extra argument(s) ${JSON.stringify(unbound)} \u2014 a raw string that begins with a flag must be passed via --stdin, not after --`
|
|
4605
4822
|
);
|
|
4606
4823
|
}
|
|
4607
|
-
const rawStr = stdin ?
|
|
4824
|
+
const rawStr = stdin ? readFileSync4(0, "utf8").replace(/\r?\n$/, "") : raw ?? "";
|
|
4825
|
+
const bundleNotice = bundleStalenessNotices(process.argv[1]);
|
|
4826
|
+
if (bundleNotice) {
|
|
4827
|
+
writeStderrLineSafe(bundleNotice);
|
|
4828
|
+
}
|
|
4608
4829
|
const parsed = parseReviewArgs(rawStr);
|
|
4609
4830
|
const json = JSON.stringify(parsed, null, 2);
|
|
4610
4831
|
if (out) {
|
|
4611
|
-
mkdirSync2(
|
|
4832
|
+
mkdirSync2(dirname2(out), { recursive: true });
|
|
4612
4833
|
writeFileSync2(out, json, "utf8");
|
|
4613
4834
|
}
|
|
4614
4835
|
writeStdoutLine(json);
|
|
4615
4836
|
}, "handler")
|
|
4616
4837
|
};
|
|
4617
4838
|
|
|
4618
|
-
// packages/cli/src/commands/review/
|
|
4619
|
-
init_esbuild_shims();
|
|
4620
|
-
import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
4621
|
-
import { dirname as dirname4, join as join9 } from "node:path";
|
|
4622
|
-
|
|
4623
|
-
// packages/cli/src/commands/review/lib/coverage.ts
|
|
4839
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
4624
4840
|
init_esbuild_shims();
|
|
4625
|
-
import { readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
4626
4841
|
|
|
4627
|
-
// packages/cli/src/commands/review/lib/
|
|
4842
|
+
// packages/cli/src/commands/review/lib/gh.ts
|
|
4628
4843
|
init_esbuild_shims();
|
|
4629
|
-
import {
|
|
4630
|
-
|
|
4631
|
-
var
|
|
4632
|
-
|
|
4633
|
-
|
|
4844
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4845
|
+
var MAX_RETRIES = 2;
|
|
4846
|
+
var BASE_DELAY_MS = 3e3;
|
|
4847
|
+
function sleepSync(ms) {
|
|
4848
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
4849
|
+
}
|
|
4850
|
+
__name(sleepSync, "sleepSync");
|
|
4851
|
+
var TRANSIENT_RE = /HTTP 5\d{2}|server is currently unavailable|service unavailable|bad gateway|internal server error/i;
|
|
4852
|
+
function isTransientGhError(err) {
|
|
4853
|
+
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
4854
|
+
const msg = err instanceof Error ? err.message : "";
|
|
4855
|
+
return TRANSIENT_RE.test(stderr) || TRANSIENT_RE.test(msg);
|
|
4856
|
+
}
|
|
4857
|
+
__name(isTransientGhError, "isTransientGhError");
|
|
4858
|
+
function execGhWithRetry(args, options) {
|
|
4859
|
+
const execOptions = {
|
|
4860
|
+
encoding: "utf8",
|
|
4861
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4862
|
+
env: ghEnv(),
|
|
4863
|
+
...options.input !== void 0 ? { input: options.input } : {}
|
|
4864
|
+
};
|
|
4865
|
+
for (let attempt = 0; ; attempt++) {
|
|
4866
|
+
try {
|
|
4867
|
+
return execFileSync2("gh", args, execOptions).replace(/\r\n/g, "\n").trim();
|
|
4868
|
+
} catch (err) {
|
|
4869
|
+
if (attempt < MAX_RETRIES && isTransientGhError(err)) {
|
|
4870
|
+
const delay = BASE_DELAY_MS * (attempt + 1);
|
|
4871
|
+
process.stderr.write(
|
|
4872
|
+
`gh transient error (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms\u2026
|
|
4873
|
+
`
|
|
4874
|
+
);
|
|
4875
|
+
sleepSync(delay);
|
|
4876
|
+
continue;
|
|
4877
|
+
}
|
|
4878
|
+
throw err;
|
|
4879
|
+
}
|
|
4634
4880
|
}
|
|
4635
|
-
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4881
|
+
}
|
|
4882
|
+
__name(execGhWithRetry, "execGhWithRetry");
|
|
4883
|
+
var ghHost;
|
|
4884
|
+
var HOSTNAME_RE = /^[A-Za-z0-9.-]+(?::\d+)?$/;
|
|
4885
|
+
function setGhHost(host) {
|
|
4886
|
+
if (host === void 0 || host === "") {
|
|
4887
|
+
ghHost = void 0;
|
|
4888
|
+
return;
|
|
4889
|
+
}
|
|
4890
|
+
if (!HOSTNAME_RE.test(host)) {
|
|
4891
|
+
throw new TypeError(
|
|
4892
|
+
`--host must be a hostname (optionally :port), got ${JSON.stringify(host)}`
|
|
4642
4893
|
);
|
|
4643
4894
|
}
|
|
4644
|
-
|
|
4645
|
-
projectDir,
|
|
4646
|
-
sessionId,
|
|
4647
|
-
dir: join5(projectDir, "subagents", sessionId)
|
|
4648
|
-
};
|
|
4895
|
+
ghHost = host;
|
|
4649
4896
|
}
|
|
4650
|
-
__name(
|
|
4651
|
-
function
|
|
4652
|
-
return
|
|
4897
|
+
__name(setGhHost, "setGhHost");
|
|
4898
|
+
function getGhHost() {
|
|
4899
|
+
return ghHost;
|
|
4653
4900
|
}
|
|
4654
|
-
__name(
|
|
4655
|
-
function
|
|
4656
|
-
|
|
4657
|
-
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
4658
|
-
return parts.map((p) => p.text).filter((t2) => typeof t2 === "string").join("");
|
|
4901
|
+
__name(getGhHost, "getGhHost");
|
|
4902
|
+
function resolveGhHost(flagHost) {
|
|
4903
|
+
return flagHost ?? (process.env["GH_HOST"]?.trim() || void 0);
|
|
4659
4904
|
}
|
|
4660
|
-
__name(
|
|
4661
|
-
function
|
|
4662
|
-
|
|
4663
|
-
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
4905
|
+
__name(resolveGhHost, "resolveGhHost");
|
|
4906
|
+
function ghEnv() {
|
|
4907
|
+
return ghHost ? { ...process.env, GH_HOST: ghHost } : void 0;
|
|
4664
4908
|
}
|
|
4665
|
-
__name(
|
|
4666
|
-
function
|
|
4667
|
-
|
|
4668
|
-
const limit = args["limit"];
|
|
4669
|
-
if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
|
|
4670
|
-
return null;
|
|
4671
|
-
}
|
|
4672
|
-
const off = typeof offset === "number" && Number.isInteger(offset) && offset >= 0 ? offset : 0;
|
|
4673
|
-
return [off + 1, off + limit];
|
|
4909
|
+
__name(ghEnv, "ghEnv");
|
|
4910
|
+
function gh(...args) {
|
|
4911
|
+
return execGhWithRetry(args, {});
|
|
4674
4912
|
}
|
|
4675
|
-
__name(
|
|
4676
|
-
function
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
const
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4913
|
+
__name(gh, "gh");
|
|
4914
|
+
function ghWithInputRetried(input, ...args) {
|
|
4915
|
+
return execGhWithRetry(args, { input });
|
|
4916
|
+
}
|
|
4917
|
+
__name(ghWithInputRetried, "ghWithInputRetried");
|
|
4918
|
+
function ghWithInput(input, ...args) {
|
|
4919
|
+
return execFileSync2("gh", args, {
|
|
4920
|
+
encoding: "utf8",
|
|
4921
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4922
|
+
env: ghEnv(),
|
|
4923
|
+
input
|
|
4924
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
4925
|
+
}
|
|
4926
|
+
__name(ghWithInput, "ghWithInput");
|
|
4927
|
+
function ghApiAll(path3) {
|
|
4928
|
+
const out = gh("api", "--paginate", path3);
|
|
4929
|
+
if (!out) return [];
|
|
4930
|
+
const parsed = JSON.parse(out);
|
|
4931
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4932
|
+
}
|
|
4933
|
+
__name(ghApiAll, "ghApiAll");
|
|
4934
|
+
function ghApiAllNested(path3, key) {
|
|
4935
|
+
return parseNdjson(gh("api", "--paginate", path3, "--jq", `.${key}[]`), {
|
|
4936
|
+
strict: true
|
|
4937
|
+
});
|
|
4938
|
+
}
|
|
4939
|
+
__name(ghApiAllNested, "ghApiAllNested");
|
|
4940
|
+
function parseNdjson(out, opts = {}) {
|
|
4941
|
+
const strict = opts.strict ?? true;
|
|
4942
|
+
if (!out) return [];
|
|
4943
|
+
const values = [];
|
|
4944
|
+
for (const line of out.split("\n")) {
|
|
4945
|
+
if (line.trim().length === 0) continue;
|
|
4946
|
+
if (strict) {
|
|
4947
|
+
values.push(JSON.parse(line));
|
|
4948
|
+
continue;
|
|
4949
|
+
}
|
|
4950
|
+
try {
|
|
4951
|
+
values.push(JSON.parse(line));
|
|
4952
|
+
} catch {
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
return values;
|
|
4956
|
+
}
|
|
4957
|
+
__name(parseNdjson, "parseNdjson");
|
|
4958
|
+
function currentUser() {
|
|
4959
|
+
return gh("api", "user", "--jq", ".login");
|
|
4960
|
+
}
|
|
4961
|
+
__name(currentUser, "currentUser");
|
|
4962
|
+
function ensureAuthenticated() {
|
|
4963
|
+
for (let attempt = 0; ; attempt++) {
|
|
4964
|
+
try {
|
|
4965
|
+
execFileSync2("gh", ["auth", "status"], { stdio: "pipe", env: ghEnv() });
|
|
4966
|
+
return;
|
|
4967
|
+
} catch (err) {
|
|
4968
|
+
if (attempt === 0 && err.code !== "ENOENT") {
|
|
4969
|
+
sleepSync(2e3);
|
|
4970
|
+
continue;
|
|
4971
|
+
}
|
|
4972
|
+
throw new Error(
|
|
4973
|
+
"gh CLI is not authenticated. Run `gh auth login` and retry."
|
|
4974
|
+
);
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
__name(ensureAuthenticated, "ensureAuthenticated");
|
|
4979
|
+
|
|
4980
|
+
// packages/cli/src/commands/review/lib/git.ts
|
|
4981
|
+
init_esbuild_shims();
|
|
4982
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
4983
|
+
import { existsSync as existsSync4, rmSync as rmSync2 } from "node:fs";
|
|
4984
|
+
var GIT_TIMEOUT_MS2 = 12e4;
|
|
4985
|
+
function gitOpts() {
|
|
4986
|
+
return {
|
|
4987
|
+
timeout: GIT_TIMEOUT_MS2,
|
|
4988
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
4989
|
+
};
|
|
4990
|
+
}
|
|
4991
|
+
__name(gitOpts, "gitOpts");
|
|
4992
|
+
function git(...args) {
|
|
4993
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8" }).replace(/\r\n/g, "\n").trim();
|
|
4994
|
+
}
|
|
4995
|
+
__name(git, "git");
|
|
4996
|
+
function gitWithInput(input, args) {
|
|
4997
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8", input }).replace(/\r\n/g, "\n").trim();
|
|
4998
|
+
}
|
|
4999
|
+
__name(gitWithInput, "gitWithInput");
|
|
5000
|
+
function gitOpt(...args) {
|
|
5001
|
+
try {
|
|
5002
|
+
return execFileSync3("git", args, {
|
|
5003
|
+
...gitOpts(),
|
|
5004
|
+
encoding: "utf8",
|
|
5005
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5006
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
5007
|
+
} catch {
|
|
5008
|
+
return null;
|
|
5009
|
+
}
|
|
5010
|
+
}
|
|
5011
|
+
__name(gitOpt, "gitOpt");
|
|
5012
|
+
function refExists(ref) {
|
|
5013
|
+
return gitOpt("rev-parse", "--verify", "--quiet", ref) !== null;
|
|
5014
|
+
}
|
|
5015
|
+
__name(refExists, "refExists");
|
|
5016
|
+
function worktreeReleaseResult(existed, stillThere, removeError) {
|
|
5017
|
+
const freed = existed && !stillThere;
|
|
5018
|
+
if (!existed || freed) {
|
|
5019
|
+
return { existed, freed, reason: void 0 };
|
|
5020
|
+
}
|
|
5021
|
+
return {
|
|
5022
|
+
existed,
|
|
5023
|
+
freed,
|
|
5024
|
+
reason: removeError ? removeError instanceof Error ? removeError.message : String(removeError) : "the path is still there after `git worktree remove --force` and `rm -rf`"
|
|
5025
|
+
};
|
|
5026
|
+
}
|
|
5027
|
+
__name(worktreeReleaseResult, "worktreeReleaseResult");
|
|
5028
|
+
function releaseWorktree(worktreePath2) {
|
|
5029
|
+
const existed = existsSync4(worktreePath2);
|
|
5030
|
+
let removeError;
|
|
5031
|
+
if (existed) {
|
|
5032
|
+
gitOpt("worktree", "remove", worktreePath2, "--force");
|
|
5033
|
+
try {
|
|
5034
|
+
rmSync2(worktreePath2, { recursive: true, force: true });
|
|
5035
|
+
} catch (e) {
|
|
5036
|
+
removeError = e;
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
gitOpt("worktree", "prune");
|
|
5040
|
+
return worktreeReleaseResult(existed, existsSync4(worktreePath2), removeError);
|
|
5041
|
+
}
|
|
5042
|
+
__name(releaseWorktree, "releaseWorktree");
|
|
5043
|
+
function gitRaw(...args) {
|
|
5044
|
+
return execFileSync3("git", args, {
|
|
5045
|
+
...gitOpts(),
|
|
5046
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
5047
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5048
|
+
});
|
|
5049
|
+
}
|
|
5050
|
+
__name(gitRaw, "gitRaw");
|
|
5051
|
+
function gitRawTolerateDiff(...args) {
|
|
5052
|
+
try {
|
|
5053
|
+
return gitRaw(...args);
|
|
5054
|
+
} catch (err) {
|
|
5055
|
+
const e = err;
|
|
5056
|
+
if (e.status === 1 && e.stdout && e.stdout.length > 0) return e.stdout;
|
|
5057
|
+
throw err;
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
__name(gitRawTolerateDiff, "gitRawTolerateDiff");
|
|
5061
|
+
|
|
5062
|
+
// packages/cli/src/commands/review/lib/remote-match.ts
|
|
5063
|
+
init_esbuild_shims();
|
|
5064
|
+
function normalizeSegment(value) {
|
|
5065
|
+
const v = value.toLowerCase();
|
|
5066
|
+
return v.endsWith(".git") ? v.slice(0, -4) : v;
|
|
5067
|
+
}
|
|
5068
|
+
__name(normalizeSegment, "normalizeSegment");
|
|
5069
|
+
function parseRemoteUrl(raw) {
|
|
5070
|
+
const url = raw.trim();
|
|
5071
|
+
if (url === "") return null;
|
|
5072
|
+
let host;
|
|
5073
|
+
let pathPart;
|
|
5074
|
+
const schemeIdx = url.indexOf("://");
|
|
5075
|
+
if (schemeIdx !== -1) {
|
|
5076
|
+
let parsed;
|
|
5077
|
+
try {
|
|
5078
|
+
parsed = new URL(url);
|
|
5079
|
+
} catch {
|
|
5080
|
+
return null;
|
|
5081
|
+
}
|
|
5082
|
+
if (parsed.hostname === "") return null;
|
|
5083
|
+
host = parsed.hostname;
|
|
5084
|
+
pathPart = parsed.pathname;
|
|
5085
|
+
} else {
|
|
5086
|
+
const colonIdx = url.indexOf(":");
|
|
5087
|
+
const slashIdx = url.indexOf("/");
|
|
5088
|
+
if (colonIdx === -1 || slashIdx === -1 || colonIdx > slashIdx) {
|
|
5089
|
+
return null;
|
|
5090
|
+
}
|
|
5091
|
+
host = url.slice(0, colonIdx);
|
|
5092
|
+
const atIdx = host.lastIndexOf("@");
|
|
5093
|
+
if (atIdx !== -1) host = host.slice(atIdx + 1);
|
|
5094
|
+
pathPart = url.slice(colonIdx + 1);
|
|
5095
|
+
}
|
|
5096
|
+
const segments = pathPart.split("/").map((s) => s.trim()).filter((s) => s !== "");
|
|
5097
|
+
if (segments.length !== 2) return null;
|
|
5098
|
+
if (host === "") return null;
|
|
5099
|
+
return {
|
|
5100
|
+
host: host.toLowerCase(),
|
|
5101
|
+
owner: normalizeSegment(segments[0]),
|
|
5102
|
+
repo: normalizeSegment(segments[1])
|
|
5103
|
+
};
|
|
5104
|
+
}
|
|
5105
|
+
__name(parseRemoteUrl, "parseRemoteUrl");
|
|
5106
|
+
function matchRemotes(remoteVOutput, { owner, repo, host = "github.com" }) {
|
|
5107
|
+
const wantOwner = normalizeSegment(owner);
|
|
5108
|
+
const wantRepo = normalizeSegment(repo);
|
|
5109
|
+
const wantHost = normalizeSegment(host.replace(/:\d+$/, ""));
|
|
5110
|
+
const matched = [];
|
|
5111
|
+
for (const line of remoteVOutput.split("\n")) {
|
|
5112
|
+
const trimmed = line.trim();
|
|
5113
|
+
if (trimmed === "" || !/\(fetch\)(\s+\[[^\]]*\])?$/.test(trimmed)) {
|
|
5114
|
+
continue;
|
|
5115
|
+
}
|
|
5116
|
+
const nameMatch = trimmed.match(
|
|
5117
|
+
/^(\S+)\s+(.*)\s+\(fetch\)(\s+\[[^\]]*\])?$/
|
|
5118
|
+
);
|
|
5119
|
+
if (!nameMatch) continue;
|
|
5120
|
+
const identity = parseRemoteUrl(nameMatch[2]);
|
|
5121
|
+
if (identity === null) continue;
|
|
5122
|
+
if (identity.host === wantHost && identity.owner === wantOwner && identity.repo === wantRepo) {
|
|
5123
|
+
matched.push(nameMatch[1]);
|
|
5124
|
+
}
|
|
5125
|
+
}
|
|
5126
|
+
return { matched };
|
|
5127
|
+
}
|
|
5128
|
+
__name(matchRemotes, "matchRemotes");
|
|
5129
|
+
|
|
5130
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
5131
|
+
function runMatchRemote(args) {
|
|
5132
|
+
try {
|
|
5133
|
+
git("rev-parse", "--is-inside-work-tree");
|
|
5134
|
+
} catch (err) {
|
|
5135
|
+
writeStderrLineSafe(
|
|
5136
|
+
`match-remote: git cannot resolve this repository: ${err.message}`
|
|
5137
|
+
);
|
|
5138
|
+
process.exitCode = 1;
|
|
5139
|
+
return;
|
|
5140
|
+
}
|
|
5141
|
+
const host = resolveGhHost(args.host) ?? "github.com";
|
|
5142
|
+
let remoteV;
|
|
5143
|
+
try {
|
|
5144
|
+
remoteV = git("remote", "-v");
|
|
5145
|
+
} catch (err) {
|
|
5146
|
+
writeStderrLineSafe(
|
|
5147
|
+
`match-remote: \`git remote -v\` failed: ${err.message}`
|
|
5148
|
+
);
|
|
5149
|
+
process.exitCode = 1;
|
|
5150
|
+
return;
|
|
5151
|
+
}
|
|
5152
|
+
const { matched } = matchRemotes(remoteV, {
|
|
5153
|
+
owner: args.owner,
|
|
5154
|
+
repo: args.repo,
|
|
5155
|
+
host
|
|
5156
|
+
});
|
|
5157
|
+
if (matched.length === 1) {
|
|
5158
|
+
writeStdoutLine(matched[0]);
|
|
5159
|
+
return;
|
|
5160
|
+
}
|
|
5161
|
+
if (matched.length === 0) {
|
|
5162
|
+
writeStdoutLine("none");
|
|
5163
|
+
writeStderrLineSafe(
|
|
5164
|
+
`match-remote: no remote matches ${host}/${args.owner}/${args.repo} by exact host + owner/repo equality \u2014 the PR is not served by any remote of this repository.`
|
|
5165
|
+
);
|
|
5166
|
+
process.exitCode = 6;
|
|
5167
|
+
return;
|
|
5168
|
+
}
|
|
5169
|
+
for (const name of matched) {
|
|
5170
|
+
writeStdoutLine(name);
|
|
5171
|
+
}
|
|
5172
|
+
writeStderrLineSafe(
|
|
5173
|
+
`warning: ${matched.length} remotes match ${host}/${args.owner}/${args.repo} (${matched.join(", ")}); refusing to pick one \u2014 the review stops here.`
|
|
5174
|
+
);
|
|
5175
|
+
process.exitCode = 7;
|
|
5176
|
+
}
|
|
5177
|
+
__name(runMatchRemote, "runMatchRemote");
|
|
5178
|
+
var matchRemoteCommand = {
|
|
5179
|
+
command: "match-remote",
|
|
5180
|
+
describe: "Print the git remote whose URL matches an owner/repo by exact host + owner/repo equality (exit 6 when none, exit 7 when several)",
|
|
5181
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.option("owner", {
|
|
5182
|
+
type: "string",
|
|
5183
|
+
demandOption: true,
|
|
5184
|
+
describe: "The repository owner (from the PR URL, or `gh repo view`)"
|
|
5185
|
+
}).option("repo", {
|
|
5186
|
+
type: "string",
|
|
5187
|
+
demandOption: true,
|
|
5188
|
+
describe: "The repository name"
|
|
5189
|
+
}).option("host", {
|
|
5190
|
+
type: "string",
|
|
5191
|
+
describe: "The PR's host \u2014 from its URL, or from `gh repo view` for a bare number (omitted: inherit an operator-exported GH_HOST, else github.com)"
|
|
5192
|
+
}), "builder"),
|
|
5193
|
+
handler: /* @__PURE__ */ __name((argv) => {
|
|
5194
|
+
runMatchRemote({
|
|
5195
|
+
owner: String(argv["owner"]),
|
|
5196
|
+
repo: String(argv["repo"]),
|
|
5197
|
+
host: argv.host
|
|
5198
|
+
});
|
|
5199
|
+
}, "handler")
|
|
5200
|
+
};
|
|
5201
|
+
|
|
5202
|
+
// packages/cli/src/commands/review/compose-review.ts
|
|
5203
|
+
init_esbuild_shims();
|
|
5204
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
5205
|
+
import { dirname as dirname5, join as join10 } from "node:path";
|
|
5206
|
+
|
|
5207
|
+
// packages/cli/src/commands/review/lib/coverage.ts
|
|
5208
|
+
init_esbuild_shims();
|
|
5209
|
+
import { readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
|
|
5210
|
+
|
|
5211
|
+
// packages/cli/src/commands/review/lib/transcripts.ts
|
|
5212
|
+
init_esbuild_shims();
|
|
5213
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
5214
|
+
import { join as join6 } from "node:path";
|
|
5215
|
+
var TranscriptsUnavailableError = class extends Error {
|
|
5216
|
+
static {
|
|
5217
|
+
__name(this, "TranscriptsUnavailableError");
|
|
5218
|
+
}
|
|
5219
|
+
};
|
|
5220
|
+
function transcriptPaths(env = process.env) {
|
|
5221
|
+
const projectDir = env["QWEN_CODE_PROJECT_DIR"]?.trim();
|
|
5222
|
+
const sessionId = env["QWEN_CODE_SESSION_ID"]?.trim();
|
|
5223
|
+
if (!projectDir || !sessionId) {
|
|
5224
|
+
throw new TranscriptsUnavailableError(
|
|
5225
|
+
"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"
|
|
5226
|
+
);
|
|
5227
|
+
}
|
|
5228
|
+
return {
|
|
5229
|
+
projectDir,
|
|
5230
|
+
sessionId,
|
|
5231
|
+
dir: join6(projectDir, "subagents", sessionId)
|
|
5232
|
+
};
|
|
5233
|
+
}
|
|
5234
|
+
__name(transcriptPaths, "transcriptPaths");
|
|
5235
|
+
function transcriptDir(env = process.env) {
|
|
5236
|
+
return transcriptPaths(env).dir;
|
|
5237
|
+
}
|
|
5238
|
+
__name(transcriptDir, "transcriptDir");
|
|
5239
|
+
function textOf(rec) {
|
|
5240
|
+
const msg = rec["message"];
|
|
5241
|
+
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
5242
|
+
return parts.map((p) => p.text).filter((t2) => typeof t2 === "string").join("");
|
|
5243
|
+
}
|
|
5244
|
+
__name(textOf, "textOf");
|
|
5245
|
+
function isErrorPart(part) {
|
|
5246
|
+
const resp = part.functionResponse?.response;
|
|
5247
|
+
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
5248
|
+
}
|
|
5249
|
+
__name(isErrorPart, "isErrorPart");
|
|
5250
|
+
function rangeOf(args) {
|
|
5251
|
+
const offset = args["offset"];
|
|
5252
|
+
const limit = args["limit"];
|
|
5253
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
|
|
5254
|
+
return null;
|
|
5255
|
+
}
|
|
5256
|
+
const off = typeof offset === "number" && Number.isInteger(offset) && offset >= 0 ? offset : 0;
|
|
5257
|
+
return [off + 1, off + limit];
|
|
5258
|
+
}
|
|
5259
|
+
__name(rangeOf, "rangeOf");
|
|
5260
|
+
function parseTranscript(file, diffPath) {
|
|
5261
|
+
let raw;
|
|
5262
|
+
try {
|
|
5263
|
+
raw = readFileSync5(file, "utf8");
|
|
5264
|
+
} catch {
|
|
5265
|
+
return null;
|
|
5266
|
+
}
|
|
5267
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
5268
|
+
if (lines.length === 0) return null;
|
|
5269
|
+
let agentId = "";
|
|
5270
|
+
let agentName = "";
|
|
5271
|
+
let launchPrompt = "";
|
|
5272
|
+
let finalText = "";
|
|
5273
|
+
let successfulToolCalls = 0;
|
|
5274
|
+
let diffToolCalls = 0;
|
|
5275
|
+
const diffReads = [];
|
|
5276
|
+
const successfulCallArgs = [];
|
|
5277
|
+
const successfulReadFileArgs = [];
|
|
5278
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5279
|
+
const anonymous = [];
|
|
5280
|
+
for (const line of lines) {
|
|
5281
|
+
let rec;
|
|
5282
|
+
try {
|
|
5283
|
+
rec = JSON.parse(line);
|
|
5284
|
+
} catch {
|
|
4701
5285
|
continue;
|
|
4702
5286
|
}
|
|
4703
5287
|
if (!agentId && typeof rec["agentId"] === "string")
|
|
@@ -4753,7 +5337,7 @@ function parseTranscript(file, diffPath) {
|
|
|
4753
5337
|
if (!agentId) return null;
|
|
4754
5338
|
let mtimeMs = 0;
|
|
4755
5339
|
try {
|
|
4756
|
-
mtimeMs =
|
|
5340
|
+
mtimeMs = statSync2(file).mtimeMs;
|
|
4757
5341
|
} catch {
|
|
4758
5342
|
}
|
|
4759
5343
|
return {
|
|
@@ -4771,7 +5355,7 @@ function parseTranscript(file, diffPath) {
|
|
|
4771
5355
|
}
|
|
4772
5356
|
__name(parseTranscript, "parseTranscript");
|
|
4773
5357
|
function listAgentTranscriptFiles(dir) {
|
|
4774
|
-
return
|
|
5358
|
+
return readdirSync3(dir).filter((name) => name.endsWith(".jsonl"));
|
|
4775
5359
|
}
|
|
4776
5360
|
__name(listAgentTranscriptFiles, "listAgentTranscriptFiles");
|
|
4777
5361
|
function readTranscripts(since, env = process.env, diffPath) {
|
|
@@ -4786,7 +5370,7 @@ function readTranscripts(since, env = process.env, diffPath) {
|
|
|
4786
5370
|
}
|
|
4787
5371
|
const out = [];
|
|
4788
5372
|
for (const name of names) {
|
|
4789
|
-
const rec = parseTranscript(
|
|
5373
|
+
const rec = parseTranscript(join6(dir, name), diffPath);
|
|
4790
5374
|
if (!rec) continue;
|
|
4791
5375
|
if (since !== void 0 && rec.mtimeMs < since) continue;
|
|
4792
5376
|
out.push(rec);
|
|
@@ -4805,24 +5389,24 @@ __name(wasGivenTheDiff, "wasGivenTheDiff");
|
|
|
4805
5389
|
init_esbuild_shims();
|
|
4806
5390
|
import {
|
|
4807
5391
|
mkdirSync as mkdirSync3,
|
|
4808
|
-
readFileSync as
|
|
4809
|
-
readdirSync as
|
|
4810
|
-
statSync as
|
|
5392
|
+
readFileSync as readFileSync6,
|
|
5393
|
+
readdirSync as readdirSync4,
|
|
5394
|
+
statSync as statSync3,
|
|
4811
5395
|
writeFileSync as writeFileSync3
|
|
4812
5396
|
} from "node:fs";
|
|
4813
|
-
import { dirname as
|
|
5397
|
+
import { dirname as dirname3, join as join7, basename as basename4, resolve as resolve4 } from "node:path";
|
|
4814
5398
|
function promptRecordDir(planPath) {
|
|
4815
|
-
const p =
|
|
4816
|
-
return
|
|
5399
|
+
const p = resolve4(planPath);
|
|
5400
|
+
return join7(dirname3(p), `${basename4(p).replace(/\.json$/i, "")}-prompts`);
|
|
4817
5401
|
}
|
|
4818
5402
|
__name(promptRecordDir, "promptRecordDir");
|
|
4819
5403
|
var fileFor = /* @__PURE__ */ __name((key) => `${encodeURIComponent(key)}.txt`, "fileFor");
|
|
4820
5404
|
function briefPath(planPath, key) {
|
|
4821
|
-
return
|
|
5405
|
+
return join7(promptRecordDir(planPath), `${encodeURIComponent(key)}.brief.md`);
|
|
4822
5406
|
}
|
|
4823
5407
|
__name(briefPath, "briefPath");
|
|
4824
5408
|
function findingsFilePath(planPath, key) {
|
|
4825
|
-
return
|
|
5409
|
+
return join7(
|
|
4826
5410
|
promptRecordDir(planPath),
|
|
4827
5411
|
`${encodeURIComponent(key)}.findings.md`
|
|
4828
5412
|
);
|
|
@@ -4852,7 +5436,7 @@ function writeBrief(planPath, key, brief) {
|
|
|
4852
5436
|
const p = briefPath(planPath, key);
|
|
4853
5437
|
let hadRules = false;
|
|
4854
5438
|
try {
|
|
4855
|
-
hadRules =
|
|
5439
|
+
hadRules = readFileSync6(p, "utf8").includes(RULES_MARKER);
|
|
4856
5440
|
} catch {
|
|
4857
5441
|
}
|
|
4858
5442
|
if (hadRules && !brief.includes(RULES_MARKER)) {
|
|
@@ -4872,7 +5456,7 @@ function recordPrompt(planPath, key, prompt) {
|
|
|
4872
5456
|
try {
|
|
4873
5457
|
const dir = promptRecordDir(planPath);
|
|
4874
5458
|
mkdirSync3(dir, { recursive: true });
|
|
4875
|
-
writeFileSync3(
|
|
5459
|
+
writeFileSync3(join7(dir, fileFor(key)), prompt);
|
|
4876
5460
|
} catch {
|
|
4877
5461
|
}
|
|
4878
5462
|
}
|
|
@@ -4882,7 +5466,7 @@ function readRecordedPrompts(planPath, sinceMs) {
|
|
|
4882
5466
|
const dir = promptRecordDir(planPath);
|
|
4883
5467
|
let names;
|
|
4884
5468
|
try {
|
|
4885
|
-
names =
|
|
5469
|
+
names = readdirSync4(dir).sort();
|
|
4886
5470
|
} catch {
|
|
4887
5471
|
return out;
|
|
4888
5472
|
}
|
|
@@ -4895,9 +5479,9 @@ function readRecordedPrompts(planPath, sinceMs) {
|
|
|
4895
5479
|
} catch {
|
|
4896
5480
|
continue;
|
|
4897
5481
|
}
|
|
4898
|
-
const file =
|
|
4899
|
-
if (sinceMs !== void 0 &&
|
|
4900
|
-
out.set(key,
|
|
5482
|
+
const file = join7(dir, name);
|
|
5483
|
+
if (sinceMs !== void 0 && statSync3(file).mtimeMs < sinceMs) continue;
|
|
5484
|
+
out.set(key, readFileSync6(file, "utf8"));
|
|
4901
5485
|
} catch {
|
|
4902
5486
|
}
|
|
4903
5487
|
}
|
|
@@ -4963,6 +5547,10 @@ __name(isRepositoryContextRoleId, "isRepositoryContextRoleId");
|
|
|
4963
5547
|
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";
|
|
4964
5548
|
var BRIEFS = {
|
|
4965
5549
|
"0": {
|
|
5550
|
+
// Budget-exempt: Issue-sized mandatory work, not diff-sized: a small bugfix
|
|
5551
|
+
// referencing many issues would exhaust a diff-derived ceiling on
|
|
5552
|
+
// required fetches alone.
|
|
5553
|
+
budgetExempt: true,
|
|
4966
5554
|
label: "Agent 0: Issue fidelity & root-cause ownership",
|
|
4967
5555
|
publicLabel: "the linked-issue fidelity pass",
|
|
4968
5556
|
publicLabelZh: "\u5173\u8054 issue \u4E00\u81F4\u6027\u68C0\u67E5",
|
|
@@ -5253,6 +5841,10 @@ Under that framing, look at:
|
|
|
5253
5841
|
You are undirected on purpose. Do not restrict yourself to the list.`
|
|
5254
5842
|
},
|
|
5255
5843
|
"7": {
|
|
5844
|
+
// Budget-exempt: Deterministic build/test commands — the run costs what the
|
|
5845
|
+
// project scripts cost, and stopping early is the one thing it must
|
|
5846
|
+
// never do.
|
|
5847
|
+
budgetExempt: true,
|
|
5256
5848
|
label: "Agent 7: Build & test verification",
|
|
5257
5849
|
publicLabel: "the build-and-test check",
|
|
5258
5850
|
publicLabelZh: "\u6784\u5EFA\u4E0E\u6D4B\u8BD5\u9A8C\u8BC1",
|
|
@@ -5337,6 +5929,9 @@ This file is largely rewritten, and reviewing it as a diff is the wrong frame. T
|
|
|
5337
5929
|
Report a **Critical** for each violation, and give **both** locations that together make it a bug (\`<file>:<lineA>\` and \`<file>:<lineB>\`), not just one.`
|
|
5338
5930
|
},
|
|
5339
5931
|
verify: {
|
|
5932
|
+
// Budget-exempt: Its per-finding re-trace must not stop early; `verifyShard`
|
|
5933
|
+
// already governs its load.
|
|
5934
|
+
budgetExempt: true,
|
|
5340
5935
|
reviewsCode: true,
|
|
5341
5936
|
output: "verdicts",
|
|
5342
5937
|
acceptsFindings: true,
|
|
@@ -5591,21 +6186,21 @@ __name(repositoryContextOf, "repositoryContextOf");
|
|
|
5591
6186
|
// packages/cli/src/commands/review/script-lint.ts
|
|
5592
6187
|
init_esbuild_shims();
|
|
5593
6188
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
5594
|
-
import { createHash } from "node:crypto";
|
|
6189
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
5595
6190
|
import {
|
|
5596
|
-
readFileSync as
|
|
6191
|
+
readFileSync as readFileSync7,
|
|
5597
6192
|
writeFileSync as writeFileSync4,
|
|
5598
6193
|
mkdirSync as mkdirSync4,
|
|
5599
6194
|
mkdtempSync,
|
|
5600
|
-
rmSync as
|
|
6195
|
+
rmSync as rmSync3,
|
|
5601
6196
|
lstatSync,
|
|
5602
|
-
realpathSync,
|
|
6197
|
+
realpathSync as realpathSync2,
|
|
5603
6198
|
openSync,
|
|
5604
6199
|
readSync,
|
|
5605
6200
|
closeSync
|
|
5606
6201
|
} from "node:fs";
|
|
5607
6202
|
import { tmpdir } from "node:os";
|
|
5608
|
-
import { dirname as
|
|
6203
|
+
import { dirname as dirname4, join as join8, resolve as resolve5, basename as basename5, sep as sep2 } from "node:path";
|
|
5609
6204
|
|
|
5610
6205
|
// packages/cli/src/commands/review/lib/diff-plan.ts
|
|
5611
6206
|
init_esbuild_shims();
|
|
@@ -5986,7 +6581,7 @@ __name(chunksCoverDiff, "chunksCoverDiff");
|
|
|
5986
6581
|
// packages/cli/src/commands/review/script-lint.ts
|
|
5987
6582
|
function pathTool(path3) {
|
|
5988
6583
|
const p = path3.toLowerCase();
|
|
5989
|
-
const base =
|
|
6584
|
+
const base = basename5(p);
|
|
5990
6585
|
if (/(^|\/)\.github\/workflows\/.+\.ya?ml$/.test(p)) {
|
|
5991
6586
|
return "actionlint";
|
|
5992
6587
|
}
|
|
@@ -6035,7 +6630,7 @@ function addedRangesFromDiff(diffText) {
|
|
|
6035
6630
|
__name(addedRangesFromDiff, "addedRangesFromDiff");
|
|
6036
6631
|
function realIfExists(p) {
|
|
6037
6632
|
try {
|
|
6038
|
-
return
|
|
6633
|
+
return realpathSync2(p);
|
|
6039
6634
|
} catch {
|
|
6040
6635
|
return void 0;
|
|
6041
6636
|
}
|
|
@@ -6069,14 +6664,14 @@ var hadolintEmptyConfigPath;
|
|
|
6069
6664
|
function emptyHadolintConfig() {
|
|
6070
6665
|
if (!hadolintEmptyConfigPath) {
|
|
6071
6666
|
try {
|
|
6072
|
-
const d = mkdtempSync(
|
|
6667
|
+
const d = mkdtempSync(join8(tmpdir(), "qwen-review-hadolint-"));
|
|
6073
6668
|
process.on("exit", () => {
|
|
6074
6669
|
try {
|
|
6075
|
-
|
|
6670
|
+
rmSync3(d, { recursive: true, force: true });
|
|
6076
6671
|
} catch {
|
|
6077
6672
|
}
|
|
6078
6673
|
});
|
|
6079
|
-
const p =
|
|
6674
|
+
const p = join8(d, "config.yaml");
|
|
6080
6675
|
writeFileSync4(p, "ignored: []\n");
|
|
6081
6676
|
hadolintEmptyConfigPath = p;
|
|
6082
6677
|
} catch {
|
|
@@ -6185,7 +6780,7 @@ __name(parseFindings, "parseFindings");
|
|
|
6185
6780
|
function diffHashOf(diffPath) {
|
|
6186
6781
|
if (typeof diffPath !== "string" || !diffPath) return void 0;
|
|
6187
6782
|
try {
|
|
6188
|
-
return
|
|
6783
|
+
return createHash2("sha256").update(readFileSync7(diffPath)).digest("hex");
|
|
6189
6784
|
} catch {
|
|
6190
6785
|
return void 0;
|
|
6191
6786
|
}
|
|
@@ -6194,7 +6789,7 @@ __name(diffHashOf, "diffHashOf");
|
|
|
6194
6789
|
function runScriptLint(args, runner = runTool) {
|
|
6195
6790
|
let plan;
|
|
6196
6791
|
try {
|
|
6197
|
-
plan = JSON.parse(
|
|
6792
|
+
plan = JSON.parse(readFileSync7(args.plan, "utf8"));
|
|
6198
6793
|
} catch (err) {
|
|
6199
6794
|
throw new Error(
|
|
6200
6795
|
`script-lint: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -6206,7 +6801,7 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6206
6801
|
let diffBuf;
|
|
6207
6802
|
if (typeof plan.diffPathAbsolute === "string") {
|
|
6208
6803
|
try {
|
|
6209
|
-
diffBuf =
|
|
6804
|
+
diffBuf = readFileSync7(plan.diffPathAbsolute);
|
|
6210
6805
|
} catch {
|
|
6211
6806
|
diffBuf = void 0;
|
|
6212
6807
|
}
|
|
@@ -6214,7 +6809,7 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6214
6809
|
if (diffBuf) {
|
|
6215
6810
|
try {
|
|
6216
6811
|
addedRanges = addedRangesFromDiff(diffBuf.toString("utf8"));
|
|
6217
|
-
diffHash =
|
|
6812
|
+
diffHash = createHash2("sha256").update(diffBuf).digest("hex");
|
|
6218
6813
|
} catch {
|
|
6219
6814
|
addedRanges = /* @__PURE__ */ new Map();
|
|
6220
6815
|
diffHash = void 0;
|
|
@@ -6228,13 +6823,13 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6228
6823
|
const errored = [];
|
|
6229
6824
|
const deferred = [];
|
|
6230
6825
|
const missing = /* @__PURE__ */ new Set();
|
|
6231
|
-
const wt =
|
|
6826
|
+
const wt = resolve5(args.worktree);
|
|
6232
6827
|
const wtReal = realIfExists(wt);
|
|
6233
6828
|
for (const f of files) {
|
|
6234
6829
|
const path3 = typeof f?.path === "string" ? f.path : "";
|
|
6235
6830
|
if (!path3) continue;
|
|
6236
|
-
const abs =
|
|
6237
|
-
const escapes = /* @__PURE__ */ __name((p, root) => p !== root && !p.startsWith(root +
|
|
6831
|
+
const abs = resolve5(join8(args.worktree, path3));
|
|
6832
|
+
const escapes = /* @__PURE__ */ __name((p, root) => p !== root && !p.startsWith(root + sep2), "escapes");
|
|
6238
6833
|
const real = realIfExists(abs);
|
|
6239
6834
|
if (escapes(abs, wt) || wtReal && real && escapes(real, wtReal)) {
|
|
6240
6835
|
const byName = pathTool(path3);
|
|
@@ -6365,7 +6960,7 @@ var scriptLintCommand = {
|
|
|
6365
6960
|
const report = runScriptLint(args);
|
|
6366
6961
|
const json = JSON.stringify(report, null, 2);
|
|
6367
6962
|
if (args.out) {
|
|
6368
|
-
mkdirSync4(
|
|
6963
|
+
mkdirSync4(dirname4(resolve5(args.out)), { recursive: true });
|
|
6369
6964
|
writeFileSync4(args.out, json);
|
|
6370
6965
|
}
|
|
6371
6966
|
writeStdoutLine(json);
|
|
@@ -6496,8 +7091,8 @@ __name(contextRoleRunsInThisReview, "contextRoleRunsInThisReview");
|
|
|
6496
7091
|
|
|
6497
7092
|
// packages/cli/src/commands/review/lib/deadline.ts
|
|
6498
7093
|
init_esbuild_shims();
|
|
6499
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
6500
|
-
import { join as
|
|
7094
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
7095
|
+
import { join as join9 } from "node:path";
|
|
6501
7096
|
var DEADLINE_ENV = "QWEN_REVIEW_DEADLINE_EPOCH";
|
|
6502
7097
|
var RESERVE_ENV = "QWEN_REVIEW_DEADLINE_RESERVE_SECONDS";
|
|
6503
7098
|
var DEFAULT_RESERVE_SECONDS = 4800;
|
|
@@ -6508,7 +7103,7 @@ var STOP_FILE = "budget-stop.json";
|
|
|
6508
7103
|
var RUN_EPOCH_SLACK_MS = 2e3;
|
|
6509
7104
|
function runEpochMs(planPath) {
|
|
6510
7105
|
try {
|
|
6511
|
-
return
|
|
7106
|
+
return statSync4(planPath).mtimeMs - RUN_EPOCH_SLACK_MS;
|
|
6512
7107
|
} catch {
|
|
6513
7108
|
return Number.NEGATIVE_INFINITY;
|
|
6514
7109
|
}
|
|
@@ -6516,8 +7111,8 @@ function runEpochMs(planPath) {
|
|
|
6516
7111
|
__name(runEpochMs, "runEpochMs");
|
|
6517
7112
|
function readRoundStamps(planPath) {
|
|
6518
7113
|
try {
|
|
6519
|
-
const raw =
|
|
6520
|
-
|
|
7114
|
+
const raw = readFileSync8(
|
|
7115
|
+
join9(promptRecordDir(planPath), STAMPS_FILE),
|
|
6521
7116
|
"utf8"
|
|
6522
7117
|
);
|
|
6523
7118
|
const parsed = JSON.parse(raw);
|
|
@@ -6538,7 +7133,7 @@ function stampRound(planPath, round, nowMs = Date.now()) {
|
|
|
6538
7133
|
stamps.push({ round: round ?? null, atMs: nowMs });
|
|
6539
7134
|
const dir = promptRecordDir(planPath);
|
|
6540
7135
|
mkdirSync5(dir, { recursive: true });
|
|
6541
|
-
writeFileSync5(
|
|
7136
|
+
writeFileSync5(join9(dir, STAMPS_FILE), JSON.stringify(stamps));
|
|
6542
7137
|
} catch {
|
|
6543
7138
|
}
|
|
6544
7139
|
}
|
|
@@ -6613,15 +7208,15 @@ function writeBudgetStop(planPath, spent, round, nowMs = Date.now()) {
|
|
|
6613
7208
|
reserveSeconds: spent.reserveSeconds,
|
|
6614
7209
|
atMs: nowMs
|
|
6615
7210
|
};
|
|
6616
|
-
writeFileSync5(
|
|
7211
|
+
writeFileSync5(join9(dir, STOP_FILE), JSON.stringify(stop, null, 2));
|
|
6617
7212
|
} catch {
|
|
6618
7213
|
}
|
|
6619
7214
|
}
|
|
6620
7215
|
__name(writeBudgetStop, "writeBudgetStop");
|
|
6621
7216
|
function readBudgetStop(planPath) {
|
|
6622
7217
|
try {
|
|
6623
|
-
const raw =
|
|
6624
|
-
|
|
7218
|
+
const raw = readFileSync8(
|
|
7219
|
+
join9(promptRecordDir(planPath), STOP_FILE),
|
|
6625
7220
|
"utf8"
|
|
6626
7221
|
);
|
|
6627
7222
|
const parsed = JSON.parse(raw);
|
|
@@ -6643,6 +7238,157 @@ function reverseAuditBudgetMessage(spent, round) {
|
|
|
6643
7238
|
}
|
|
6644
7239
|
__name(reverseAuditBudgetMessage, "reverseAuditBudgetMessage");
|
|
6645
7240
|
|
|
7241
|
+
// packages/cli/src/commands/review/lib/budget.ts
|
|
7242
|
+
init_esbuild_shims();
|
|
7243
|
+
var SWEEP_FLOOR = 25;
|
|
7244
|
+
var SPECIALIST_FLOOR = 80;
|
|
7245
|
+
var LINES_PER_ANGLE = 60;
|
|
7246
|
+
var MIN_INLINE_ANGLES = 3;
|
|
7247
|
+
var MAX_INLINE_ANGLES = 6;
|
|
7248
|
+
var VERIFY_SHARD = 8;
|
|
7249
|
+
var MIN_AGENT_TOOL_BUDGET = 30;
|
|
7250
|
+
var MAX_AGENT_TOOL_BUDGET = 60;
|
|
7251
|
+
var LINES_PER_TOOL_CALL = 20;
|
|
7252
|
+
function reviewBudget(input) {
|
|
7253
|
+
const src = sane(input.srcDiffLines);
|
|
7254
|
+
const total = sane(input.diffLines);
|
|
7255
|
+
const effective = Math.max(src, Math.floor(total / 8));
|
|
7256
|
+
const extraAngles = Math.floor(effective / LINES_PER_ANGLE);
|
|
7257
|
+
const inlineAngles = clamp(
|
|
7258
|
+
MIN_INLINE_ANGLES + extraAngles,
|
|
7259
|
+
MIN_INLINE_ANGLES,
|
|
7260
|
+
MAX_INLINE_ANGLES
|
|
7261
|
+
);
|
|
7262
|
+
return {
|
|
7263
|
+
inlineAngles,
|
|
7264
|
+
sweep: effective >= SWEEP_FLOOR,
|
|
7265
|
+
specialistCap: src >= SPECIALIST_FLOOR ? 2 : 0,
|
|
7266
|
+
verifyShard: VERIFY_SHARD,
|
|
7267
|
+
agentToolBudget: clamp(
|
|
7268
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(effective / LINES_PER_TOOL_CALL),
|
|
7269
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7270
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7271
|
+
)
|
|
7272
|
+
};
|
|
7273
|
+
}
|
|
7274
|
+
__name(reviewBudget, "reviewBudget");
|
|
7275
|
+
var MAX_TOTAL_TOOL_CALLS = 200;
|
|
7276
|
+
function launchToolBudget(planBudget, territoryLines, mandatoryReads) {
|
|
7277
|
+
const base = clamp(
|
|
7278
|
+
sane(planBudget) || MIN_AGENT_TOOL_BUDGET,
|
|
7279
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7280
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7281
|
+
);
|
|
7282
|
+
const allowance = territoryLines === null ? base : Math.min(
|
|
7283
|
+
base,
|
|
7284
|
+
clamp(
|
|
7285
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(sane(territoryLines) / LINES_PER_TOOL_CALL),
|
|
7286
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7287
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7288
|
+
)
|
|
7289
|
+
);
|
|
7290
|
+
return Math.min(
|
|
7291
|
+
MAX_TOTAL_TOOL_CALLS,
|
|
7292
|
+
allowance + Math.max(0, Math.floor(sane(mandatoryReads)))
|
|
7293
|
+
);
|
|
7294
|
+
}
|
|
7295
|
+
__name(launchToolBudget, "launchToolBudget");
|
|
7296
|
+
var BUDGET_GAP_LINE_RE = /^[ \t]*(?:[-*+]|\d+[.)])?[ \t]*(`?)[*_~]{0,3}(?:budget gap|预算(?:缺口|不足|用尽))[*_~]{0,3}[ \t]*[::][*_~]{0,3}[ \t]*(.+?)[ \t]*$/i;
|
|
7297
|
+
var GAP_HINT_RE = /budget gap|预算(?:缺口|不足|用尽)/i;
|
|
7298
|
+
var INLINE_BUDGET_GAP_RE = /(?:budget gap|预算(?:缺口|不足|用尽))[*_~`]{0,3}[ \t]*[::]/i;
|
|
7299
|
+
var PLACEHOLDER_GAP_RE = /^(?:<[^>]*>|none\b.*|n\/a\b.*|nothing\b.*|no (?:gaps?|checks?)\b.*|[-—*_~`]+)$/i;
|
|
7300
|
+
var MAX_GAP_LENGTH = 160;
|
|
7301
|
+
var MAX_GAPS_PER_AGENT = 8;
|
|
7302
|
+
var DANGEROUS_CHARS_RE = (
|
|
7303
|
+
// eslint-disable-next-line no-control-regex
|
|
7304
|
+
/[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e]/g
|
|
7305
|
+
);
|
|
7306
|
+
var WRAPPER_PAIRS = [
|
|
7307
|
+
["**", "**"],
|
|
7308
|
+
["__", "__"],
|
|
7309
|
+
["*", "*"],
|
|
7310
|
+
["_", "_"],
|
|
7311
|
+
["~", "~"],
|
|
7312
|
+
["`", "`"]
|
|
7313
|
+
];
|
|
7314
|
+
function stripWrappers(s) {
|
|
7315
|
+
let out = s;
|
|
7316
|
+
let changed = true;
|
|
7317
|
+
while (changed) {
|
|
7318
|
+
changed = false;
|
|
7319
|
+
for (const [open, close] of WRAPPER_PAIRS) {
|
|
7320
|
+
if (out.length > open.length + close.length && out.startsWith(open) && out.endsWith(close)) {
|
|
7321
|
+
out = out.slice(open.length, out.length - close.length).trim();
|
|
7322
|
+
changed = true;
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
return out;
|
|
7327
|
+
}
|
|
7328
|
+
__name(stripWrappers, "stripWrappers");
|
|
7329
|
+
function truncateGap(s) {
|
|
7330
|
+
const points = [...s];
|
|
7331
|
+
return points.length > MAX_GAP_LENGTH ? `${points.slice(0, MAX_GAP_LENGTH).join("")}\u2026` : s;
|
|
7332
|
+
}
|
|
7333
|
+
__name(truncateGap, "truncateGap");
|
|
7334
|
+
function budgetGapDisclosures(finalText) {
|
|
7335
|
+
if (!GAP_HINT_RE.test(finalText)) return [];
|
|
7336
|
+
const gaps = [];
|
|
7337
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7338
|
+
let inFence = false;
|
|
7339
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7340
|
+
if (/^[ \t]*(?:```|~~~)/.test(line)) {
|
|
7341
|
+
inFence = !inFence;
|
|
7342
|
+
continue;
|
|
7343
|
+
}
|
|
7344
|
+
if (inFence) continue;
|
|
7345
|
+
if (/^[ \t]*>/.test(line)) continue;
|
|
7346
|
+
const m = BUDGET_GAP_LINE_RE.exec(line.replace(DANGEROUS_CHARS_RE, " "));
|
|
7347
|
+
if (!m) continue;
|
|
7348
|
+
let raw = m[2] ?? "";
|
|
7349
|
+
if (m[1] === "`") {
|
|
7350
|
+
if (!raw.endsWith("`")) continue;
|
|
7351
|
+
raw = raw.slice(0, -1);
|
|
7352
|
+
}
|
|
7353
|
+
raw = stripWrappers(raw.trim()).trim();
|
|
7354
|
+
const normalized = raw.replace(/[.!…,;:\s]+$/, "").trim();
|
|
7355
|
+
if (normalized.length === 0 || PLACEHOLDER_GAP_RE.test(normalized)) {
|
|
7356
|
+
continue;
|
|
7357
|
+
}
|
|
7358
|
+
const key = normalized.toLowerCase();
|
|
7359
|
+
if (seen.has(key)) continue;
|
|
7360
|
+
seen.add(key);
|
|
7361
|
+
gaps.push(truncateGap(raw));
|
|
7362
|
+
if (gaps.length >= MAX_GAPS_PER_AGENT) break;
|
|
7363
|
+
}
|
|
7364
|
+
return gaps;
|
|
7365
|
+
}
|
|
7366
|
+
__name(budgetGapDisclosures, "budgetGapDisclosures");
|
|
7367
|
+
function stripBudgetGapLines(finalText) {
|
|
7368
|
+
if (!GAP_HINT_RE.test(finalText)) return finalText;
|
|
7369
|
+
const kept = [];
|
|
7370
|
+
let inFence = false;
|
|
7371
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7372
|
+
const fence = /^[ \t]*(?:```|~~~)/.test(line);
|
|
7373
|
+
if (fence) inFence = !inFence;
|
|
7374
|
+
if (!fence && !inFence && !/^[ \t]*>/.test(line) && BUDGET_GAP_LINE_RE.test(line)) {
|
|
7375
|
+
continue;
|
|
7376
|
+
}
|
|
7377
|
+
kept.push(line);
|
|
7378
|
+
}
|
|
7379
|
+
return kept.join("\n");
|
|
7380
|
+
}
|
|
7381
|
+
__name(stripBudgetGapLines, "stripBudgetGapLines");
|
|
7382
|
+
function sane(n) {
|
|
7383
|
+
const v = Number(n);
|
|
7384
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 0;
|
|
7385
|
+
}
|
|
7386
|
+
__name(sane, "sane");
|
|
7387
|
+
function clamp(v, lo, hi) {
|
|
7388
|
+
return Math.min(hi, Math.max(lo, v));
|
|
7389
|
+
}
|
|
7390
|
+
__name(clamp, "clamp");
|
|
7391
|
+
|
|
6646
7392
|
// packages/cli/src/commands/review/lib/shell-quote.ts
|
|
6647
7393
|
init_esbuild_shims();
|
|
6648
7394
|
function shellQuotePath(p) {
|
|
@@ -6652,7 +7398,7 @@ __name(shellQuotePath, "shellQuotePath");
|
|
|
6652
7398
|
|
|
6653
7399
|
// packages/cli/src/commands/review/lib/coverage.ts
|
|
6654
7400
|
function readPlan(path3) {
|
|
6655
|
-
const plan = JSON.parse(
|
|
7401
|
+
const plan = JSON.parse(readFileSync9(path3, "utf8"));
|
|
6656
7402
|
if (typeof plan?.diffPathAbsolute !== "string" || !plan.diffPathAbsolute) {
|
|
6657
7403
|
throw new Error(`coverage: ${path3} has no diffPathAbsolute`);
|
|
6658
7404
|
}
|
|
@@ -6663,7 +7409,7 @@ function readPlan(path3) {
|
|
|
6663
7409
|
if (problem) {
|
|
6664
7410
|
throw new Error(`coverage: ${path3} has ${problem}`);
|
|
6665
7411
|
}
|
|
6666
|
-
return { plan, mtimeMs:
|
|
7412
|
+
return { plan, mtimeMs: statSync5(path3).mtimeMs };
|
|
6667
7413
|
}
|
|
6668
7414
|
__name(readPlan, "readPlan");
|
|
6669
7415
|
var CHUNK_RE = /\bchunk\s+(\d+)\s+of\s+\d+\b/i;
|
|
@@ -6787,6 +7533,37 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6787
7533
|
return false;
|
|
6788
7534
|
}, "keySatisfied");
|
|
6789
7535
|
const superseded = /* @__PURE__ */ __name((rec, chunk2) => chunk2 !== null ? chunkSatisfied(chunk2, rec) : keySatisfied(rec), "superseded");
|
|
7536
|
+
const gapsMemo = /* @__PURE__ */ new Map();
|
|
7537
|
+
const gapsOf = /* @__PURE__ */ __name((rec) => {
|
|
7538
|
+
let g = gapsMemo.get(rec);
|
|
7539
|
+
if (g === void 0) {
|
|
7540
|
+
g = budgetGapDisclosures(rec.finalText);
|
|
7541
|
+
gapsMemo.set(rec, g);
|
|
7542
|
+
}
|
|
7543
|
+
return g;
|
|
7544
|
+
}, "gapsOf");
|
|
7545
|
+
const gapsSuperseded = /* @__PURE__ */ __name((rec, chunk2) => {
|
|
7546
|
+
if (chunk2 !== null) {
|
|
7547
|
+
const b = builtOf(`chunk-${chunk2}`);
|
|
7548
|
+
if (b === void 0) return false;
|
|
7549
|
+
return records.some(
|
|
7550
|
+
(r) => r !== rec && assignedChunk(r) === chunk2 && wasDeliveredVerbatim(r.launchPrompt, b) && r.diffToolCalls > 0 && gapsOf(r).length === 0
|
|
7551
|
+
);
|
|
7552
|
+
}
|
|
7553
|
+
for (const key of built.keys()) {
|
|
7554
|
+
const b = builtOf(key);
|
|
7555
|
+
if (b === void 0) continue;
|
|
7556
|
+
if (!wasDeliveredVerbatim(rec.launchPrompt, b)) continue;
|
|
7557
|
+
const needle = JSON.stringify(briefPath(planPath, key));
|
|
7558
|
+
if (records.some(
|
|
7559
|
+
(r) => r !== rec && wasDeliveredVerbatim(r.launchPrompt, b) && r.successfulCallArgs.some((a) => a.includes(needle)) && gapsOf(r).length === 0
|
|
7560
|
+
)) {
|
|
7561
|
+
return true;
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
return false;
|
|
7565
|
+
}, "gapsSuperseded");
|
|
7566
|
+
const budgetGaps = [];
|
|
6790
7567
|
for (const rec of records) {
|
|
6791
7568
|
const chunk2 = assignedChunk(rec);
|
|
6792
7569
|
const name = label(rec, chunk2);
|
|
@@ -6844,6 +7621,10 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6844
7621
|
}
|
|
6845
7622
|
continue;
|
|
6846
7623
|
}
|
|
7624
|
+
const gaps = gapsOf(rec);
|
|
7625
|
+
if (gaps.length > 0 && !gapsSuperseded(rec, chunk2)) {
|
|
7626
|
+
budgetGaps.push({ agent: name, gaps });
|
|
7627
|
+
}
|
|
6847
7628
|
const ranges = merge([...told, ...rec.diffReads]);
|
|
6848
7629
|
if (ranges.length === 0) continue;
|
|
6849
7630
|
const u = UNCOVERABLE_RE.exec(rec.finalText);
|
|
@@ -7001,6 +7782,7 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
7001
7782
|
unreadBriefs,
|
|
7002
7783
|
missingChunks,
|
|
7003
7784
|
uncoverableChunks: [...uncoverable].sort((a, b) => a - b),
|
|
7785
|
+
budgetGaps,
|
|
7004
7786
|
coveredChunks: [...covered].sort((a, b) => a - b),
|
|
7005
7787
|
plannedChunks: plan.chunks.map((c) => ({
|
|
7006
7788
|
id: c.id,
|
|
@@ -7172,188 +7954,54 @@ function verificationGaps(planPath, opts, env = process.env) {
|
|
|
7172
7954
|
(k) => k === "verify" || k.startsWith("verify--")
|
|
7173
7955
|
);
|
|
7174
7956
|
verify = bestDelivery(verifyKeys);
|
|
7175
|
-
if (verify !== "ok") {
|
|
7176
|
-
unverifiedFindings = true;
|
|
7177
|
-
remediation.push(
|
|
7178
|
-
`verification: ${VERIFY_GAP[verify].fix.replace(
|
|
7179
|
-
"--plan <plan>",
|
|
7180
|
-
// A function replacer: a plain string gives `$&`/`$\`` special
|
|
7181
|
-
// meaning, and a path is not a place for replacement patterns.
|
|
7182
|
-
() => `--plan ${shellQuotePath(planPath)}`
|
|
7183
|
-
)}`
|
|
7184
|
-
);
|
|
7185
|
-
}
|
|
7186
|
-
}
|
|
7187
|
-
if (reverseGap && verify !== null && verify === reverse) {
|
|
7188
|
-
gaps.push({
|
|
7189
|
-
subject: "verification and reverse audit",
|
|
7190
|
-
reason: COMBINED_STEP45_GAP[reverse].en,
|
|
7191
|
-
subjectZh: "\u9A8C\u8BC1\u4E0E\u53CD\u5411\u5BA1\u8BA1",
|
|
7192
|
-
reasonZh: COMBINED_STEP45_GAP[reverse].zh
|
|
7193
|
-
});
|
|
7194
|
-
} else {
|
|
7195
|
-
if (reverseGap) {
|
|
7196
|
-
gaps.push({
|
|
7197
|
-
subject: "reverse audit",
|
|
7198
|
-
reason: REVERSE_AUDIT_GAP[reverse].gap,
|
|
7199
|
-
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7200
|
-
reasonZh: REVERSE_AUDIT_GAP[reverse].gapZh
|
|
7201
|
-
});
|
|
7202
|
-
}
|
|
7203
|
-
if (verify !== null && verify !== "ok") {
|
|
7204
|
-
gaps.push({
|
|
7205
|
-
subject: "verification",
|
|
7206
|
-
reason: VERIFY_GAP[verify].gap,
|
|
7207
|
-
subjectZh: "\u9A8C\u8BC1",
|
|
7208
|
-
reasonZh: VERIFY_GAP[verify].gapZh
|
|
7209
|
-
});
|
|
7210
|
-
}
|
|
7211
|
-
}
|
|
7212
|
-
if (balancedMedium) {
|
|
7213
|
-
gaps.push({
|
|
7214
|
-
subject: "reverse audit",
|
|
7215
|
-
reason: "not run \u2014 the balanced (medium) tier skips the second-look pass, so this verdict is capped at Comment rather than Approve",
|
|
7216
|
-
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7217
|
-
reasonZh: "\u672A\u8FD0\u884C\u2014\u2014\u5747\u8861\uFF08medium\uFF09\u6863\u8DF3\u8FC7\u4E8C\u6B21\u5BA1\u67E5\u6B65\u9AA4\uFF0C\u56E0\u6B64\u672C\u6B21\u5224\u5B9A\u4E0A\u9650\u4E3A Comment\uFF0C\u4E0D\u4F1A Approve"
|
|
7218
|
-
});
|
|
7219
|
-
}
|
|
7220
|
-
return { ok: gaps.length === 0, gaps, remediation, unverifiedFindings };
|
|
7221
|
-
}
|
|
7222
|
-
__name(verificationGaps, "verificationGaps");
|
|
7223
|
-
|
|
7224
|
-
// packages/cli/src/commands/review/lib/gh.ts
|
|
7225
|
-
init_esbuild_shims();
|
|
7226
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
7227
|
-
var MAX_RETRIES = 2;
|
|
7228
|
-
var BASE_DELAY_MS = 3e3;
|
|
7229
|
-
function sleepSync(ms) {
|
|
7230
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
7231
|
-
}
|
|
7232
|
-
__name(sleepSync, "sleepSync");
|
|
7233
|
-
var TRANSIENT_RE = /HTTP 5\d{2}|server is currently unavailable|service unavailable|bad gateway|internal server error/i;
|
|
7234
|
-
function isTransientGhError(err) {
|
|
7235
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
7236
|
-
const msg = err instanceof Error ? err.message : "";
|
|
7237
|
-
return TRANSIENT_RE.test(stderr) || TRANSIENT_RE.test(msg);
|
|
7238
|
-
}
|
|
7239
|
-
__name(isTransientGhError, "isTransientGhError");
|
|
7240
|
-
function execGhWithRetry(args, options) {
|
|
7241
|
-
const execOptions = {
|
|
7242
|
-
encoding: "utf8",
|
|
7243
|
-
maxBuffer: 64 * 1024 * 1024,
|
|
7244
|
-
env: ghEnv(),
|
|
7245
|
-
...options.input !== void 0 ? { input: options.input } : {}
|
|
7246
|
-
};
|
|
7247
|
-
for (let attempt = 0; ; attempt++) {
|
|
7248
|
-
try {
|
|
7249
|
-
return execFileSync2("gh", args, execOptions).replace(/\r\n/g, "\n").trim();
|
|
7250
|
-
} catch (err) {
|
|
7251
|
-
if (attempt < MAX_RETRIES && isTransientGhError(err)) {
|
|
7252
|
-
const delay = BASE_DELAY_MS * (attempt + 1);
|
|
7253
|
-
process.stderr.write(
|
|
7254
|
-
`gh transient error (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms\u2026
|
|
7255
|
-
`
|
|
7256
|
-
);
|
|
7257
|
-
sleepSync(delay);
|
|
7258
|
-
continue;
|
|
7259
|
-
}
|
|
7260
|
-
throw err;
|
|
7261
|
-
}
|
|
7262
|
-
}
|
|
7263
|
-
}
|
|
7264
|
-
__name(execGhWithRetry, "execGhWithRetry");
|
|
7265
|
-
var ghHost;
|
|
7266
|
-
var HOSTNAME_RE = /^[A-Za-z0-9.-]+(?::\d+)?$/;
|
|
7267
|
-
function setGhHost(host) {
|
|
7268
|
-
if (host === void 0 || host === "") {
|
|
7269
|
-
ghHost = void 0;
|
|
7270
|
-
return;
|
|
7271
|
-
}
|
|
7272
|
-
if (!HOSTNAME_RE.test(host)) {
|
|
7273
|
-
throw new TypeError(
|
|
7274
|
-
`--host must be a hostname (optionally :port), got ${JSON.stringify(host)}`
|
|
7275
|
-
);
|
|
7276
|
-
}
|
|
7277
|
-
ghHost = host;
|
|
7278
|
-
}
|
|
7279
|
-
__name(setGhHost, "setGhHost");
|
|
7280
|
-
function getGhHost() {
|
|
7281
|
-
return ghHost;
|
|
7282
|
-
}
|
|
7283
|
-
__name(getGhHost, "getGhHost");
|
|
7284
|
-
function ghEnv() {
|
|
7285
|
-
return ghHost ? { ...process.env, GH_HOST: ghHost } : void 0;
|
|
7286
|
-
}
|
|
7287
|
-
__name(ghEnv, "ghEnv");
|
|
7288
|
-
function gh(...args) {
|
|
7289
|
-
return execGhWithRetry(args, {});
|
|
7290
|
-
}
|
|
7291
|
-
__name(gh, "gh");
|
|
7292
|
-
function ghWithInputRetried(input, ...args) {
|
|
7293
|
-
return execGhWithRetry(args, { input });
|
|
7294
|
-
}
|
|
7295
|
-
__name(ghWithInputRetried, "ghWithInputRetried");
|
|
7296
|
-
function ghWithInput(input, ...args) {
|
|
7297
|
-
return execFileSync2("gh", args, {
|
|
7298
|
-
encoding: "utf8",
|
|
7299
|
-
maxBuffer: 64 * 1024 * 1024,
|
|
7300
|
-
env: ghEnv(),
|
|
7301
|
-
input
|
|
7302
|
-
}).replace(/\r\n/g, "\n").trim();
|
|
7303
|
-
}
|
|
7304
|
-
__name(ghWithInput, "ghWithInput");
|
|
7305
|
-
function ghApiAll(path3) {
|
|
7306
|
-
const out = gh("api", "--paginate", path3);
|
|
7307
|
-
if (!out) return [];
|
|
7308
|
-
const parsed = JSON.parse(out);
|
|
7309
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
7310
|
-
}
|
|
7311
|
-
__name(ghApiAll, "ghApiAll");
|
|
7312
|
-
function ghApiAllNested(path3, key) {
|
|
7313
|
-
return parseNdjson(gh("api", "--paginate", path3, "--jq", `.${key}[]`), {
|
|
7314
|
-
strict: true
|
|
7315
|
-
});
|
|
7316
|
-
}
|
|
7317
|
-
__name(ghApiAllNested, "ghApiAllNested");
|
|
7318
|
-
function parseNdjson(out, opts = {}) {
|
|
7319
|
-
const strict = opts.strict ?? true;
|
|
7320
|
-
if (!out) return [];
|
|
7321
|
-
const values = [];
|
|
7322
|
-
for (const line of out.split("\n")) {
|
|
7323
|
-
if (line.trim().length === 0) continue;
|
|
7324
|
-
if (strict) {
|
|
7325
|
-
values.push(JSON.parse(line));
|
|
7326
|
-
continue;
|
|
7327
|
-
}
|
|
7328
|
-
try {
|
|
7329
|
-
values.push(JSON.parse(line));
|
|
7330
|
-
} catch {
|
|
7957
|
+
if (verify !== "ok") {
|
|
7958
|
+
unverifiedFindings = true;
|
|
7959
|
+
remediation.push(
|
|
7960
|
+
`verification: ${VERIFY_GAP[verify].fix.replace(
|
|
7961
|
+
"--plan <plan>",
|
|
7962
|
+
// A function replacer: a plain string gives `$&`/`$\`` special
|
|
7963
|
+
// meaning, and a path is not a place for replacement patterns.
|
|
7964
|
+
() => `--plan ${shellQuotePath(planPath)}`
|
|
7965
|
+
)}`
|
|
7966
|
+
);
|
|
7331
7967
|
}
|
|
7332
7968
|
}
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7969
|
+
if (reverseGap && verify !== null && verify === reverse) {
|
|
7970
|
+
gaps.push({
|
|
7971
|
+
subject: "verification and reverse audit",
|
|
7972
|
+
reason: COMBINED_STEP45_GAP[reverse].en,
|
|
7973
|
+
subjectZh: "\u9A8C\u8BC1\u4E0E\u53CD\u5411\u5BA1\u8BA1",
|
|
7974
|
+
reasonZh: COMBINED_STEP45_GAP[reverse].zh
|
|
7975
|
+
});
|
|
7976
|
+
} else {
|
|
7977
|
+
if (reverseGap) {
|
|
7978
|
+
gaps.push({
|
|
7979
|
+
subject: "reverse audit",
|
|
7980
|
+
reason: REVERSE_AUDIT_GAP[reverse].gap,
|
|
7981
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7982
|
+
reasonZh: REVERSE_AUDIT_GAP[reverse].gapZh
|
|
7983
|
+
});
|
|
7984
|
+
}
|
|
7985
|
+
if (verify !== null && verify !== "ok") {
|
|
7986
|
+
gaps.push({
|
|
7987
|
+
subject: "verification",
|
|
7988
|
+
reason: VERIFY_GAP[verify].gap,
|
|
7989
|
+
subjectZh: "\u9A8C\u8BC1",
|
|
7990
|
+
reasonZh: VERIFY_GAP[verify].gapZh
|
|
7991
|
+
});
|
|
7353
7992
|
}
|
|
7354
7993
|
}
|
|
7994
|
+
if (balancedMedium) {
|
|
7995
|
+
gaps.push({
|
|
7996
|
+
subject: "reverse audit",
|
|
7997
|
+
reason: "not run \u2014 the balanced (medium) tier skips the second-look pass, so this verdict is capped at Comment rather than Approve",
|
|
7998
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7999
|
+
reasonZh: "\u672A\u8FD0\u884C\u2014\u2014\u5747\u8861\uFF08medium\uFF09\u6863\u8DF3\u8FC7\u4E8C\u6B21\u5BA1\u67E5\u6B65\u9AA4\uFF0C\u56E0\u6B64\u672C\u6B21\u5224\u5B9A\u4E0A\u9650\u4E3A Comment\uFF0C\u4E0D\u4F1A Approve"
|
|
8000
|
+
});
|
|
8001
|
+
}
|
|
8002
|
+
return { ok: gaps.length === 0, gaps, remediation, unverifiedFindings };
|
|
7355
8003
|
}
|
|
7356
|
-
__name(
|
|
8004
|
+
__name(verificationGaps, "verificationGaps");
|
|
7357
8005
|
|
|
7358
8006
|
// packages/cli/src/commands/review/lib/ledger.ts
|
|
7359
8007
|
init_esbuild_shims();
|
|
@@ -7529,16 +8177,16 @@ __name(composeReview, "composeReview");
|
|
|
7529
8177
|
function ledgerMarkerFor(input) {
|
|
7530
8178
|
try {
|
|
7531
8179
|
if (!input.planPath) return null;
|
|
7532
|
-
const plan = JSON.parse(
|
|
8180
|
+
const plan = JSON.parse(readFileSync10(input.planPath, "utf8"));
|
|
7533
8181
|
const pr = plan?.prNumber;
|
|
7534
8182
|
const isPr = typeof pr === "number" && Number.isInteger(pr) && pr > 0 || typeof pr === "string" && /^\d+$/.test(pr);
|
|
7535
8183
|
if (!isPr) return null;
|
|
7536
8184
|
let prevRound = 0;
|
|
7537
8185
|
try {
|
|
7538
8186
|
const prev = JSON.parse(
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
8187
|
+
readFileSync10(
|
|
8188
|
+
join10(
|
|
8189
|
+
dirname5(input.planPath),
|
|
7542
8190
|
`qwen-review-pr-${pr}-prev-ledger.json`
|
|
7543
8191
|
),
|
|
7544
8192
|
"utf8"
|
|
@@ -7598,6 +8246,8 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7598
8246
|
}
|
|
7599
8247
|
}
|
|
7600
8248
|
const remediation = [];
|
|
8249
|
+
const budgetGapNotes = [];
|
|
8250
|
+
const MAX_BUDGET_GAP_LINES = 5;
|
|
7601
8251
|
const planRef = input.planPath ? shellQuotePath(input.planPath) : "<plan>";
|
|
7602
8252
|
const missingReceipts = [];
|
|
7603
8253
|
let plannedChunks = [];
|
|
@@ -7676,6 +8326,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7676
8326
|
"agents that never opened the diff: relaunch each with the same printed prompt \u2014 the prompt already names the diff and its ranges; the read is what proves the review happened"
|
|
7677
8327
|
);
|
|
7678
8328
|
}
|
|
8329
|
+
budgetGapNotes.push(...cov.budgetGaps);
|
|
7679
8330
|
coverageEntries.push(...cov.disclosures);
|
|
7680
8331
|
if (cov.rewrittenPrompts.length > 0) {
|
|
7681
8332
|
remediation.push(
|
|
@@ -7740,7 +8391,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7740
8391
|
);
|
|
7741
8392
|
}
|
|
7742
8393
|
try {
|
|
7743
|
-
const findingsContent =
|
|
8394
|
+
const findingsContent = readFileSync10(findingsPath, "utf8");
|
|
7744
8395
|
unverifiedTagCount = (findingsContent.match(UNVERIFIED_FINDING_TAG_RE) ?? []).length;
|
|
7745
8396
|
findingsUnverifiedAtCompose = unverifiedTagCount > 0;
|
|
7746
8397
|
if (findingsUnverifiedAtCompose) {
|
|
@@ -7826,7 +8477,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7826
8477
|
if (event2 === "APPROVE" && input.planPath) {
|
|
7827
8478
|
let plan;
|
|
7828
8479
|
try {
|
|
7829
|
-
plan = JSON.parse(
|
|
8480
|
+
plan = JSON.parse(readFileSync10(input.planPath, "utf8"));
|
|
7830
8481
|
} catch {
|
|
7831
8482
|
}
|
|
7832
8483
|
if (plan) {
|
|
@@ -7838,10 +8489,10 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7838
8489
|
}
|
|
7839
8490
|
const footer = reviewFooter(modelId, cliVersion);
|
|
7840
8491
|
const bilingual = bilingualFromPlan(input.planPath, input.prBodyFetcher);
|
|
7841
|
-
const render = /* @__PURE__ */ __name((parts,
|
|
7842
|
-
const en = parts.map((p) => p.en).join(
|
|
8492
|
+
const render = /* @__PURE__ */ __name((parts, sep9) => {
|
|
8493
|
+
const en = parts.map((p) => p.en).join(sep9);
|
|
7843
8494
|
if (en === "") return "";
|
|
7844
|
-
const zh = parts.map((p) => p.zh).join(
|
|
8495
|
+
const zh = parts.map((p) => p.zh).join(sep9);
|
|
7845
8496
|
const text = bilingual && zh !== en ? `${en}
|
|
7846
8497
|
|
|
7847
8498
|
<details>
|
|
@@ -7913,6 +8564,23 @@ ${footer}`;
|
|
|
7913
8564
|
zh: `\u672A\u5BA1\u67E5\uFF1A${d}\u3002`
|
|
7914
8565
|
});
|
|
7915
8566
|
}
|
|
8567
|
+
const budgetGapItems = [];
|
|
8568
|
+
for (const g of budgetGapNotes) {
|
|
8569
|
+
for (const gap of g.gaps) budgetGapItems.push({ agent: g.agent, gap });
|
|
8570
|
+
}
|
|
8571
|
+
const keptBudgetGaps = budgetGapItems.filter(
|
|
8572
|
+
(it) => !unreviewed.some((d) => d.includes(it.gap))
|
|
8573
|
+
);
|
|
8574
|
+
if (keptBudgetGaps.length > 0) {
|
|
8575
|
+
const shown = keptBudgetGaps.slice(0, MAX_BUDGET_GAP_LINES);
|
|
8576
|
+
const more = keptBudgetGaps.length - shown.length;
|
|
8577
|
+
const enList = shown.map((it) => `${it.agent}: ${mdField(it.gap)}`).join("; ") + (more > 0 ? `, and ${more} more` : "");
|
|
8578
|
+
const zhList = shown.map((it) => `${it.agent}\uFF1A${mdField(it.gap)}`).join("\uFF1B") + (more > 0 ? `\uFF0C\u53E6\u6709 ${more} \u6761` : "");
|
|
8579
|
+
notReviewedParts.push({
|
|
8580
|
+
en: `Not explored to full depth (tool budget reached): ${enList}.`,
|
|
8581
|
+
zh: `\u672A\u63A2\u7D22\u5230\u5168\u90E8\u6DF1\u5EA6\uFF08\u8FBE\u5230\u5DE5\u5177\u8C03\u7528\u9884\u7B97\uFF09\uFF1A${zhList}\u3002`
|
|
8582
|
+
});
|
|
8583
|
+
}
|
|
7916
8584
|
const seenSubjects = /* @__PURE__ */ new Set();
|
|
7917
8585
|
const byReason = /* @__PURE__ */ new Map();
|
|
7918
8586
|
const reasonZhOf = /* @__PURE__ */ new Map();
|
|
@@ -8020,11 +8688,12 @@ ${footer}`;
|
|
|
8020
8688
|
body: render(
|
|
8021
8689
|
[
|
|
8022
8690
|
{ en: "No issues found. LGTM! \u2705", zh: "\u672A\u53D1\u73B0\u95EE\u9898\u3002LGTM\uFF01\u2705" },
|
|
8691
|
+
...notReviewedParts,
|
|
8023
8692
|
...deferredBlock,
|
|
8024
8693
|
...testPlanBlock,
|
|
8025
8694
|
...repositoryContextBlock2
|
|
8026
8695
|
],
|
|
8027
|
-
deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8696
|
+
notReviewedParts.length || deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8028
8697
|
),
|
|
8029
8698
|
baseEvent,
|
|
8030
8699
|
cappedBy,
|
|
@@ -8050,7 +8719,12 @@ ${footer}`;
|
|
|
8050
8719
|
// body could open "Reviewed — no blockers." two lines above "nobody read
|
|
8051
8720
|
// them." Nothing nobody read can be certified blocker-free — and neither
|
|
8052
8721
|
// can a loop that ended with findings no verifier ever ruled on.
|
|
8053
|
-
missingReceipts.length === 0 &&
|
|
8722
|
+
missingReceipts.length === 0 && // A disclosed budget gap is not a blocker, but "Reviewed — no
|
|
8723
|
+
// blockers." two lines above "Not explored to full depth" is the
|
|
8724
|
+
// opener certifying what the disclosure takes back — the exact
|
|
8725
|
+
// shape the comment below forbids. (A gap the caller promoted into
|
|
8726
|
+
// `unreviewedDimensions` already denies certification above.)
|
|
8727
|
+
keptBudgetGaps.length === 0 && !findingsUnverifiedAtCompose;
|
|
8054
8728
|
const disclosedChunkIds = /* @__PURE__ */ new Set();
|
|
8055
8729
|
for (const e of coverageEntries) {
|
|
8056
8730
|
const m = /^chunk (\d+)$/.exec(e.subject);
|
|
@@ -8139,7 +8813,7 @@ var fetchPrBodyViaGh = /* @__PURE__ */ __name((ownerRepo, prNumber) => {
|
|
|
8139
8813
|
function repositoryContextGate(planPath) {
|
|
8140
8814
|
let plan;
|
|
8141
8815
|
try {
|
|
8142
|
-
plan = JSON.parse(
|
|
8816
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8143
8817
|
} catch {
|
|
8144
8818
|
return [];
|
|
8145
8819
|
}
|
|
@@ -8161,7 +8835,7 @@ function scriptLintGate(planPath) {
|
|
|
8161
8835
|
const disclosed = [];
|
|
8162
8836
|
let plan;
|
|
8163
8837
|
try {
|
|
8164
|
-
plan = JSON.parse(
|
|
8838
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8165
8839
|
} catch {
|
|
8166
8840
|
unreviewed.push(
|
|
8167
8841
|
"the executable-script lint \u2014 could not read the plan to check the gate"
|
|
@@ -8172,13 +8846,13 @@ function scriptLintGate(planPath) {
|
|
|
8172
8846
|
return { criticals, unreviewed, disclosed };
|
|
8173
8847
|
}
|
|
8174
8848
|
const owed = hasExecutableScript(plan);
|
|
8175
|
-
const reportPath =
|
|
8176
|
-
|
|
8849
|
+
const reportPath = join10(
|
|
8850
|
+
dirname5(planPath),
|
|
8177
8851
|
scriptLintReportName(plan.prNumber)
|
|
8178
8852
|
);
|
|
8179
8853
|
let report;
|
|
8180
8854
|
try {
|
|
8181
|
-
report = JSON.parse(
|
|
8855
|
+
report = JSON.parse(readFileSync10(reportPath, "utf8"));
|
|
8182
8856
|
} catch {
|
|
8183
8857
|
if (owed) {
|
|
8184
8858
|
unreviewed.push(
|
|
@@ -8234,7 +8908,7 @@ function testPlanGate(planPath) {
|
|
|
8234
8908
|
const notes = [];
|
|
8235
8909
|
let plan;
|
|
8236
8910
|
try {
|
|
8237
|
-
plan = JSON.parse(
|
|
8911
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8238
8912
|
} catch {
|
|
8239
8913
|
return { notes };
|
|
8240
8914
|
}
|
|
@@ -8244,8 +8918,8 @@ function testPlanGate(planPath) {
|
|
|
8244
8918
|
let report;
|
|
8245
8919
|
try {
|
|
8246
8920
|
report = JSON.parse(
|
|
8247
|
-
|
|
8248
|
-
|
|
8921
|
+
readFileSync10(
|
|
8922
|
+
join10(dirname5(planPath), `qwen-review-pr-${pr}-test-plan.json`),
|
|
8249
8923
|
"utf8"
|
|
8250
8924
|
)
|
|
8251
8925
|
);
|
|
@@ -8278,7 +8952,7 @@ function bilingualFromPlan(planPath, fetchPrBody2 = fetchPrBodyViaGh) {
|
|
|
8278
8952
|
if (!planPath) return false;
|
|
8279
8953
|
let plan;
|
|
8280
8954
|
try {
|
|
8281
|
-
plan = JSON.parse(
|
|
8955
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8282
8956
|
} catch {
|
|
8283
8957
|
return false;
|
|
8284
8958
|
}
|
|
@@ -8298,7 +8972,7 @@ __name(bilingualFromPlan, "bilingualFromPlan");
|
|
|
8298
8972
|
function readDraftedComments(path3) {
|
|
8299
8973
|
let raw;
|
|
8300
8974
|
try {
|
|
8301
|
-
raw =
|
|
8975
|
+
raw = readFileSync10(path3, "utf8");
|
|
8302
8976
|
} catch (err) {
|
|
8303
8977
|
throw new Error(
|
|
8304
8978
|
`compose-review: cannot read the comments file ${path3}: ${err.message}. Pass the drafted inline comments \u2014 the same array the review payload will carry \u2014 or a file containing [] when nothing anchors inline.`
|
|
@@ -8352,7 +9026,7 @@ var composeReviewCommand = {
|
|
|
8352
9026
|
"compose-review: --comments is required \u2014 the inline counts are counted from the drafted comments file, never typed. Pass a file containing [] when nothing anchors inline."
|
|
8353
9027
|
);
|
|
8354
9028
|
}
|
|
8355
|
-
const raw =
|
|
9029
|
+
const raw = readFileSync10(input ?? 0, "utf8");
|
|
8356
9030
|
const parsed = JSON.parse(raw);
|
|
8357
9031
|
delete parsed.env;
|
|
8358
9032
|
delete parsed.prBodyFetcher;
|
|
@@ -8379,7 +9053,7 @@ var composeReviewCommand = {
|
|
|
8379
9053
|
2
|
|
8380
9054
|
);
|
|
8381
9055
|
if (out) {
|
|
8382
|
-
mkdirSync6(
|
|
9056
|
+
mkdirSync6(dirname5(out), { recursive: true });
|
|
8383
9057
|
writeFileSync6(out, json, "utf8");
|
|
8384
9058
|
}
|
|
8385
9059
|
writeStdoutLine(json);
|
|
@@ -8482,8 +9156,8 @@ __name(verdictLine, "verdictLine");
|
|
|
8482
9156
|
|
|
8483
9157
|
// packages/cli/src/commands/review/findings.ts
|
|
8484
9158
|
init_esbuild_shims();
|
|
8485
|
-
import { existsSync as
|
|
8486
|
-
import { dirname as
|
|
9159
|
+
import { existsSync as existsSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
9160
|
+
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
8487
9161
|
var SEVERITIES = ["Critical", "Suggestion", "Nice to have"];
|
|
8488
9162
|
var CONFIDENCES = ["high", "low"];
|
|
8489
9163
|
var OUTCOMES = ["fixed", "skipped", "no_change_needed"];
|
|
@@ -8856,7 +9530,7 @@ __name(renderFindings, "renderFindings");
|
|
|
8856
9530
|
function readJson(path3, what) {
|
|
8857
9531
|
let text;
|
|
8858
9532
|
try {
|
|
8859
|
-
text =
|
|
9533
|
+
text = readFileSync11(resolve6(path3), "utf8");
|
|
8860
9534
|
} catch (err) {
|
|
8861
9535
|
throw new Error(
|
|
8862
9536
|
`Could not read the ${what} file at ${JSON.stringify(path3)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -8905,7 +9579,7 @@ var findingsCommand = {
|
|
|
8905
9579
|
let readjudicated = [];
|
|
8906
9580
|
if (testDelta !== void 0) {
|
|
8907
9581
|
let measurement;
|
|
8908
|
-
if (
|
|
9582
|
+
if (existsSync5(resolve6(testDelta))) {
|
|
8909
9583
|
try {
|
|
8910
9584
|
measurement = readJson(testDelta, "test-delta");
|
|
8911
9585
|
} catch (err) {
|
|
@@ -8926,8 +9600,8 @@ var findingsCommand = {
|
|
|
8926
9600
|
));
|
|
8927
9601
|
}
|
|
8928
9602
|
const report = buildReport(findings);
|
|
8929
|
-
const target =
|
|
8930
|
-
mkdirSync7(
|
|
9603
|
+
const target = resolve6(out);
|
|
9604
|
+
mkdirSync7(dirname6(target), { recursive: true });
|
|
8931
9605
|
writeFileSync7(target, `${JSON.stringify(report, null, 2)}
|
|
8932
9606
|
`, "utf8");
|
|
8933
9607
|
const { bySeverity, byConfidence } = report.counts;
|
|
@@ -8959,90 +9633,8 @@ var findingsCommand = {
|
|
|
8959
9633
|
// packages/cli/src/commands/review/fetch-pr.ts
|
|
8960
9634
|
init_esbuild_shims();
|
|
8961
9635
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
8962
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
8963
|
-
import { dirname as
|
|
8964
|
-
|
|
8965
|
-
// packages/cli/src/commands/review/lib/git.ts
|
|
8966
|
-
init_esbuild_shims();
|
|
8967
|
-
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
8968
|
-
import { existsSync as existsSync4, rmSync as rmSync3 } from "node:fs";
|
|
8969
|
-
var GIT_TIMEOUT_MS2 = 12e4;
|
|
8970
|
-
function gitOpts() {
|
|
8971
|
-
return {
|
|
8972
|
-
timeout: GIT_TIMEOUT_MS2,
|
|
8973
|
-
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
8974
|
-
};
|
|
8975
|
-
}
|
|
8976
|
-
__name(gitOpts, "gitOpts");
|
|
8977
|
-
function git(...args) {
|
|
8978
|
-
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8" }).replace(/\r\n/g, "\n").trim();
|
|
8979
|
-
}
|
|
8980
|
-
__name(git, "git");
|
|
8981
|
-
function gitWithInput(input, args) {
|
|
8982
|
-
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8", input }).replace(/\r\n/g, "\n").trim();
|
|
8983
|
-
}
|
|
8984
|
-
__name(gitWithInput, "gitWithInput");
|
|
8985
|
-
function gitOpt(...args) {
|
|
8986
|
-
try {
|
|
8987
|
-
return execFileSync3("git", args, {
|
|
8988
|
-
...gitOpts(),
|
|
8989
|
-
encoding: "utf8",
|
|
8990
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
8991
|
-
}).replace(/\r\n/g, "\n").trim();
|
|
8992
|
-
} catch {
|
|
8993
|
-
return null;
|
|
8994
|
-
}
|
|
8995
|
-
}
|
|
8996
|
-
__name(gitOpt, "gitOpt");
|
|
8997
|
-
function refExists(ref) {
|
|
8998
|
-
return gitOpt("rev-parse", "--verify", "--quiet", ref) !== null;
|
|
8999
|
-
}
|
|
9000
|
-
__name(refExists, "refExists");
|
|
9001
|
-
function worktreeReleaseResult(existed, stillThere, removeError) {
|
|
9002
|
-
const freed = existed && !stillThere;
|
|
9003
|
-
if (!existed || freed) {
|
|
9004
|
-
return { existed, freed, reason: void 0 };
|
|
9005
|
-
}
|
|
9006
|
-
return {
|
|
9007
|
-
existed,
|
|
9008
|
-
freed,
|
|
9009
|
-
reason: removeError ? removeError instanceof Error ? removeError.message : String(removeError) : "the path is still there after `git worktree remove --force` and `rm -rf`"
|
|
9010
|
-
};
|
|
9011
|
-
}
|
|
9012
|
-
__name(worktreeReleaseResult, "worktreeReleaseResult");
|
|
9013
|
-
function releaseWorktree(worktreePath2) {
|
|
9014
|
-
const existed = existsSync4(worktreePath2);
|
|
9015
|
-
let removeError;
|
|
9016
|
-
if (existed) {
|
|
9017
|
-
gitOpt("worktree", "remove", worktreePath2, "--force");
|
|
9018
|
-
try {
|
|
9019
|
-
rmSync3(worktreePath2, { recursive: true, force: true });
|
|
9020
|
-
} catch (e) {
|
|
9021
|
-
removeError = e;
|
|
9022
|
-
}
|
|
9023
|
-
}
|
|
9024
|
-
gitOpt("worktree", "prune");
|
|
9025
|
-
return worktreeReleaseResult(existed, existsSync4(worktreePath2), removeError);
|
|
9026
|
-
}
|
|
9027
|
-
__name(releaseWorktree, "releaseWorktree");
|
|
9028
|
-
function gitRaw(...args) {
|
|
9029
|
-
return execFileSync3("git", args, {
|
|
9030
|
-
...gitOpts(),
|
|
9031
|
-
maxBuffer: 512 * 1024 * 1024,
|
|
9032
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
9033
|
-
});
|
|
9034
|
-
}
|
|
9035
|
-
__name(gitRaw, "gitRaw");
|
|
9036
|
-
function gitRawTolerateDiff(...args) {
|
|
9037
|
-
try {
|
|
9038
|
-
return gitRaw(...args);
|
|
9039
|
-
} catch (err) {
|
|
9040
|
-
const e = err;
|
|
9041
|
-
if (e.status === 1 && e.stdout && e.stdout.length > 0) return e.stdout;
|
|
9042
|
-
throw err;
|
|
9043
|
-
}
|
|
9044
|
-
}
|
|
9045
|
-
__name(gitRawTolerateDiff, "gitRawTolerateDiff");
|
|
9636
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
9637
|
+
import { dirname as dirname7, resolve as resolve7 } from "node:path";
|
|
9046
9638
|
|
|
9047
9639
|
// packages/cli/src/commands/review/lib/diff-flags.ts
|
|
9048
9640
|
init_esbuild_shims();
|
|
@@ -9067,11 +9659,11 @@ var LITERAL_PATHSPECS = "--literal-pathspecs";
|
|
|
9067
9659
|
|
|
9068
9660
|
// packages/cli/src/commands/review/lib/effort.ts
|
|
9069
9661
|
init_esbuild_shims();
|
|
9070
|
-
import { readFileSync as
|
|
9662
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
9071
9663
|
function resolveEffort(explicit) {
|
|
9072
9664
|
if (explicit && EFFORT_LEVELS.has(explicit)) return explicit;
|
|
9073
9665
|
try {
|
|
9074
|
-
const parsed = JSON.parse(
|
|
9666
|
+
const parsed = JSON.parse(readFileSync12(PARSE_ARGS_REPORT, "utf8"));
|
|
9075
9667
|
if (typeof parsed.effort === "string" && EFFORT_LEVELS.has(parsed.effort)) {
|
|
9076
9668
|
return parsed.effort;
|
|
9077
9669
|
}
|
|
@@ -9092,7 +9684,7 @@ __name(planEffortField, "planEffortField");
|
|
|
9092
9684
|
|
|
9093
9685
|
// packages/cli/src/commands/review/lib/report.ts
|
|
9094
9686
|
init_esbuild_shims();
|
|
9095
|
-
import { statSync as
|
|
9687
|
+
import { statSync as statSync6 } from "node:fs";
|
|
9096
9688
|
|
|
9097
9689
|
// packages/cli/src/commands/review/lib/heavy.ts
|
|
9098
9690
|
init_esbuild_shims();
|
|
@@ -9109,42 +9701,6 @@ function classifyHeavy(input) {
|
|
|
9109
9701
|
}
|
|
9110
9702
|
__name(classifyHeavy, "classifyHeavy");
|
|
9111
9703
|
|
|
9112
|
-
// packages/cli/src/commands/review/lib/budget.ts
|
|
9113
|
-
init_esbuild_shims();
|
|
9114
|
-
var SWEEP_FLOOR = 25;
|
|
9115
|
-
var SPECIALIST_FLOOR = 80;
|
|
9116
|
-
var LINES_PER_ANGLE = 60;
|
|
9117
|
-
var MIN_INLINE_ANGLES = 3;
|
|
9118
|
-
var MAX_INLINE_ANGLES = 6;
|
|
9119
|
-
var VERIFY_SHARD = 8;
|
|
9120
|
-
function reviewBudget(input) {
|
|
9121
|
-
const src = sane(input.srcDiffLines);
|
|
9122
|
-
const total = sane(input.diffLines);
|
|
9123
|
-
const effective = Math.max(src, Math.floor(total / 8));
|
|
9124
|
-
const extraAngles = Math.floor(effective / LINES_PER_ANGLE);
|
|
9125
|
-
const inlineAngles = clamp(
|
|
9126
|
-
MIN_INLINE_ANGLES + extraAngles,
|
|
9127
|
-
MIN_INLINE_ANGLES,
|
|
9128
|
-
MAX_INLINE_ANGLES
|
|
9129
|
-
);
|
|
9130
|
-
return {
|
|
9131
|
-
inlineAngles,
|
|
9132
|
-
sweep: effective >= SWEEP_FLOOR,
|
|
9133
|
-
specialistCap: src >= SPECIALIST_FLOOR ? 2 : 0,
|
|
9134
|
-
verifyShard: VERIFY_SHARD
|
|
9135
|
-
};
|
|
9136
|
-
}
|
|
9137
|
-
__name(reviewBudget, "reviewBudget");
|
|
9138
|
-
function sane(n) {
|
|
9139
|
-
const v = Number(n);
|
|
9140
|
-
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 0;
|
|
9141
|
-
}
|
|
9142
|
-
__name(sane, "sane");
|
|
9143
|
-
function clamp(v, lo, hi) {
|
|
9144
|
-
return Math.min(hi, Math.max(lo, v));
|
|
9145
|
-
}
|
|
9146
|
-
__name(clamp, "clamp");
|
|
9147
|
-
|
|
9148
9704
|
// packages/cli/src/commands/review/lib/report.ts
|
|
9149
9705
|
function buildPlanReport(plan, postImageLines) {
|
|
9150
9706
|
const files = plan.files.map((f) => {
|
|
@@ -9195,7 +9751,7 @@ __name(buildPlanReport, "buildPlanReport");
|
|
|
9195
9751
|
function warnOnReportSize(path3, cap) {
|
|
9196
9752
|
let size = 0;
|
|
9197
9753
|
try {
|
|
9198
|
-
size =
|
|
9754
|
+
size = statSync6(path3).size;
|
|
9199
9755
|
} catch {
|
|
9200
9756
|
return;
|
|
9201
9757
|
}
|
|
@@ -9318,7 +9874,7 @@ async function runFetchPr(args) {
|
|
|
9318
9874
|
);
|
|
9319
9875
|
}
|
|
9320
9876
|
try {
|
|
9321
|
-
mkdirSync8(
|
|
9877
|
+
mkdirSync8(dirname7(wt), { recursive: true });
|
|
9322
9878
|
git("worktree", "add", wt, ref);
|
|
9323
9879
|
} catch (err) {
|
|
9324
9880
|
tryRemove(
|
|
@@ -9355,7 +9911,7 @@ async function runFetchPr(args) {
|
|
|
9355
9911
|
writeFileSync8(diffRel, buf);
|
|
9356
9912
|
diffText = buf.toString("utf8");
|
|
9357
9913
|
diffPath = diffRel;
|
|
9358
|
-
diffPathAbsolute =
|
|
9914
|
+
diffPathAbsolute = resolve7(diffRel);
|
|
9359
9915
|
} catch (err) {
|
|
9360
9916
|
writeStderrLine(`Failed to capture diff: ${err.message}`);
|
|
9361
9917
|
}
|
|
@@ -9379,7 +9935,7 @@ async function runFetchPr(args) {
|
|
|
9379
9935
|
let auditSince = fetchedAt;
|
|
9380
9936
|
let prevRaw = null;
|
|
9381
9937
|
try {
|
|
9382
|
-
prevRaw =
|
|
9938
|
+
prevRaw = readFileSync13(out, "utf8");
|
|
9383
9939
|
} catch (err) {
|
|
9384
9940
|
const code = err.code;
|
|
9385
9941
|
if (code !== "ENOENT") {
|
|
@@ -9547,12 +10103,12 @@ var fetchPrCommand = {
|
|
|
9547
10103
|
// packages/cli/src/commands/review/capture-local.ts
|
|
9548
10104
|
init_esbuild_shims();
|
|
9549
10105
|
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
9550
|
-
import { dirname as
|
|
10106
|
+
import { dirname as dirname8, resolve as resolve9 } from "node:path";
|
|
9551
10107
|
|
|
9552
10108
|
// packages/cli/src/commands/review/lib/local-diff.ts
|
|
9553
10109
|
init_esbuild_shims();
|
|
9554
|
-
import { lstatSync as lstatSync2, statSync as
|
|
9555
|
-
import { join as
|
|
10110
|
+
import { lstatSync as lstatSync2, statSync as statSync7, realpathSync as realpathSync3 } from "node:fs";
|
|
10111
|
+
import { join as join11, relative as relative3, resolve as resolve8, isAbsolute as isAbsolute2, sep as sep3 } from "node:path";
|
|
9556
10112
|
var MAX_UNTRACKED_BYTES = 1e6;
|
|
9557
10113
|
var MAX_UNTRACKED_FILES = 500;
|
|
9558
10114
|
var MAX_UNTRACKED_TOTAL_BYTES = 1e7;
|
|
@@ -9573,7 +10129,7 @@ function describeUndiffable(abs, st) {
|
|
|
9573
10129
|
}
|
|
9574
10130
|
if (st.isSymbolicLink()) {
|
|
9575
10131
|
try {
|
|
9576
|
-
return
|
|
10132
|
+
return statSync7(abs).isDirectory() ? "is a symlink to a directory \u2014 git cannot diff it as a file" : null;
|
|
9577
10133
|
} catch {
|
|
9578
10134
|
return null;
|
|
9579
10135
|
}
|
|
@@ -9582,19 +10138,19 @@ function describeUndiffable(abs, st) {
|
|
|
9582
10138
|
}
|
|
9583
10139
|
__name(describeUndiffable, "describeUndiffable");
|
|
9584
10140
|
function toRepoPathspec(repoRoot, file) {
|
|
9585
|
-
let abs =
|
|
10141
|
+
let abs = resolve8(process.cwd(), file);
|
|
9586
10142
|
try {
|
|
9587
|
-
abs =
|
|
10143
|
+
abs = realpathSync3(abs);
|
|
9588
10144
|
} catch {
|
|
9589
10145
|
}
|
|
9590
|
-
const rel =
|
|
9591
|
-
const escapes = rel === "" || rel === ".." || rel.startsWith(".." +
|
|
10146
|
+
const rel = relative3(repoRoot, abs);
|
|
10147
|
+
const escapes = rel === "" || rel === ".." || rel.startsWith(".." + sep3) || isAbsolute2(rel);
|
|
9592
10148
|
if (escapes) {
|
|
9593
10149
|
throw new Error(
|
|
9594
10150
|
`--file ${file} resolves to ${abs}, which is outside the repository at ${repoRoot}.`
|
|
9595
10151
|
);
|
|
9596
10152
|
}
|
|
9597
|
-
return rel.split(
|
|
10153
|
+
return rel.split(sep3).join("/");
|
|
9598
10154
|
}
|
|
9599
10155
|
__name(toRepoPathspec, "toRepoPathspec");
|
|
9600
10156
|
function isBinarySection(section) {
|
|
@@ -9678,7 +10234,7 @@ function captureLocalDiff(opts) {
|
|
|
9678
10234
|
for (const path3 of candidates) {
|
|
9679
10235
|
let bytes;
|
|
9680
10236
|
try {
|
|
9681
|
-
const abs =
|
|
10237
|
+
const abs = join11(repoRoot, path3);
|
|
9682
10238
|
const st = lstatSync2(abs);
|
|
9683
10239
|
const kind = describeUndiffable(abs, st);
|
|
9684
10240
|
if (kind) {
|
|
@@ -9771,13 +10327,13 @@ function runCaptureLocal(args) {
|
|
|
9771
10327
|
});
|
|
9772
10328
|
const diffText = capture.diff.toString("utf8");
|
|
9773
10329
|
mkdirSync9(REVIEW_TMP_DIR, { recursive: true });
|
|
9774
|
-
mkdirSync9(
|
|
10330
|
+
mkdirSync9(dirname8(resolve9(out)), { recursive: true });
|
|
9775
10331
|
const diffPath = tmpFile(target, "diff.txt");
|
|
9776
10332
|
writeFileSync9(diffPath, capture.diff);
|
|
9777
10333
|
const plan = buildDiffPlan(diffText);
|
|
9778
10334
|
const result = {
|
|
9779
10335
|
diffPath,
|
|
9780
|
-
diffPathAbsolute:
|
|
10336
|
+
diffPathAbsolute: resolve9(diffPath),
|
|
9781
10337
|
// No ref to `git show` a pre-change file out of, so per-file line counts and
|
|
9782
10338
|
// heaviness are unavailable — same as `plan-diff`. Chunk coverage, which is
|
|
9783
10339
|
// what the topology needs, is not.
|
|
@@ -9844,13 +10400,13 @@ var captureLocalCommand = {
|
|
|
9844
10400
|
|
|
9845
10401
|
// packages/cli/src/commands/review/plan-diff.ts
|
|
9846
10402
|
init_esbuild_shims();
|
|
9847
|
-
import { readFileSync as
|
|
9848
|
-
import { resolve as
|
|
10403
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
10404
|
+
import { resolve as resolve10 } from "node:path";
|
|
9849
10405
|
function runPlanDiff(args) {
|
|
9850
10406
|
const { diff_path: diffPath, out } = args;
|
|
9851
10407
|
let diffText;
|
|
9852
10408
|
try {
|
|
9853
|
-
diffText =
|
|
10409
|
+
diffText = readFileSync14(diffPath, "utf8");
|
|
9854
10410
|
} catch (err) {
|
|
9855
10411
|
throw new Error(
|
|
9856
10412
|
`Cannot read diff file ${diffPath}: ${err.message}`
|
|
@@ -9864,7 +10420,7 @@ function runPlanDiff(args) {
|
|
|
9864
10420
|
const plan = buildDiffPlan(diffText, args.maxChunkLines);
|
|
9865
10421
|
const result = {
|
|
9866
10422
|
diffPath,
|
|
9867
|
-
diffPathAbsolute:
|
|
10423
|
+
diffPathAbsolute: resolve10(diffPath),
|
|
9868
10424
|
// The PR identity, when the caller resolved one. This is what lets the
|
|
9869
10425
|
// roster require Agent 0 on a lightweight cross-repo review — a diff-only
|
|
9870
10426
|
// plan without it cannot demand an agent nobody could build. Passed only
|
|
@@ -9925,18 +10481,18 @@ var planDiffCommand = {
|
|
|
9925
10481
|
// packages/cli/src/commands/review/repo-context.ts
|
|
9926
10482
|
init_esbuild_shims();
|
|
9927
10483
|
import {
|
|
9928
|
-
existsSync as
|
|
10484
|
+
existsSync as existsSync6,
|
|
9929
10485
|
mkdirSync as mkdirSync11,
|
|
9930
|
-
readFileSync as
|
|
9931
|
-
realpathSync as
|
|
9932
|
-
statSync as
|
|
10486
|
+
readFileSync as readFileSync15,
|
|
10487
|
+
realpathSync as realpathSync5,
|
|
10488
|
+
statSync as statSync9
|
|
9933
10489
|
} from "node:fs";
|
|
9934
|
-
import { dirname as
|
|
10490
|
+
import { dirname as dirname9, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve12, sep as sep5 } from "node:path";
|
|
9935
10491
|
|
|
9936
10492
|
// packages/cli/src/commands/review/lib/manifest-repository-context.ts
|
|
9937
10493
|
init_esbuild_shims();
|
|
9938
|
-
import { lstatSync as lstatSync3, readdirSync as
|
|
9939
|
-
import { isAbsolute as isAbsolute3, relative as
|
|
10494
|
+
import { lstatSync as lstatSync3, readdirSync as readdirSync5, realpathSync as realpathSync4, statSync as statSync8 } from "node:fs";
|
|
10495
|
+
import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve11, sep as sep4 } from "node:path";
|
|
9940
10496
|
var MANIFEST_PATH = ".qwen/review-context.json";
|
|
9941
10497
|
var MAX_GLOB_CANDIDATES = 16384;
|
|
9942
10498
|
var MAX_MATCH_WORK = 1024 * 1024 * 1024;
|
|
@@ -9945,12 +10501,15 @@ var MANIFEST_PREFIX = "repository context manifest ";
|
|
|
9945
10501
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
9946
10502
|
".git",
|
|
9947
10503
|
".next",
|
|
10504
|
+
".playwright",
|
|
9948
10505
|
".turbo",
|
|
9949
10506
|
"coverage",
|
|
9950
10507
|
"dist",
|
|
9951
10508
|
"node_modules",
|
|
9952
10509
|
"out",
|
|
9953
|
-
"
|
|
10510
|
+
"playwright-report",
|
|
10511
|
+
"target",
|
|
10512
|
+
"test-results"
|
|
9954
10513
|
]);
|
|
9955
10514
|
var MANIFEST_KEYS = ["label", "rules", "version"].sort();
|
|
9956
10515
|
var RULE_KEYS = [
|
|
@@ -10156,9 +10715,9 @@ function globMatches(pattern, path3) {
|
|
|
10156
10715
|
__name(globMatches, "globMatches");
|
|
10157
10716
|
function isContainedFile(worktree, path3) {
|
|
10158
10717
|
try {
|
|
10159
|
-
const resolved =
|
|
10160
|
-
const contained =
|
|
10161
|
-
return contained !== "" && !isAbsolute3(contained) && contained !== ".." && !contained.startsWith(`..${
|
|
10718
|
+
const resolved = realpathSync4(resolve11(worktree, path3));
|
|
10719
|
+
const contained = relative4(worktree, resolved);
|
|
10720
|
+
return contained !== "" && !isAbsolute3(contained) && contained !== ".." && !contained.startsWith(`..${sep4}`) && statSync8(resolved).isFile();
|
|
10162
10721
|
} catch {
|
|
10163
10722
|
return false;
|
|
10164
10723
|
}
|
|
@@ -10202,7 +10761,7 @@ function expandRelatedPaths(worktree, patterns, changedPaths2) {
|
|
|
10202
10761
|
const visit = /* @__PURE__ */ __name((directory) => {
|
|
10203
10762
|
let entries;
|
|
10204
10763
|
try {
|
|
10205
|
-
const stat = lstatSync3(
|
|
10764
|
+
const stat = lstatSync3(resolve11(worktree, directory));
|
|
10206
10765
|
if (stat.isSymbolicLink()) return;
|
|
10207
10766
|
if (!stat.isDirectory()) {
|
|
10208
10767
|
candidates++;
|
|
@@ -10222,7 +10781,7 @@ function expandRelatedPaths(worktree, patterns, changedPaths2) {
|
|
|
10222
10781
|
}
|
|
10223
10782
|
return;
|
|
10224
10783
|
}
|
|
10225
|
-
entries =
|
|
10784
|
+
entries = readdirSync5(resolve11(worktree, directory), {
|
|
10226
10785
|
withFileTypes: true
|
|
10227
10786
|
});
|
|
10228
10787
|
if (candidates + entries.length > MAX_GLOB_CANDIDATES) {
|
|
@@ -10345,24 +10904,24 @@ var manifestRepositoryContextProvider = {
|
|
|
10345
10904
|
var REPOSITORY_CONTEXT_PROVIDERS = [manifestRepositoryContextProvider];
|
|
10346
10905
|
function sameFile(left, right) {
|
|
10347
10906
|
if (left === right) return true;
|
|
10348
|
-
if (!
|
|
10349
|
-
const leftStat =
|
|
10350
|
-
const rightStat =
|
|
10907
|
+
if (!existsSync6(left) || !existsSync6(right)) return false;
|
|
10908
|
+
const leftStat = statSync9(left);
|
|
10909
|
+
const rightStat = statSync9(right);
|
|
10351
10910
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
10352
10911
|
}
|
|
10353
10912
|
__name(sameFile, "sameFile");
|
|
10354
10913
|
function recordedWorktreeMatches(recordedPath, worktree) {
|
|
10355
|
-
const candidates = [
|
|
10914
|
+
const candidates = [resolve12(recordedPath)];
|
|
10356
10915
|
if (!isAbsolute4(recordedPath)) {
|
|
10357
10916
|
const commonDir = gitOpt("-C", worktree, "rev-parse", "--git-common-dir");
|
|
10358
10917
|
if (commonDir !== null) {
|
|
10359
10918
|
candidates.push(
|
|
10360
|
-
|
|
10919
|
+
resolve12(dirname9(resolve12(worktree, commonDir)), recordedPath)
|
|
10361
10920
|
);
|
|
10362
10921
|
}
|
|
10363
10922
|
}
|
|
10364
10923
|
return candidates.some(
|
|
10365
|
-
(candidate) =>
|
|
10924
|
+
(candidate) => existsSync6(candidate) && realpathSync5(candidate) === worktree
|
|
10366
10925
|
);
|
|
10367
10926
|
}
|
|
10368
10927
|
__name(recordedWorktreeMatches, "recordedWorktreeMatches");
|
|
@@ -10416,7 +10975,7 @@ function readBaseBlob(worktree, mergeBase, path3) {
|
|
|
10416
10975
|
__name(readBaseBlob, "readBaseBlob");
|
|
10417
10976
|
function resolveTreeSymlinkTarget(fromPath, target) {
|
|
10418
10977
|
if (target.startsWith("/") || /^[A-Za-z]:/.test(target)) return null;
|
|
10419
|
-
const segments = `${
|
|
10978
|
+
const segments = `${dirname9(fromPath)}/${target}`.split("/");
|
|
10420
10979
|
const resolved = [];
|
|
10421
10980
|
for (const segment of segments) {
|
|
10422
10981
|
if (segment === "" || segment === ".") continue;
|
|
@@ -10472,29 +11031,29 @@ function identityReader(worktree, mergeBase) {
|
|
|
10472
11031
|
if (mergeBase !== null) {
|
|
10473
11032
|
return readBaseIdentity(worktree, mergeBase, relativePath);
|
|
10474
11033
|
}
|
|
10475
|
-
const candidate =
|
|
11034
|
+
const candidate = resolve12(worktree, relativePath);
|
|
10476
11035
|
let resolved;
|
|
10477
11036
|
try {
|
|
10478
|
-
resolved =
|
|
11037
|
+
resolved = realpathSync5(candidate);
|
|
10479
11038
|
} catch (error) {
|
|
10480
11039
|
if (isAbsentError(error)) return null;
|
|
10481
11040
|
throw error;
|
|
10482
11041
|
}
|
|
10483
|
-
const contained =
|
|
10484
|
-
if (isAbsolute4(contained) || contained === ".." || contained.startsWith(`..${
|
|
11042
|
+
const contained = relative5(worktree, resolved);
|
|
11043
|
+
if (isAbsolute4(contained) || contained === ".." || contained.startsWith(`..${sep5}`)) {
|
|
10485
11044
|
throw new Error(
|
|
10486
11045
|
`repo-context: identity path escapes the worktree: ${JSON.stringify(relativePath)}`
|
|
10487
11046
|
);
|
|
10488
11047
|
}
|
|
10489
11048
|
try {
|
|
10490
|
-
const stat =
|
|
11049
|
+
const stat = statSync9(resolved);
|
|
10491
11050
|
if (!stat.isFile()) return null;
|
|
10492
11051
|
if (stat.size > MAX_IDENTITY_BYTES) {
|
|
10493
11052
|
throw new Error(
|
|
10494
11053
|
`repo-context: identity read exceeds the size limit: ${JSON.stringify(relativePath)}`
|
|
10495
11054
|
);
|
|
10496
11055
|
}
|
|
10497
|
-
return normalizeIdentityContent(
|
|
11056
|
+
return normalizeIdentityContent(readFileSync15(resolved, "utf8"));
|
|
10498
11057
|
} catch (error) {
|
|
10499
11058
|
if (isAbsentError(error)) return null;
|
|
10500
11059
|
throw error;
|
|
@@ -10505,7 +11064,7 @@ __name(identityReader, "identityReader");
|
|
|
10505
11064
|
function readPlan2(path3) {
|
|
10506
11065
|
let value;
|
|
10507
11066
|
try {
|
|
10508
|
-
value = JSON.parse(
|
|
11067
|
+
value = JSON.parse(readFileSync15(path3, "utf8"));
|
|
10509
11068
|
} catch (error) {
|
|
10510
11069
|
throw new Error(`Cannot read plan ${path3}: ${error.message}`);
|
|
10511
11070
|
}
|
|
@@ -10543,13 +11102,13 @@ function contextFromProviders(providers, worktree, paths, readIdentityFile) {
|
|
|
10543
11102
|
}
|
|
10544
11103
|
__name(contextFromProviders, "contextFromProviders");
|
|
10545
11104
|
function runRepoContext(args, providers = REPOSITORY_CONTEXT_PROVIDERS) {
|
|
10546
|
-
const planPath =
|
|
10547
|
-
const outPath =
|
|
11105
|
+
const planPath = resolve12(args.plan);
|
|
11106
|
+
const outPath = resolve12(args.out);
|
|
10548
11107
|
if (sameFile(planPath, outPath)) {
|
|
10549
11108
|
throw new Error("repo-context: --out must differ from --plan");
|
|
10550
11109
|
}
|
|
10551
|
-
const worktree =
|
|
10552
|
-
if (!
|
|
11110
|
+
const worktree = realpathSync5(resolve12(args.worktree));
|
|
11111
|
+
if (!statSync9(worktree).isDirectory()) {
|
|
10553
11112
|
throw new Error(`repo-context: worktree is not a directory: ${worktree}`);
|
|
10554
11113
|
}
|
|
10555
11114
|
const plan = readPlan2(planPath);
|
|
@@ -10575,7 +11134,7 @@ function runRepoContext(args, providers = REPOSITORY_CONTEXT_PROVIDERS) {
|
|
|
10575
11134
|
);
|
|
10576
11135
|
if (context === null) delete plan.repositoryContext;
|
|
10577
11136
|
else plan.repositoryContext = context;
|
|
10578
|
-
mkdirSync11(
|
|
11137
|
+
mkdirSync11(dirname9(outPath), { recursive: true });
|
|
10579
11138
|
atomicWriteFileSync(outPath, `${JSON.stringify(context, null, 2)}
|
|
10580
11139
|
`);
|
|
10581
11140
|
atomicWriteFileSync(planPath, stringifyPlanReport(plan));
|
|
@@ -10608,7 +11167,7 @@ var repoContextCommand = {
|
|
|
10608
11167
|
// packages/cli/src/commands/review/pr-context.ts
|
|
10609
11168
|
init_esbuild_shims();
|
|
10610
11169
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10611
|
-
import { dirname as
|
|
11170
|
+
import { dirname as dirname10, join as join12 } from "node:path";
|
|
10612
11171
|
var SUMMARY_MARKER = "<!-- qwen-review-suggestion-summary -->";
|
|
10613
11172
|
function isLegacySuggestionSummary(body) {
|
|
10614
11173
|
return (body ?? "").includes(SUMMARY_MARKER);
|
|
@@ -11086,9 +11645,9 @@ async function runPrContext(args) {
|
|
|
11086
11645
|
}
|
|
11087
11646
|
if (prevLedger) {
|
|
11088
11647
|
try {
|
|
11089
|
-
mkdirSync12(
|
|
11648
|
+
mkdirSync12(dirname10(out), { recursive: true });
|
|
11090
11649
|
writeFileSync11(
|
|
11091
|
-
|
|
11650
|
+
join12(dirname10(out), `qwen-review-pr-${prNumber}-prev-ledger.json`),
|
|
11092
11651
|
JSON.stringify(prevLedger, null, 2)
|
|
11093
11652
|
);
|
|
11094
11653
|
} catch {
|
|
@@ -11103,7 +11662,7 @@ async function runPrContext(args) {
|
|
|
11103
11662
|
reviews,
|
|
11104
11663
|
prevLedger
|
|
11105
11664
|
);
|
|
11106
|
-
mkdirSync12(
|
|
11665
|
+
mkdirSync12(dirname10(out), { recursive: true });
|
|
11107
11666
|
writeFileSync11(out, md, "utf8");
|
|
11108
11667
|
const meaningfulReviewCount = reviews.filter(
|
|
11109
11668
|
(r) => isReviewWorthShowing(stripLedgerMarker(r.body ?? ""))
|
|
@@ -11159,7 +11718,7 @@ var prContextCommand = {
|
|
|
11159
11718
|
// packages/cli/src/commands/review/comment-status.ts
|
|
11160
11719
|
init_esbuild_shims();
|
|
11161
11720
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12 } from "node:fs";
|
|
11162
|
-
import { dirname as
|
|
11721
|
+
import { dirname as dirname11 } from "node:path";
|
|
11163
11722
|
var TOUCHED_BY_CAP = 10;
|
|
11164
11723
|
function buildThreadStatuses(comments, prAuthor, probe) {
|
|
11165
11724
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -11364,7 +11923,7 @@ async function runCommentStatus(args) {
|
|
|
11364
11923
|
summary,
|
|
11365
11924
|
threads
|
|
11366
11925
|
};
|
|
11367
|
-
mkdirSync13(
|
|
11926
|
+
mkdirSync13(dirname11(out), { recursive: true });
|
|
11368
11927
|
const json = JSON.stringify(report, null, 2) + "\n";
|
|
11369
11928
|
writeFileSync12(out, json, "utf8");
|
|
11370
11929
|
writeStdoutLine(
|
|
@@ -11394,7 +11953,7 @@ async function runCommentStatus(args) {
|
|
|
11394
11953
|
writeStdoutLine(
|
|
11395
11954
|
`warning: comment-status failed: ${msg}. It is an index, not the evidence \u2014 re-derive thread statuses per-comment if needed.`
|
|
11396
11955
|
);
|
|
11397
|
-
mkdirSync13(
|
|
11956
|
+
mkdirSync13(dirname11(out), { recursive: true });
|
|
11398
11957
|
writeFileSync12(
|
|
11399
11958
|
out,
|
|
11400
11959
|
JSON.stringify(
|
|
@@ -11458,7 +12017,7 @@ var commentStatusCommand = {
|
|
|
11458
12017
|
// packages/cli/src/commands/review/load-rules.ts
|
|
11459
12018
|
init_esbuild_shims();
|
|
11460
12019
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13 } from "node:fs";
|
|
11461
|
-
import { dirname as
|
|
12020
|
+
import { dirname as dirname12 } from "node:path";
|
|
11462
12021
|
function showFile(baseRef, path3) {
|
|
11463
12022
|
return gitOpt("show", `${baseRef}:${path3}`);
|
|
11464
12023
|
}
|
|
@@ -11538,7 +12097,7 @@ __name(loadCombined, "loadCombined");
|
|
|
11538
12097
|
async function runLoadRules(args) {
|
|
11539
12098
|
const { base_ref: baseRef, out } = args;
|
|
11540
12099
|
const { combined, loaded } = loadCombined(baseRef);
|
|
11541
|
-
mkdirSync14(
|
|
12100
|
+
mkdirSync14(dirname12(out), { recursive: true });
|
|
11542
12101
|
writeFileSync13(out, combined, "utf8");
|
|
11543
12102
|
if (loaded.length === 0) {
|
|
11544
12103
|
writeStdoutLine(
|
|
@@ -11570,7 +12129,7 @@ var loadRulesCommand = {
|
|
|
11570
12129
|
|
|
11571
12130
|
// packages/cli/src/commands/review/presubmit.ts
|
|
11572
12131
|
init_esbuild_shims();
|
|
11573
|
-
import { writeFileSync as writeFileSync14, readFileSync as
|
|
12132
|
+
import { writeFileSync as writeFileSync14, readFileSync as readFileSync16 } from "node:fs";
|
|
11574
12133
|
function verdictStamp(run4) {
|
|
11575
12134
|
return run4.completed_at ?? run4.started_at ?? "";
|
|
11576
12135
|
}
|
|
@@ -11606,7 +12165,7 @@ __name(isCurrentActionsRunCheck, "isCurrentActionsRunCheck");
|
|
|
11606
12165
|
function parseFindingsFile(path3) {
|
|
11607
12166
|
let parsed;
|
|
11608
12167
|
try {
|
|
11609
|
-
parsed = JSON.parse(
|
|
12168
|
+
parsed = JSON.parse(readFileSync16(path3, "utf8"));
|
|
11610
12169
|
} catch {
|
|
11611
12170
|
return null;
|
|
11612
12171
|
}
|
|
@@ -11947,13 +12506,13 @@ var presubmitCommand = {
|
|
|
11947
12506
|
|
|
11948
12507
|
// packages/cli/src/commands/review/publish-assets.ts
|
|
11949
12508
|
init_esbuild_shims();
|
|
11950
|
-
import { createHash as
|
|
11951
|
-
import { readFileSync as
|
|
11952
|
-
import { basename as
|
|
12509
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
12510
|
+
import { readFileSync as readFileSync18, statSync as statSync10, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "node:fs";
|
|
12511
|
+
import { basename as basename6, dirname as dirname13, resolve as resolve13 } from "node:path";
|
|
11953
12512
|
|
|
11954
12513
|
// packages/cli/src/commands/review/lib/authorization.ts
|
|
11955
12514
|
init_esbuild_shims();
|
|
11956
|
-
import { readFileSync as
|
|
12515
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
11957
12516
|
|
|
11958
12517
|
// packages/cli/src/services/skill-args-file.ts
|
|
11959
12518
|
init_esbuild_shims();
|
|
@@ -11964,12 +12523,12 @@ import {
|
|
|
11964
12523
|
closeSync as closeSync2,
|
|
11965
12524
|
rmSync as rmSync4,
|
|
11966
12525
|
lstatSync as lstatSync4,
|
|
11967
|
-
existsSync as
|
|
12526
|
+
existsSync as existsSync7,
|
|
11968
12527
|
constants
|
|
11969
12528
|
} from "node:fs";
|
|
11970
|
-
import { join as
|
|
12529
|
+
import { join as join13 } from "node:path";
|
|
11971
12530
|
var debugLogger3 = createDebugLogger("SKILL_ARGS_FILE");
|
|
11972
|
-
var SKILL_ARGS_DIR =
|
|
12531
|
+
var SKILL_ARGS_DIR = join13(".qwen", "tmp");
|
|
11973
12532
|
function safe(s) {
|
|
11974
12533
|
return s.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
11975
12534
|
}
|
|
@@ -11979,11 +12538,11 @@ function currentSessionId() {
|
|
|
11979
12538
|
}
|
|
11980
12539
|
__name(currentSessionId, "currentSessionId");
|
|
11981
12540
|
function skillArgsDir(sessionId = currentSessionId()) {
|
|
11982
|
-
return sessionId ?
|
|
12541
|
+
return sessionId ? join13(SKILL_ARGS_DIR, `s-${safe(sessionId)}`) : SKILL_ARGS_DIR;
|
|
11983
12542
|
}
|
|
11984
12543
|
__name(skillArgsDir, "skillArgsDir");
|
|
11985
12544
|
function skillArgsPath(skillName, sessionId = currentSessionId()) {
|
|
11986
|
-
return
|
|
12545
|
+
return join13(
|
|
11987
12546
|
skillArgsDir(sessionId),
|
|
11988
12547
|
`qwen-skill-args-${safe(skillName)}.txt`
|
|
11989
12548
|
);
|
|
@@ -12039,7 +12598,7 @@ function clearSkillArgs(skillName) {
|
|
|
12039
12598
|
);
|
|
12040
12599
|
return false;
|
|
12041
12600
|
}
|
|
12042
|
-
if (
|
|
12601
|
+
if (existsSync7(path3)) {
|
|
12043
12602
|
debugLogger3.warn(`Skill args for ${skillName} survived removal at ${path3}`);
|
|
12044
12603
|
return false;
|
|
12045
12604
|
}
|
|
@@ -12076,7 +12635,7 @@ function reviewWriteAuthorization(req) {
|
|
|
12076
12635
|
const path3 = currentSessionId() === "" && req.skillArgs ? req.skillArgs : sessionScoped;
|
|
12077
12636
|
let raw;
|
|
12078
12637
|
try {
|
|
12079
|
-
raw =
|
|
12638
|
+
raw = readFileSync17(path3, "utf8");
|
|
12080
12639
|
} catch {
|
|
12081
12640
|
return {
|
|
12082
12641
|
ok: false,
|
|
@@ -12139,8 +12698,8 @@ var EXTENSION_FORMAT = {
|
|
|
12139
12698
|
webp: "webp"
|
|
12140
12699
|
};
|
|
12141
12700
|
var ASSET_EXTENSIONS = new Set(Object.keys(EXTENSION_FORMAT));
|
|
12142
|
-
function claimedExtension(
|
|
12143
|
-
return
|
|
12701
|
+
function claimedExtension(basename7) {
|
|
12702
|
+
return basename7.includes(".") ? basename7.slice(basename7.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
12144
12703
|
}
|
|
12145
12704
|
__name(claimedExtension, "claimedExtension");
|
|
12146
12705
|
var ASSET_HEADER_BYTES = 16;
|
|
@@ -12166,18 +12725,18 @@ function sniffImageFormat(header) {
|
|
|
12166
12725
|
return null;
|
|
12167
12726
|
}
|
|
12168
12727
|
__name(sniffImageFormat, "sniffImageFormat");
|
|
12169
|
-
function refusedExtension(
|
|
12728
|
+
function refusedExtension(basename7, ext) {
|
|
12170
12729
|
return {
|
|
12171
12730
|
ok: false,
|
|
12172
|
-
reason: `${
|
|
12731
|
+
reason: `${basename7}: extension ${JSON.stringify(ext)} is not an allowed evidence image type (${[...ASSET_EXTENSIONS].join(", ")})`
|
|
12173
12732
|
};
|
|
12174
12733
|
}
|
|
12175
12734
|
__name(refusedExtension, "refusedExtension");
|
|
12176
|
-
function validateAssetContent(
|
|
12177
|
-
const ext = claimedExtension(
|
|
12735
|
+
function validateAssetContent(basename7, header) {
|
|
12736
|
+
const ext = claimedExtension(basename7);
|
|
12178
12737
|
const claimed = Object.hasOwn(EXTENSION_FORMAT, ext) ? EXTENSION_FORMAT[ext] : void 0;
|
|
12179
12738
|
if (claimed === void 0) {
|
|
12180
|
-
return refusedExtension(
|
|
12739
|
+
return refusedExtension(basename7, ext);
|
|
12181
12740
|
}
|
|
12182
12741
|
const actual = sniffImageFormat(header);
|
|
12183
12742
|
if (actual !== claimed) {
|
|
@@ -12195,8 +12754,8 @@ function assetsBranch(pr) {
|
|
|
12195
12754
|
return `pr-assets/${pr}-review`;
|
|
12196
12755
|
}
|
|
12197
12756
|
__name(assetsBranch, "assetsBranch");
|
|
12198
|
-
function remoteAssetPath(pr,
|
|
12199
|
-
const safe2 =
|
|
12757
|
+
function remoteAssetPath(pr, basename7, sha256Hex) {
|
|
12758
|
+
const safe2 = basename7.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
12200
12759
|
return `${pr}-review/${sha256Hex.slice(0, 12)}-${safe2}`;
|
|
12201
12760
|
}
|
|
12202
12761
|
__name(remoteAssetPath, "remoteAssetPath");
|
|
@@ -12222,18 +12781,18 @@ function parseAssetsRepo(value) {
|
|
|
12222
12781
|
return { repo: v };
|
|
12223
12782
|
}
|
|
12224
12783
|
__name(parseAssetsRepo, "parseAssetsRepo");
|
|
12225
|
-
function validateAssetFile(
|
|
12226
|
-
const ext = claimedExtension(
|
|
12784
|
+
function validateAssetFile(basename7, bytes) {
|
|
12785
|
+
const ext = claimedExtension(basename7);
|
|
12227
12786
|
if (!ASSET_EXTENSIONS.has(ext)) {
|
|
12228
|
-
return refusedExtension(
|
|
12787
|
+
return refusedExtension(basename7, ext);
|
|
12229
12788
|
}
|
|
12230
12789
|
if (bytes <= 0) {
|
|
12231
|
-
return { ok: false, reason: `${
|
|
12790
|
+
return { ok: false, reason: `${basename7}: empty file` };
|
|
12232
12791
|
}
|
|
12233
12792
|
if (bytes > MAX_ASSET_BYTES) {
|
|
12234
12793
|
return {
|
|
12235
12794
|
ok: false,
|
|
12236
|
-
reason: `${
|
|
12795
|
+
reason: `${basename7}: ${bytes} bytes exceeds the per-file cap of ${MAX_ASSET_BYTES} bytes`
|
|
12237
12796
|
};
|
|
12238
12797
|
}
|
|
12239
12798
|
return { ok: true };
|
|
@@ -12363,7 +12922,7 @@ function runPublishAssets(args) {
|
|
|
12363
12922
|
return;
|
|
12364
12923
|
}
|
|
12365
12924
|
const repo = repoResult.repo;
|
|
12366
|
-
const effectiveHost = args.host
|
|
12925
|
+
const effectiveHost = resolveGhHost(args.host);
|
|
12367
12926
|
const auth = reviewWriteAuthorization({
|
|
12368
12927
|
userAuthorized: args.userAuthorized,
|
|
12369
12928
|
skillArgs: args.skillArgs,
|
|
@@ -12396,7 +12955,7 @@ function runPublishAssets(args) {
|
|
|
12396
12955
|
const fileList = [...args.files ?? []];
|
|
12397
12956
|
if (args.findings) {
|
|
12398
12957
|
try {
|
|
12399
|
-
const artifact = JSON.parse(
|
|
12958
|
+
const artifact = JSON.parse(readFileSync18(resolve13(args.findings), "utf8"));
|
|
12400
12959
|
findings = validateFindings(
|
|
12401
12960
|
Array.isArray(artifact) ? artifact : artifact.findings
|
|
12402
12961
|
);
|
|
@@ -12424,11 +12983,11 @@ function runPublishAssets(args) {
|
|
|
12424
12983
|
}
|
|
12425
12984
|
const stats = [];
|
|
12426
12985
|
for (const file of unique) {
|
|
12427
|
-
const abs =
|
|
12986
|
+
const abs = resolve13(file);
|
|
12428
12987
|
try {
|
|
12429
|
-
const st =
|
|
12988
|
+
const st = statSync10(abs);
|
|
12430
12989
|
if (!st.isFile()) throw new Error("not a regular file");
|
|
12431
|
-
stats.push({ file, abs, basename:
|
|
12990
|
+
stats.push({ file, abs, basename: basename6(abs), bytes: st.size });
|
|
12432
12991
|
} catch (err) {
|
|
12433
12992
|
refuse(
|
|
12434
12993
|
`cannot read ${JSON.stringify(file)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -12445,7 +13004,7 @@ function runPublishAssets(args) {
|
|
|
12445
13004
|
for (const st of stats) {
|
|
12446
13005
|
let content;
|
|
12447
13006
|
try {
|
|
12448
|
-
content =
|
|
13007
|
+
content = readFileSync18(st.abs);
|
|
12449
13008
|
} catch (err) {
|
|
12450
13009
|
refuse(
|
|
12451
13010
|
`cannot read ${JSON.stringify(st.file)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -12460,7 +13019,7 @@ function runPublishAssets(args) {
|
|
|
12460
13019
|
refuse(`${JSON.stringify(st.file)}: ${contentRuling.reason}`);
|
|
12461
13020
|
return;
|
|
12462
13021
|
}
|
|
12463
|
-
const sha256 =
|
|
13022
|
+
const sha256 = createHash3("sha256").update(content).digest("hex");
|
|
12464
13023
|
prepared.push({
|
|
12465
13024
|
file: st.file,
|
|
12466
13025
|
bytes: st.bytes,
|
|
@@ -12499,8 +13058,8 @@ function runPublishAssets(args) {
|
|
|
12499
13058
|
pr: args.pr,
|
|
12500
13059
|
published
|
|
12501
13060
|
};
|
|
12502
|
-
const outPath =
|
|
12503
|
-
mkdirSync16(
|
|
13061
|
+
const outPath = resolve13(args.out);
|
|
13062
|
+
mkdirSync16(dirname13(outPath), { recursive: true });
|
|
12504
13063
|
writeFileSync15(outPath, `${JSON.stringify(manifest, null, 2)}
|
|
12505
13064
|
`, "utf8");
|
|
12506
13065
|
if (findings && !args.findingsOut) {
|
|
@@ -12515,8 +13074,8 @@ function runPublishAssets(args) {
|
|
|
12515
13074
|
return urls.length > 0 ? { ...f, assets: urls } : f;
|
|
12516
13075
|
});
|
|
12517
13076
|
const report = buildReport(updated);
|
|
12518
|
-
const fOut =
|
|
12519
|
-
mkdirSync16(
|
|
13077
|
+
const fOut = resolve13(args.findingsOut);
|
|
13078
|
+
mkdirSync16(dirname13(fOut), { recursive: true });
|
|
12520
13079
|
writeFileSync15(fOut, `${JSON.stringify(report, null, 2)}
|
|
12521
13080
|
`, "utf8");
|
|
12522
13081
|
}
|
|
@@ -12579,8 +13138,8 @@ var publishAssetsCommand = {
|
|
|
12579
13138
|
|
|
12580
13139
|
// packages/cli/src/commands/review/resolve-anchors.ts
|
|
12581
13140
|
init_esbuild_shims();
|
|
12582
|
-
import { readFileSync as
|
|
12583
|
-
import { dirname as
|
|
13141
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17 } from "node:fs";
|
|
13142
|
+
import { dirname as dirname14, resolve as resolve14 } from "node:path";
|
|
12584
13143
|
|
|
12585
13144
|
// packages/cli/src/commands/review/lib/anchors.ts
|
|
12586
13145
|
init_esbuild_shims();
|
|
@@ -12804,7 +13363,7 @@ __name(validateRequests, "validateRequests");
|
|
|
12804
13363
|
function runResolveAnchors(args) {
|
|
12805
13364
|
let diffText;
|
|
12806
13365
|
try {
|
|
12807
|
-
diffText =
|
|
13366
|
+
diffText = readFileSync19(args.diff, "utf8");
|
|
12808
13367
|
} catch (err) {
|
|
12809
13368
|
throw new Error(
|
|
12810
13369
|
`Cannot read diff file ${args.diff}: ${err.message}`
|
|
@@ -12812,7 +13371,7 @@ function runResolveAnchors(args) {
|
|
|
12812
13371
|
}
|
|
12813
13372
|
let rawText;
|
|
12814
13373
|
try {
|
|
12815
|
-
rawText =
|
|
13374
|
+
rawText = readFileSync19(args.input, "utf8");
|
|
12816
13375
|
} catch (err) {
|
|
12817
13376
|
throw new Error(
|
|
12818
13377
|
`Cannot read findings file ${args.input}: ${err.message}`
|
|
@@ -12843,7 +13402,7 @@ function runResolveAnchors(args) {
|
|
|
12843
13402
|
loose: resolved.filter((r) => r.tier?.startsWith("loose")).length
|
|
12844
13403
|
}
|
|
12845
13404
|
};
|
|
12846
|
-
mkdirSync17(
|
|
13405
|
+
mkdirSync17(dirname14(resolve14(args.out)), { recursive: true });
|
|
12847
13406
|
writeFileSync16(args.out, JSON.stringify(report, null, 2), "utf8");
|
|
12848
13407
|
writeStdoutLine(`Wrote resolved anchors to ${args.out}`);
|
|
12849
13408
|
const s = report.stats;
|
|
@@ -12892,7 +13451,7 @@ var resolveAnchorsCommand = {
|
|
|
12892
13451
|
// packages/cli/src/commands/review/check-coverage.ts
|
|
12893
13452
|
init_esbuild_shims();
|
|
12894
13453
|
import { writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "node:fs";
|
|
12895
|
-
import { dirname as
|
|
13454
|
+
import { dirname as dirname15, resolve as resolve15 } from "node:path";
|
|
12896
13455
|
function runCheckCoverage(args) {
|
|
12897
13456
|
let report;
|
|
12898
13457
|
try {
|
|
@@ -12908,7 +13467,7 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12908
13467
|
}
|
|
12909
13468
|
throw err;
|
|
12910
13469
|
}
|
|
12911
|
-
mkdirSync18(
|
|
13470
|
+
mkdirSync18(dirname15(resolve15(args.out)), { recursive: true });
|
|
12912
13471
|
writeFileSync17(args.out, JSON.stringify(report, null, 2));
|
|
12913
13472
|
writeStdoutLine(`Wrote coverage report to ${args.out}`);
|
|
12914
13473
|
const totalChunks = report.coveredChunks.length + report.missingChunks.length + report.uncoverableChunks.length;
|
|
@@ -12965,7 +13524,7 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12965
13524
|
}
|
|
12966
13525
|
if (report.missingChunks.length > 0) {
|
|
12967
13526
|
writeStderrLine(
|
|
12968
|
-
`NOTE: a chunk counts as read when an agent was pointed at its lines AND the harness recorded that agent opening the diff. An agent handed the diff with no line ranges covers nothing.
|
|
13527
|
+
`NOTE: a chunk counts as read when an agent was pointed at its lines AND the harness recorded that agent opening the diff. An agent handed the diff with no line ranges covers nothing. Every rostered agent's launch block \u2014 its diff reads included \u2014 comes from \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt --plan ${shellQuotePath(args.plan)} --roster\` (or \`--role <r>\` for one, \`--chunk <id>\` for a chunk agent \u2014 the usual reader of a missing chunk, which \`--role\` cannot rebuild); pass each verbatim. \`--whole-diff\` builds the reading block for an Agent 8 specialist alone \u2014 prepending it to a rostered brief double-budgets the agent.`
|
|
12969
13528
|
);
|
|
12970
13529
|
}
|
|
12971
13530
|
if (report.idleAgents.length > 0) {
|
|
@@ -12983,6 +13542,12 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12983
13542
|
`ERROR: ${report.missingChunks.length} chunk(s) were not reviewed \u2014 ${report.missingChunks.join(", ")}. Nobody read those lines. Do not aggregate findings over a diff that was not read.`
|
|
12984
13543
|
);
|
|
12985
13544
|
}
|
|
13545
|
+
if (report.budgetGaps.length > 0) {
|
|
13546
|
+
const total = report.budgetGaps.reduce((n, g) => n + g.gaps.length, 0);
|
|
13547
|
+
writeStderrLine(
|
|
13548
|
+
`NOTE: ${total} budget-gap disclosure(s) from ${report.budgetGaps.length} agent(s). Do not relaunch over these; rule on each: a gap naming an incomplete required trace goes in unreviewedDimensions, optional depth is disclosed in the report's "Not reviewed" section. The disclosures \u2014 ` + report.budgetGaps.map((g) => `${g.agent}: ${g.gaps.join("; ")}`).join(" | ")
|
|
13549
|
+
);
|
|
13550
|
+
}
|
|
12986
13551
|
if (!report.ok) {
|
|
12987
13552
|
process.exitCode = 3;
|
|
12988
13553
|
}
|
|
@@ -13007,14 +13572,14 @@ var checkCoverageCommand = {
|
|
|
13007
13572
|
|
|
13008
13573
|
// packages/cli/src/commands/review/agent-prompt.ts
|
|
13009
13574
|
init_esbuild_shims();
|
|
13010
|
-
import { createHash as
|
|
13011
|
-
import { readFileSync as
|
|
13012
|
-
import { dirname as
|
|
13575
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
13576
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
13577
|
+
import { dirname as dirname16, join as join14, resolve as resolve17 } from "node:path";
|
|
13013
13578
|
|
|
13014
13579
|
// packages/cli/src/commands/review/lib/retirement.ts
|
|
13015
13580
|
init_esbuild_shims();
|
|
13016
|
-
import { readFileSync as
|
|
13017
|
-
import { resolve as
|
|
13581
|
+
import { readFileSync as readFileSync20, statSync as statSync11 } from "node:fs";
|
|
13582
|
+
import { resolve as resolve16, sep as sep6 } from "node:path";
|
|
13018
13583
|
var REVERSE_AUDIT_MAX_ROUNDS = 5;
|
|
13019
13584
|
var RECORD_KEY_RE = /^reverse-audit--chunk-(\d+)--round-(\d+)--[0-9a-f]+$/;
|
|
13020
13585
|
var REVERSE_AUDIT_MARKER = "reverse-audit";
|
|
@@ -13056,13 +13621,13 @@ __name(substantiveClause, "substantiveClause");
|
|
|
13056
13621
|
function findingsListFor(prompt, recordDir, memo) {
|
|
13057
13622
|
const pointer = findingsPointerOf(prompt);
|
|
13058
13623
|
if (pointer === null) return prompt;
|
|
13059
|
-
const root =
|
|
13060
|
-
const target =
|
|
13061
|
-
if (target !== root && !target.startsWith(root +
|
|
13624
|
+
const root = resolve16(recordDir);
|
|
13625
|
+
const target = resolve16(pointer);
|
|
13626
|
+
if (target !== root && !target.startsWith(root + sep6)) return prompt;
|
|
13062
13627
|
const cached = memo.get(pointer);
|
|
13063
13628
|
if (cached !== void 0) return cached;
|
|
13064
13629
|
try {
|
|
13065
|
-
const content =
|
|
13630
|
+
const content = readFileSync20(target, "utf8");
|
|
13066
13631
|
memo.set(pointer, content);
|
|
13067
13632
|
return content;
|
|
13068
13633
|
} catch {
|
|
@@ -13080,8 +13645,12 @@ function classifyReturn(rec, territory, findingsList) {
|
|
|
13080
13645
|
return "yielded";
|
|
13081
13646
|
}
|
|
13082
13647
|
}
|
|
13083
|
-
const
|
|
13084
|
-
|
|
13648
|
+
const judged = stripBudgetGapLines(text);
|
|
13649
|
+
const receipt = DRY_RECEIPT_RE.exec(judged);
|
|
13650
|
+
const clause = receipt?.[1] ?? "";
|
|
13651
|
+
const inlineGap = INLINE_BUDGET_GAP_RE.exec(clause);
|
|
13652
|
+
const judgedClause = inlineGap === null ? clause : clause.slice(0, inlineGap.index);
|
|
13653
|
+
if (rec.successfulToolCalls > 0 && rec.diffToolCalls > 0 && openedTheTerritory(rec.diffReads, territory) && receipt !== null && substantiveClause(judgedClause)) {
|
|
13085
13654
|
return "dry";
|
|
13086
13655
|
}
|
|
13087
13656
|
return "unknown";
|
|
@@ -13109,7 +13678,7 @@ function scheduleReverseAuditRound(planPath, chunkIds, round, env = process.env,
|
|
|
13109
13678
|
converged: false
|
|
13110
13679
|
};
|
|
13111
13680
|
}
|
|
13112
|
-
const since =
|
|
13681
|
+
const since = statSync11(planPath).mtimeMs;
|
|
13113
13682
|
const transcripts = readTranscripts(since, env, diffPath);
|
|
13114
13683
|
const built = readRecordedPrompts(planPath, since);
|
|
13115
13684
|
const recordDir = promptRecordDir(planPath);
|
|
@@ -13381,6 +13950,60 @@ function chunkFrom(report, id) {
|
|
|
13381
13950
|
return { diffPath, chunk: chunk2, total: chunks.length };
|
|
13382
13951
|
}
|
|
13383
13952
|
__name(chunkFrom, "chunkFrom");
|
|
13953
|
+
var FINDINGS_LIST_READS = 3;
|
|
13954
|
+
var LINES_PER_FILE_READ = 500;
|
|
13955
|
+
function wholeDiffReadPages(report) {
|
|
13956
|
+
return (Array.isArray(report.chunks) ? report.chunks : []).reduce(
|
|
13957
|
+
(n, c) => {
|
|
13958
|
+
const chars = c?.chars;
|
|
13959
|
+
return n + Math.max(
|
|
13960
|
+
1,
|
|
13961
|
+
Math.ceil(
|
|
13962
|
+
(typeof chars === "number" && Number.isFinite(chars) ? chars : 0) / READ_FILE_CHAR_CAP
|
|
13963
|
+
)
|
|
13964
|
+
);
|
|
13965
|
+
},
|
|
13966
|
+
0
|
|
13967
|
+
);
|
|
13968
|
+
}
|
|
13969
|
+
__name(wholeDiffReadPages, "wholeDiffReadPages");
|
|
13970
|
+
function weightedTerritoryLines(report, chunk2) {
|
|
13971
|
+
const lines = typeof chunk2.lines === "number" && Number.isFinite(chunk2.lines) ? Math.max(0, Math.floor(chunk2.lines)) : 0;
|
|
13972
|
+
if (lines === 0) return 0;
|
|
13973
|
+
const kinds = new Map(
|
|
13974
|
+
(Array.isArray(report.files) ? report.files : []).filter((f) => !!f && typeof f.path === "string").map((f) => [f.path, f.kind])
|
|
13975
|
+
);
|
|
13976
|
+
let src = 0;
|
|
13977
|
+
let other = 0;
|
|
13978
|
+
for (const f of Array.isArray(chunk2.files) ? chunk2.files : []) {
|
|
13979
|
+
const e = f;
|
|
13980
|
+
const span = typeof e?.newStart === "number" && typeof e?.newEnd === "number" ? e.newEnd - e.newStart + 1 : 0;
|
|
13981
|
+
if (!(span > 0)) continue;
|
|
13982
|
+
const kind = typeof e.path === "string" ? kinds.get(e.path) : void 0;
|
|
13983
|
+
if (kind === void 0 || kind === "source") src += span;
|
|
13984
|
+
else other += span;
|
|
13985
|
+
}
|
|
13986
|
+
const total = src + other;
|
|
13987
|
+
if (total === 0) return lines;
|
|
13988
|
+
return Math.max(1, Math.round(lines * (src + other / 8) / total));
|
|
13989
|
+
}
|
|
13990
|
+
__name(weightedTerritoryLines, "weightedTerritoryLines");
|
|
13991
|
+
function toolBudgetBlock(report, launch) {
|
|
13992
|
+
const base = report.budget?.agentToolBudget;
|
|
13993
|
+
if (typeof base !== "number" || !Number.isFinite(base) || base <= 0) {
|
|
13994
|
+
return [];
|
|
13995
|
+
}
|
|
13996
|
+
const reads = Number.isFinite(launch.mandatoryReads) ? Math.max(0, Math.floor(launch.mandatoryReads)) : 0;
|
|
13997
|
+
const territory = typeof launch.territoryLines === "number" && Number.isFinite(launch.territoryLines) ? launch.territoryLines : launch.territoryLines === null || launch.territoryLines === void 0 ? null : 0;
|
|
13998
|
+
const total = launchToolBudget(base, territory, reads);
|
|
13999
|
+
return [
|
|
14000
|
+
"",
|
|
14001
|
+
"## Tool budget",
|
|
14002
|
+
"",
|
|
14003
|
+
`About **${total} tool calls** for this whole review \u2014 reads, greps, shell, everything \u2014 and the ~${reads} reads your launch is assigned (your brief, the diff pages, any files your method mandates) are already counted in. It is a soft ceiling. At the ceiling: stop exploring, write your findings from the evidence already in hand, and disclose each unfinished check on its own line, exactly as \`Budget gap: <the check>\` \u2014 the coverage tool reads those lines, so the format is load-bearing. The budget never suppresses a finding: a candidate you can already name goes in your return regardless (at \`Confidence: low\` if the budget stopped you before verifying it).`
|
|
14004
|
+
];
|
|
14005
|
+
}
|
|
14006
|
+
__name(toolBudgetBlock, "toolBudgetBlock");
|
|
13384
14007
|
function buildChunkAgentPrompt(report, id, rules) {
|
|
13385
14008
|
const { chunk: chunk2, total } = chunkFrom(report, id);
|
|
13386
14009
|
const files = (Array.isArray(chunk2.files) ? chunk2.files : []).filter(
|
|
@@ -13436,6 +14059,21 @@ function buildChunkAgentPrompt(report, id, rules) {
|
|
|
13436
14059
|
if (repositoryContext) {
|
|
13437
14060
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13438
14061
|
}
|
|
14062
|
+
if (!unreachable) {
|
|
14063
|
+
parts.push(
|
|
14064
|
+
...toolBudgetBlock(report, {
|
|
14065
|
+
territoryLines: weightedTerritoryLines(report, chunk2),
|
|
14066
|
+
// The launch's whole reading list: the brief file, plus the diff pages
|
|
14067
|
+
// this chunk takes.
|
|
14068
|
+
mandatoryReads: 1 + Math.max(
|
|
14069
|
+
1,
|
|
14070
|
+
Math.ceil(
|
|
14071
|
+
(Number.isFinite(chunk2.chars) ? chunk2.chars : 0) / READ_FILE_CHAR_CAP
|
|
14072
|
+
)
|
|
14073
|
+
)
|
|
14074
|
+
})
|
|
14075
|
+
);
|
|
14076
|
+
}
|
|
13439
14077
|
parts.push(
|
|
13440
14078
|
"",
|
|
13441
14079
|
"## When you are done",
|
|
@@ -13485,6 +14123,9 @@ function buildWholeDiffBlock(report, rules) {
|
|
|
13485
14123
|
if (repositoryContext) {
|
|
13486
14124
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13487
14125
|
}
|
|
14126
|
+
parts.push(
|
|
14127
|
+
...toolBudgetBlock(report, { mandatoryReads: wholeDiffReadPages(report) })
|
|
14128
|
+
);
|
|
13488
14129
|
parts.push(...tail(rules));
|
|
13489
14130
|
return parts.join("\n");
|
|
13490
14131
|
}
|
|
@@ -13672,6 +14313,56 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13672
14313
|
parts.push("");
|
|
13673
14314
|
}
|
|
13674
14315
|
parts.push("## Your dimension", "", brief.brief);
|
|
14316
|
+
if (!brief.budgetExempt) {
|
|
14317
|
+
const chunks = Array.isArray(report.chunks) ? report.chunks : [];
|
|
14318
|
+
if (typeof opts.chunk === "number") {
|
|
14319
|
+
const c = chunks.find((x) => x?.id === opts.chunk);
|
|
14320
|
+
parts.push(
|
|
14321
|
+
...toolBudgetBlock(report, {
|
|
14322
|
+
territoryLines: weightedTerritoryLines(report, c ?? {}),
|
|
14323
|
+
// Its reading list: the brief file, the chunk's diff pages, and
|
|
14324
|
+
// the cumulative findings list its brief orders read in full —
|
|
14325
|
+
// measured at 65-82 KB on real runs, several pages of it.
|
|
14326
|
+
mandatoryReads: 1 + Math.max(
|
|
14327
|
+
1,
|
|
14328
|
+
Math.ceil(
|
|
14329
|
+
(typeof c?.chars === "number" && Number.isFinite(c.chars) ? c.chars : 0) / READ_FILE_CHAR_CAP
|
|
14330
|
+
)
|
|
14331
|
+
) + FINDINGS_LIST_READS
|
|
14332
|
+
})
|
|
14333
|
+
);
|
|
14334
|
+
} else if (role.startsWith("invariant-") && opts.file) {
|
|
14335
|
+
const files = Array.isArray(report.files) ? report.files : [];
|
|
14336
|
+
const f = files.find((x) => x?.path === opts.file);
|
|
14337
|
+
const added = typeof f?.addedLines === "number" ? f.addedLines : 0;
|
|
14338
|
+
const fileLines = typeof f?.fileLines === "number" && Number.isFinite(f.fileLines) ? f.fileLines : 0;
|
|
14339
|
+
const changed = added + (typeof f?.removedLines === "number" ? f.removedLines : 0);
|
|
14340
|
+
parts.push(
|
|
14341
|
+
...toolBudgetBlock(report, {
|
|
14342
|
+
territoryLines: changed,
|
|
14343
|
+
// Its reading list: the brief, its own diff slice, and the whole
|
|
14344
|
+
// post-change file paged to the end. The pages come from
|
|
14345
|
+
// `fileLines` — the post-change length the plan records for
|
|
14346
|
+
// every file — with `addedLines` as the fallback lower bound
|
|
14347
|
+
// for an older plan without it: a file can go heavy by VOLUME
|
|
14348
|
+
// in a large file it barely rewrote, and estimating its paging
|
|
14349
|
+
// from added lines alone told exactly that agent its mandatory
|
|
14350
|
+
// reading was already overspending. Floors at the old flat 4 so
|
|
14351
|
+
// no launch gets less than before.
|
|
14352
|
+
mandatoryReads: Math.max(
|
|
14353
|
+
4,
|
|
14354
|
+
2 + Math.ceil(Math.max(added, fileLines) / LINES_PER_FILE_READ)
|
|
14355
|
+
)
|
|
14356
|
+
})
|
|
14357
|
+
);
|
|
14358
|
+
} else {
|
|
14359
|
+
parts.push(
|
|
14360
|
+
...toolBudgetBlock(report, {
|
|
14361
|
+
mandatoryReads: 1 + wholeDiffReadPages(report) + (brief.acceptsFindings ? FINDINGS_LIST_READS : 0)
|
|
14362
|
+
})
|
|
14363
|
+
);
|
|
14364
|
+
}
|
|
14365
|
+
}
|
|
13675
14366
|
const repositoryContext = repositoryContextOf(report);
|
|
13676
14367
|
if (role === "7") {
|
|
13677
14368
|
if (repositoryContext) {
|
|
@@ -13702,7 +14393,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13702
14393
|
"agent-prompt: --role 0 needs a plan with `prNumber` and `ownerRepo` (the report `fetch-pr` writes). Issue fidelity has nothing to check against without a pull request."
|
|
13703
14394
|
);
|
|
13704
14395
|
}
|
|
13705
|
-
const ctx = opts.planPath ?
|
|
14396
|
+
const ctx = opts.planPath ? join14(dirname16(resolve17(opts.planPath)), `qwen-review-pr-${pr}-context.md`) : null;
|
|
13706
14397
|
parts.push(
|
|
13707
14398
|
"",
|
|
13708
14399
|
`**This PR:** #${pr} of \`${repo}\`. Use exactly that number and repo \u2014 a bare \`gh pr view\` falls back to the current branch's PR and would judge this diff against an unrelated issue.`
|
|
@@ -13724,7 +14415,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13724
14415
|
}
|
|
13725
14416
|
const base = report.mergeBaseSha;
|
|
13726
14417
|
const pr = report.prNumber;
|
|
13727
|
-
const buildTree = typeof wt === "string" && wt ?
|
|
14418
|
+
const buildTree = typeof wt === "string" && wt ? resolve17(wt) : pr === void 0 && opts.planPath ? "." : null;
|
|
13728
14419
|
if (buildTree && opts.planPath) {
|
|
13729
14420
|
const outName = pr !== void 0 ? `qwen-review-pr-${pr}-build-test.json` : "qwen-review-build-test.json";
|
|
13730
14421
|
parts.push(
|
|
@@ -13740,9 +14431,9 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13740
14431
|
// that an old global lacks it entirely, wedging Agent 7 between its
|
|
13741
14432
|
// mandate (no hand-run `npm run build`) and a command that does not exist.
|
|
13742
14433
|
`"\${QWEN_CODE_CLI:-qwen}" review build-test \\`,
|
|
13743
|
-
` --plan ${
|
|
13744
|
-
` --worktree ${
|
|
13745
|
-
` --out ${
|
|
14434
|
+
` --plan ${resolve17(opts.planPath)} \\`,
|
|
14435
|
+
` --worktree ${resolve17(buildTree)} \\`,
|
|
14436
|
+
` --out ${resolve17(dirname16(opts.planPath), outName)}`,
|
|
13746
14437
|
"```"
|
|
13747
14438
|
);
|
|
13748
14439
|
}
|
|
@@ -13752,10 +14443,10 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13752
14443
|
"**Then run the test-efficacy probe.** A green suite says the tests pass. It does not say they would have failed had the change been wrong, and those are different claims. Give this call `timeout: 600000` too \u2014 besides the revert probe it runs up to 8 single-statement deletion mutants and up to 6 per-hunk reverse-apply probes, each a suite run, and it budgets itself to finish inside that ceiling:",
|
|
13753
14444
|
"",
|
|
13754
14445
|
"```bash",
|
|
13755
|
-
`"\${QWEN_CODE_CLI:-qwen}" review test-efficacy ${
|
|
13756
|
-
` --worktree ${typeof wt === "string" ?
|
|
14446
|
+
`"\${QWEN_CODE_CLI:-qwen}" review test-efficacy ${resolve17(opts.planPath)} \\`,
|
|
14447
|
+
` --worktree ${typeof wt === "string" ? resolve17(wt) : "<worktree>"} \\`,
|
|
13757
14448
|
` --base ${base} \\`,
|
|
13758
|
-
` --out ${
|
|
14449
|
+
` --out ${resolve17(dirname16(opts.planPath), `qwen-review-pr-${pr}-efficacy.json`)}`,
|
|
13759
14450
|
"```",
|
|
13760
14451
|
"",
|
|
13761
14452
|
'Read its `findings[]`. `kind: "unreachable"` is a test the project\'s test command never collects \u2014 it did not run here and it does not run in CI. `kind: "inert"` is a test that **still passed with the change reverted**: it is green whether or not the feature exists, so it cannot catch a regression in it. `kind: "mutant-survived"` is a single safety statement the diff added (a `.clear()`, an `.abort(\u2026)`, a reset-to-empty) that was **deleted and every affected test stayed green** \u2014 no test in the diff fails when it is removed, which the whole-file revert cannot see when the file\'s other, tested behaviours mask it. `kind: "hunk-survived"` is one HUNK reverted on its own with every affected test still green \u2014 that specific change ships with nothing gating it. Report each of the four as a **Suggestion** with `Source: [test]`, saying plainly which behaviour has no test in this diff that would catch its removal. `harnessValidated` has THREE values and they are not two: `false` means the positive control failed and every would-be survivor was re-classed \u2014 say the harness could not be validated instead of implying clean coverage; `null` means the control never ran, so the run is neither validated nor refuted and any survivor below is unconfirmed by a control; only `true` licenses reading a survivor as a coverage gap. **`inconclusive` is not a finding** \u2014 for probes, mutants and hunks alike, reverting or mutating the source often breaks the test\'s own compile, and that is not the test catching anything. Entries counted in `mutants.skipped*` or `hunks.skipped*` never ran \u2014 not findings either, and `skippedForControl` in particular means the control stopped the run, NOT that the window ran out. `mutants.note`, when present, explains why no mutants ran at all. Note them and move on.'
|
|
@@ -13921,7 +14612,7 @@ function buildLaunch(report, planPath, spec, rules) {
|
|
|
13921
14612
|
}
|
|
13922
14613
|
__name(buildLaunch, "buildLaunch");
|
|
13923
14614
|
function findingsDigest(content, rules) {
|
|
13924
|
-
return
|
|
14615
|
+
return createHash4("sha256").update(JSON.stringify([content, rules ?? null])).digest("hex").slice(0, 12);
|
|
13925
14616
|
}
|
|
13926
14617
|
__name(findingsDigest, "findingsDigest");
|
|
13927
14618
|
function foldFindings(role, content, prompt, findingsFile) {
|
|
@@ -14215,7 +14906,7 @@ function runAgentPrompt(args) {
|
|
|
14215
14906
|
}
|
|
14216
14907
|
let report;
|
|
14217
14908
|
try {
|
|
14218
|
-
report = JSON.parse(
|
|
14909
|
+
report = JSON.parse(readFileSync21(args.plan, "utf8"));
|
|
14219
14910
|
} catch (err) {
|
|
14220
14911
|
throw new Error(
|
|
14221
14912
|
`agent-prompt: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -14224,7 +14915,7 @@ function runAgentPrompt(args) {
|
|
|
14224
14915
|
let rules;
|
|
14225
14916
|
if (args.rules) {
|
|
14226
14917
|
try {
|
|
14227
|
-
rules =
|
|
14918
|
+
rules = readFileSync21(args.rules, "utf8");
|
|
14228
14919
|
} catch (err) {
|
|
14229
14920
|
throw new Error(
|
|
14230
14921
|
`agent-prompt: cannot read the rules ${args.rules}: ${err.message}. Omit --rules if this review has none; passing a path that does not resolve would silently review without the project rules it was told to enforce.`
|
|
@@ -14239,7 +14930,7 @@ function runAgentPrompt(args) {
|
|
|
14239
14930
|
if (hasFindings && args.role) {
|
|
14240
14931
|
const role = args.role;
|
|
14241
14932
|
try {
|
|
14242
|
-
findingsContent =
|
|
14933
|
+
findingsContent = readFileSync21(args.findings, "utf8");
|
|
14243
14934
|
} catch (err) {
|
|
14244
14935
|
throw new Error(
|
|
14245
14936
|
`agent-prompt: cannot read the findings ${args.findings}: ${err.message}. Pass a path that resolves \u2014 --findings is required for this role, so omitting it only fails one guard earlier. An early reverse-audit round with nothing confirmed passes an empty file (create it first).`
|
|
@@ -14384,18 +15075,18 @@ var agentPromptCommand = {
|
|
|
14384
15075
|
init_esbuild_shims();
|
|
14385
15076
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
14386
15077
|
import {
|
|
14387
|
-
existsSync as
|
|
14388
|
-
readFileSync as
|
|
15078
|
+
existsSync as existsSync9,
|
|
15079
|
+
readFileSync as readFileSync23,
|
|
14389
15080
|
rmSync as rmSync5,
|
|
14390
15081
|
statfsSync,
|
|
14391
15082
|
writeFileSync as writeFileSync18
|
|
14392
15083
|
} from "node:fs";
|
|
14393
|
-
import { join as
|
|
15084
|
+
import { join as join16, resolve as resolve18 } from "node:path";
|
|
14394
15085
|
|
|
14395
15086
|
// packages/cli/src/commands/review/lib/workspaces.ts
|
|
14396
15087
|
init_esbuild_shims();
|
|
14397
|
-
import { existsSync as
|
|
14398
|
-
import { join as
|
|
15088
|
+
import { existsSync as existsSync8, readFileSync as readFileSync22, readdirSync as readdirSync6 } from "node:fs";
|
|
15089
|
+
import { join as join15 } from "node:path";
|
|
14399
15090
|
function isWorkspaceMember(filePath, workspaceGlobs) {
|
|
14400
15091
|
return workspaceDirFor(filePath, workspaceGlobs) !== null;
|
|
14401
15092
|
}
|
|
@@ -14447,7 +15138,7 @@ __name(hasUnmodeledWorkspaceGlob, "hasUnmodeledWorkspaceGlob");
|
|
|
14447
15138
|
function readWorkspaceGlobs(root) {
|
|
14448
15139
|
try {
|
|
14449
15140
|
const pkg = JSON.parse(
|
|
14450
|
-
|
|
15141
|
+
readFileSync22(join15(root, "package.json"), "utf8")
|
|
14451
15142
|
);
|
|
14452
15143
|
const ws = pkg.workspaces;
|
|
14453
15144
|
const globs = Array.isArray(ws) ? ws : Array.isArray(ws?.packages) ? ws.packages : [];
|
|
@@ -14460,7 +15151,7 @@ __name(readWorkspaceGlobs, "readWorkspaceGlobs");
|
|
|
14460
15151
|
function readRootPackage(root) {
|
|
14461
15152
|
let pkg;
|
|
14462
15153
|
try {
|
|
14463
|
-
pkg = JSON.parse(
|
|
15154
|
+
pkg = JSON.parse(readFileSync22(join15(root, "package.json"), "utf8"));
|
|
14464
15155
|
} catch {
|
|
14465
15156
|
return null;
|
|
14466
15157
|
}
|
|
@@ -14502,8 +15193,8 @@ function workspaceDirCandidates(root, globs) {
|
|
|
14502
15193
|
const base = g.slice(0, -2);
|
|
14503
15194
|
let entries;
|
|
14504
15195
|
try {
|
|
14505
|
-
entries =
|
|
14506
|
-
(e) => e.isDirectory() || e.isSymbolicLink() &&
|
|
15196
|
+
entries = readdirSync6(join15(root, base), { withFileTypes: true }).filter(
|
|
15197
|
+
(e) => e.isDirectory() || e.isSymbolicLink() && existsSync8(join15(root, base, e.name, "package.json"))
|
|
14507
15198
|
).map((e) => e.name);
|
|
14508
15199
|
} catch {
|
|
14509
15200
|
continue;
|
|
@@ -14521,8 +15212,8 @@ function readWorkspacePackages(root) {
|
|
|
14521
15212
|
const packages = [];
|
|
14522
15213
|
const skipped = [];
|
|
14523
15214
|
for (const dir of workspaceDirCandidates(root, globs)) {
|
|
14524
|
-
const manifest =
|
|
14525
|
-
if (!
|
|
15215
|
+
const manifest = join15(root, dir, "package.json");
|
|
15216
|
+
if (!existsSync8(manifest)) continue;
|
|
14526
15217
|
if (workspaceDirFor(`${dir}/package.json`, globs) !== dir) {
|
|
14527
15218
|
const positives = globs.filter((g) => !g.startsWith("!"));
|
|
14528
15219
|
if (workspaceDirFor(`${dir}/package.json`, positives) === dir) continue;
|
|
@@ -14531,7 +15222,7 @@ function readWorkspacePackages(root) {
|
|
|
14531
15222
|
}
|
|
14532
15223
|
let pkg;
|
|
14533
15224
|
try {
|
|
14534
|
-
pkg = JSON.parse(
|
|
15225
|
+
pkg = JSON.parse(readFileSync22(manifest, "utf8"));
|
|
14535
15226
|
} catch {
|
|
14536
15227
|
skipped.push(dir);
|
|
14537
15228
|
continue;
|
|
@@ -14788,7 +15479,7 @@ __name(unresolvedWorkspaceDeps, "unresolvedWorkspaceDeps");
|
|
|
14788
15479
|
function changedFilesFrom(planPath) {
|
|
14789
15480
|
let parsed;
|
|
14790
15481
|
try {
|
|
14791
|
-
parsed = JSON.parse(
|
|
15482
|
+
parsed = JSON.parse(readFileSync23(planPath, "utf8"));
|
|
14792
15483
|
} catch (err) {
|
|
14793
15484
|
throw new Error(
|
|
14794
15485
|
`build-test: cannot read the plan ${planPath}: ${err.message}`
|
|
@@ -14805,7 +15496,7 @@ function changedFilesFrom(planPath) {
|
|
|
14805
15496
|
}
|
|
14806
15497
|
__name(changedFilesFrom, "changedFilesFrom");
|
|
14807
15498
|
function runBuildTest(args) {
|
|
14808
|
-
const root =
|
|
15499
|
+
const root = resolve18(args.worktree);
|
|
14809
15500
|
const perCommandMs = args.timeout * 1e3;
|
|
14810
15501
|
const callBudgetMs = (args.budget ?? Math.max(args.timeout, args.timeout * 2 - 30)) * 1e3;
|
|
14811
15502
|
const runStarted = Date.now();
|
|
@@ -14883,15 +15574,15 @@ function runBuildTest(args) {
|
|
|
14883
15574
|
timedOut: [],
|
|
14884
15575
|
note: ""
|
|
14885
15576
|
};
|
|
14886
|
-
const npmLock =
|
|
14887
|
-
const installComplete = /* @__PURE__ */ __name(() =>
|
|
14888
|
-
if (args.install && !npmLock && !
|
|
15577
|
+
const npmLock = existsSync9(join16(root, "package-lock.json"));
|
|
15578
|
+
const installComplete = /* @__PURE__ */ __name(() => existsSync9(join16(root, "node_modules", ".package-lock.json")), "installComplete");
|
|
15579
|
+
if (args.install && !npmLock && !existsSync9(join16(root, "node_modules"))) {
|
|
14889
15580
|
const altLock = [
|
|
14890
15581
|
["yarn.lock", "yarn install --frozen-lockfile"],
|
|
14891
15582
|
["pnpm-lock.yaml", "pnpm install --frozen-lockfile"],
|
|
14892
15583
|
["bun.lockb", "bun install --frozen-lockfile"],
|
|
14893
15584
|
["bun.lock", "bun install --frozen-lockfile"]
|
|
14894
|
-
].find(([f]) =>
|
|
15585
|
+
].find(([f]) => existsSync9(join16(root, f)));
|
|
14895
15586
|
return unsupportedReport(
|
|
14896
15587
|
altLock ? `This is a ${altLock[0]} repo with no installed \`node_modules\`, so \`npm ci\` cannot install it. Run \`${altLock[1]}\` first, then fall back to the build/test precedence in your brief, each command with a deadline it can meet.` : "There is no lockfile and no `node_modules` here, so nothing can be installed deterministically. Install dependencies first, then fall back to the build/test precedence in your brief."
|
|
14897
15588
|
);
|
|
@@ -14918,7 +15609,7 @@ function runBuildTest(args) {
|
|
|
14918
15609
|
if (install.timedOut) results.timedOut.push(install.command);
|
|
14919
15610
|
if (install.timedOut) {
|
|
14920
15611
|
try {
|
|
14921
|
-
rmSync5(
|
|
15612
|
+
rmSync5(join16(root, "node_modules"), {
|
|
14922
15613
|
recursive: true,
|
|
14923
15614
|
force: true,
|
|
14924
15615
|
maxRetries: 3
|
|
@@ -15131,14 +15822,14 @@ var buildTestCommand = {
|
|
|
15131
15822
|
init_esbuild_shims();
|
|
15132
15823
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
15133
15824
|
import {
|
|
15134
|
-
existsSync as
|
|
15825
|
+
existsSync as existsSync10,
|
|
15135
15826
|
mkdirSync as mkdirSync19,
|
|
15136
|
-
readFileSync as
|
|
15827
|
+
readFileSync as readFileSync24,
|
|
15137
15828
|
rmSync as rmSync7,
|
|
15138
|
-
statSync as
|
|
15829
|
+
statSync as statSync12,
|
|
15139
15830
|
writeFileSync as writeFileSync19
|
|
15140
15831
|
} from "node:fs";
|
|
15141
|
-
import { dirname as
|
|
15832
|
+
import { dirname as dirname17, join as join17, resolve as resolve19 } from "node:path";
|
|
15142
15833
|
|
|
15143
15834
|
// packages/cli/src/commands/review/lib/worktree.ts
|
|
15144
15835
|
init_esbuild_shims();
|
|
@@ -15185,7 +15876,7 @@ function runBaseTree(args) {
|
|
|
15185
15876
|
}), "unavailable");
|
|
15186
15877
|
let plan;
|
|
15187
15878
|
try {
|
|
15188
|
-
plan = JSON.parse(
|
|
15879
|
+
plan = JSON.parse(readFileSync24(args.plan, "utf8"));
|
|
15189
15880
|
} catch (err) {
|
|
15190
15881
|
return unavailable(
|
|
15191
15882
|
`cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -15202,15 +15893,15 @@ function runBaseTree(args) {
|
|
|
15202
15893
|
"the base branch could not be fetched, so mergeBaseSha may be stale; an A/B against it would attribute the base branch's own commits to this PR"
|
|
15203
15894
|
);
|
|
15204
15895
|
}
|
|
15205
|
-
const worktree =
|
|
15206
|
-
if (!
|
|
15896
|
+
const worktree = resolve19(args.worktree);
|
|
15897
|
+
if (!existsSync10(worktree)) {
|
|
15207
15898
|
return unavailable(`the review worktree ${worktree} does not exist`);
|
|
15208
15899
|
}
|
|
15209
15900
|
const tree = baseWorktreePath(worktree);
|
|
15210
|
-
const marker = /* @__PURE__ */ __name(() =>
|
|
15211
|
-
const failedMarker = /* @__PURE__ */ __name(() =>
|
|
15901
|
+
const marker = /* @__PURE__ */ __name(() => join17(tree, ".qwen-review-base-ok"), "marker");
|
|
15902
|
+
const failedMarker = /* @__PURE__ */ __name(() => join17(tree, ".qwen-review-base-failed"), "failedMarker");
|
|
15212
15903
|
try {
|
|
15213
|
-
if (
|
|
15904
|
+
if (existsSync10(tree) && readFileSync24(marker(), "utf8").trim() === baseSha && gitOut(tree, "rev-parse", "HEAD") === baseSha) {
|
|
15214
15905
|
return {
|
|
15215
15906
|
available: true,
|
|
15216
15907
|
path: tree,
|
|
@@ -15222,7 +15913,7 @@ function runBaseTree(args) {
|
|
|
15222
15913
|
} catch {
|
|
15223
15914
|
}
|
|
15224
15915
|
try {
|
|
15225
|
-
if (
|
|
15916
|
+
if (existsSync10(tree) && readFileSync24(failedMarker(), "utf8").trim() === baseSha) {
|
|
15226
15917
|
return {
|
|
15227
15918
|
available: false,
|
|
15228
15919
|
path: tree,
|
|
@@ -15235,7 +15926,7 @@ function runBaseTree(args) {
|
|
|
15235
15926
|
}
|
|
15236
15927
|
const lock = `${tree}.lock`;
|
|
15237
15928
|
try {
|
|
15238
|
-
const age = Date.now() -
|
|
15929
|
+
const age = Date.now() - statSync12(lock).mtimeMs;
|
|
15239
15930
|
if (age > 30 * 60 * 1e3) {
|
|
15240
15931
|
rmSync7(lock, { recursive: true, force: true });
|
|
15241
15932
|
}
|
|
@@ -15342,8 +16033,8 @@ var baseTreeCommand = {
|
|
|
15342
16033
|
try {
|
|
15343
16034
|
const report = runBaseTree(args);
|
|
15344
16035
|
if (args.out) {
|
|
15345
|
-
mkdirSync19(
|
|
15346
|
-
writeFileSync19(
|
|
16036
|
+
mkdirSync19(dirname17(resolve19(args.out)), { recursive: true });
|
|
16037
|
+
writeFileSync19(resolve19(args.out), JSON.stringify(report, null, 2));
|
|
15347
16038
|
}
|
|
15348
16039
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15349
16040
|
writeStderrLine(`base-tree: ${report.note}`);
|
|
@@ -15357,8 +16048,8 @@ var baseTreeCommand = {
|
|
|
15357
16048
|
// packages/cli/src/commands/review/test-delta.ts
|
|
15358
16049
|
init_esbuild_shims();
|
|
15359
16050
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
15360
|
-
import { existsSync as
|
|
15361
|
-
import { dirname as
|
|
16051
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync20, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "node:fs";
|
|
16052
|
+
import { dirname as dirname18, resolve as resolve20 } from "node:path";
|
|
15362
16053
|
var ANSI_SGR_RE2 = /\x1b\[[0-9;]*m/g;
|
|
15363
16054
|
var RERUNNABLE_COMMAND_RE = /^npm test(?: --workspace="[\w@./-]+")?$/;
|
|
15364
16055
|
var TRIM_MARKER_RE = /\.\.\. \[\d+ characters omitted/;
|
|
@@ -15421,7 +16112,7 @@ var TOTAL_BUDGET_MS = 54e4;
|
|
|
15421
16112
|
var DEFAULT_TIMEOUT_S = 300;
|
|
15422
16113
|
function runTestDelta(args) {
|
|
15423
16114
|
const exec = args.exec ?? run2;
|
|
15424
|
-
const baseline =
|
|
16115
|
+
const baseline = resolve20(args.baseline);
|
|
15425
16116
|
const empty = /* @__PURE__ */ __name((note) => ({
|
|
15426
16117
|
entries: [],
|
|
15427
16118
|
netNew: [],
|
|
@@ -15431,13 +16122,13 @@ function runTestDelta(args) {
|
|
|
15431
16122
|
}), "empty");
|
|
15432
16123
|
let report;
|
|
15433
16124
|
try {
|
|
15434
|
-
report = JSON.parse(
|
|
16125
|
+
report = JSON.parse(readFileSync25(args.report, "utf8"));
|
|
15435
16126
|
} catch (err) {
|
|
15436
16127
|
return empty(
|
|
15437
16128
|
`cannot read the build-test report ${args.report}: ${err.message}`
|
|
15438
16129
|
);
|
|
15439
16130
|
}
|
|
15440
|
-
if (!
|
|
16131
|
+
if (!existsSync11(baseline)) {
|
|
15441
16132
|
return empty(
|
|
15442
16133
|
`the base tree ${baseline} does not exist \u2014 run \`qwen review base-tree\` first`
|
|
15443
16134
|
);
|
|
@@ -15573,8 +16264,8 @@ var testDeltaCommand = {
|
|
|
15573
16264
|
const args = argv;
|
|
15574
16265
|
const report = runTestDelta(args);
|
|
15575
16266
|
if (args.out) {
|
|
15576
|
-
mkdirSync20(
|
|
15577
|
-
writeFileSync20(
|
|
16267
|
+
mkdirSync20(dirname18(resolve20(args.out)), { recursive: true });
|
|
16268
|
+
writeFileSync20(resolve20(args.out), JSON.stringify(report, null, 2));
|
|
15578
16269
|
}
|
|
15579
16270
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15580
16271
|
writeStderrLine(`test-delta: ${report.note}`);
|
|
@@ -15587,12 +16278,12 @@ import { spawnSync as spawnSync7 } from "node:child_process";
|
|
|
15587
16278
|
import {
|
|
15588
16279
|
mkdirSync as mkdirSync21,
|
|
15589
16280
|
writeFileSync as writeFileSync21,
|
|
15590
|
-
readFileSync as
|
|
15591
|
-
existsSync as
|
|
16281
|
+
readFileSync as readFileSync26,
|
|
16282
|
+
existsSync as existsSync12,
|
|
15592
16283
|
rmSync as rmSync8,
|
|
15593
|
-
statSync as
|
|
16284
|
+
statSync as statSync13
|
|
15594
16285
|
} from "node:fs";
|
|
15595
|
-
import { dirname as
|
|
16286
|
+
import { dirname as dirname19, join as join18, resolve as resolve21 } from "node:path";
|
|
15596
16287
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
15597
16288
|
var SERVER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
15598
16289
|
function shellQuote(v) {
|
|
@@ -15604,7 +16295,7 @@ var LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
|
15604
16295
|
var POLL_MS = 250;
|
|
15605
16296
|
function logBytes(p) {
|
|
15606
16297
|
try {
|
|
15607
|
-
return
|
|
16298
|
+
return statSync13(p).size;
|
|
15608
16299
|
} catch {
|
|
15609
16300
|
return 0;
|
|
15610
16301
|
}
|
|
@@ -15710,11 +16401,11 @@ function runDrive(args) {
|
|
|
15710
16401
|
waitMs(POLL_MS);
|
|
15711
16402
|
}
|
|
15712
16403
|
}
|
|
15713
|
-
const dir =
|
|
16404
|
+
const dir = join18(tmpdir2(), `qwen-review-drive-${server}`);
|
|
15714
16405
|
mkdirSync21(dir, { recursive: true });
|
|
15715
|
-
const scriptPath =
|
|
15716
|
-
const logPath = args.logPath ??
|
|
15717
|
-
const sentinelPath =
|
|
16406
|
+
const scriptPath = join18(dir, "drive.sh");
|
|
16407
|
+
const logPath = args.logPath ?? join18(dir, "drive.log");
|
|
16408
|
+
const sentinelPath = join18(dir, "drive.rc");
|
|
15718
16409
|
rmSync8(sentinelPath, { force: true });
|
|
15719
16410
|
writeFileSync21(scriptPath, wrapScript(args.script, sentinelPath), "utf8");
|
|
15720
16411
|
const droveFrom = Date.now();
|
|
@@ -15746,8 +16437,8 @@ function runDrive(args) {
|
|
|
15746
16437
|
}
|
|
15747
16438
|
const deadline = droveFrom + args.timeout * 1e3;
|
|
15748
16439
|
for (; ; ) {
|
|
15749
|
-
output =
|
|
15750
|
-
exitCode =
|
|
16440
|
+
output = existsSync12(logPath) ? readFileSync26(logPath, "utf8") : "";
|
|
16441
|
+
exitCode = existsSync12(sentinelPath) ? sentinelExitCode(readFileSync26(sentinelPath, "utf8")) : null;
|
|
15751
16442
|
if (exitCode !== null) {
|
|
15752
16443
|
outcome = "completed";
|
|
15753
16444
|
break;
|
|
@@ -15811,11 +16502,13 @@ var driveCommand = {
|
|
|
15811
16502
|
}), "builder"),
|
|
15812
16503
|
handler: /* @__PURE__ */ __name((argv) => {
|
|
15813
16504
|
try {
|
|
16505
|
+
const bundleNotice = bundleStalenessNotices(process.argv[1], true);
|
|
16506
|
+
if (bundleNotice) writeStderrLineSafe(bundleNotice);
|
|
15814
16507
|
const args = argv;
|
|
15815
16508
|
const report = runDrive(args);
|
|
15816
16509
|
if (args.out) {
|
|
15817
|
-
mkdirSync21(
|
|
15818
|
-
writeFileSync21(
|
|
16510
|
+
mkdirSync21(dirname19(resolve21(args.out)), { recursive: true });
|
|
16511
|
+
writeFileSync21(resolve21(args.out), JSON.stringify(report, null, 2));
|
|
15819
16512
|
}
|
|
15820
16513
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15821
16514
|
writeStderrLine(`drive: ${report.note}`);
|
|
@@ -15833,7 +16526,7 @@ import {
|
|
|
15833
16526
|
createServer
|
|
15834
16527
|
} from "node:http";
|
|
15835
16528
|
import { appendFileSync, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
|
|
15836
|
-
import { dirname as
|
|
16529
|
+
import { dirname as dirname20, resolve as resolve22 } from "node:path";
|
|
15837
16530
|
import { pathToFileURL } from "node:url";
|
|
15838
16531
|
function messagesText(body) {
|
|
15839
16532
|
const msgs = Array.isArray(body?.["messages"]) ? body["messages"] : [];
|
|
@@ -16079,7 +16772,7 @@ var DEFAULT_REPLY = { text: "ok" };
|
|
|
16079
16772
|
async function startMockProvider(args, respondOverride) {
|
|
16080
16773
|
let respond = respondOverride ?? (() => DEFAULT_REPLY);
|
|
16081
16774
|
if (!respondOverride && args.responder) {
|
|
16082
|
-
const mod = await import(pathToFileURL(
|
|
16775
|
+
const mod = await import(pathToFileURL(resolve22(args.responder)).href);
|
|
16083
16776
|
const fn = mod.respond ?? mod.default;
|
|
16084
16777
|
if (typeof fn !== "function") {
|
|
16085
16778
|
throw new Error(
|
|
@@ -16088,8 +16781,8 @@ async function startMockProvider(args, respondOverride) {
|
|
|
16088
16781
|
}
|
|
16089
16782
|
respond = fn;
|
|
16090
16783
|
}
|
|
16091
|
-
const logPath =
|
|
16092
|
-
mkdirSync22(
|
|
16784
|
+
const logPath = resolve22(args.log);
|
|
16785
|
+
mkdirSync22(dirname20(logPath), { recursive: true });
|
|
16093
16786
|
writeFileSync22(logPath, "");
|
|
16094
16787
|
let n = 0;
|
|
16095
16788
|
const record = /* @__PURE__ */ __name((entry) => appendFileSync(logPath, `${JSON.stringify(entry)}
|
|
@@ -16252,8 +16945,8 @@ var mockProviderCommand = {
|
|
|
16252
16945
|
const args = argv;
|
|
16253
16946
|
const { report, close } = await startMockProvider(args);
|
|
16254
16947
|
if (args.out) {
|
|
16255
|
-
mkdirSync22(
|
|
16256
|
-
writeFileSync22(
|
|
16948
|
+
mkdirSync22(dirname20(resolve22(args.out)), { recursive: true });
|
|
16949
|
+
writeFileSync22(resolve22(args.out), JSON.stringify(report, null, 2));
|
|
16257
16950
|
}
|
|
16258
16951
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
16259
16952
|
writeStderrLine(`mock-provider: ${report.note}`);
|
|
@@ -16271,8 +16964,8 @@ var mockProviderCommand = {
|
|
|
16271
16964
|
// packages/cli/src/commands/review/extract-step.ts
|
|
16272
16965
|
init_esbuild_shims();
|
|
16273
16966
|
var import_yaml = __toESM(require_dist(), 1);
|
|
16274
|
-
import { mkdirSync as mkdirSync23, readFileSync as
|
|
16275
|
-
import { dirname as
|
|
16967
|
+
import { mkdirSync as mkdirSync23, readFileSync as readFileSync27, writeFileSync as writeFileSync23, chmodSync } from "node:fs";
|
|
16968
|
+
import { dirname as dirname21, resolve as resolve23 } from "node:path";
|
|
16276
16969
|
function expressionsOf(...texts) {
|
|
16277
16970
|
const seen = /* @__PURE__ */ new Set();
|
|
16278
16971
|
for (const t2 of texts) {
|
|
@@ -16516,10 +17209,10 @@ function nearestFirst(env, sources) {
|
|
|
16516
17209
|
}
|
|
16517
17210
|
__name(nearestFirst, "nearestFirst");
|
|
16518
17211
|
function runExtractStep(args) {
|
|
16519
|
-
const wfPath =
|
|
17212
|
+
const wfPath = resolve23(args.workflow);
|
|
16520
17213
|
let text;
|
|
16521
17214
|
try {
|
|
16522
|
-
text =
|
|
17215
|
+
text = readFileSync27(wfPath, "utf8");
|
|
16523
17216
|
} catch (err) {
|
|
16524
17217
|
throw new Error(
|
|
16525
17218
|
`extract-step: cannot read ${args.workflow}: ${err.message}`
|
|
@@ -16585,8 +17278,8 @@ function runExtractStep(args) {
|
|
|
16585
17278
|
const workingDirectory = workingDir?.value;
|
|
16586
17279
|
const script = step.run;
|
|
16587
17280
|
const stepLabel = String(step.name ?? step.id ?? index);
|
|
16588
|
-
const outPath =
|
|
16589
|
-
mkdirSync23(
|
|
17281
|
+
const outPath = resolve23(args.out);
|
|
17282
|
+
mkdirSync23(dirname21(outPath), { recursive: true });
|
|
16590
17283
|
const header = [
|
|
16591
17284
|
`#!/usr/bin/env ${shellCommand}`,
|
|
16592
17285
|
...commentLines(
|
|
@@ -16671,7 +17364,7 @@ var extractStepCommand = {
|
|
|
16671
17364
|
|
|
16672
17365
|
// packages/cli/src/commands/review/submit.ts
|
|
16673
17366
|
init_esbuild_shims();
|
|
16674
|
-
import { mkdirSync as mkdirSync24, readFileSync as
|
|
17367
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync28 } from "node:fs";
|
|
16675
17368
|
|
|
16676
17369
|
// packages/cli/src/commands/review/lib/receipt.ts
|
|
16677
17370
|
init_esbuild_shims();
|
|
@@ -16693,7 +17386,7 @@ __name(parseReceiptIds, "parseReceiptIds");
|
|
|
16693
17386
|
var EVENTS = /* @__PURE__ */ new Set(["APPROVE", "REQUEST_CHANGES", "COMMENT"]);
|
|
16694
17387
|
function readReceiptIds(receiptPath) {
|
|
16695
17388
|
try {
|
|
16696
|
-
return parseReceiptIds(
|
|
17389
|
+
return parseReceiptIds(readFileSync28(receiptPath, "utf8"));
|
|
16697
17390
|
} catch {
|
|
16698
17391
|
return [];
|
|
16699
17392
|
}
|
|
@@ -16729,12 +17422,8 @@ function authorization(args) {
|
|
|
16729
17422
|
repo: args.repo,
|
|
16730
17423
|
// The EFFECTIVE host, not merely the flag: with --host absent the gh
|
|
16731
17424
|
// child inherits an operator-exported GH_HOST, so that is where this
|
|
16732
|
-
// write would route — and what the gate must bind.
|
|
16733
|
-
|
|
16734
|
-
// `|| undefined`, not `??`: an exported-but-empty GH_HOST ("" survives
|
|
16735
|
-
// `??`, being non-nullish) must read as "no host", not as a host named
|
|
16736
|
-
// "" that fails every comparison.
|
|
16737
|
-
host: args.host ?? (process.env["GH_HOST"]?.trim() || void 0)
|
|
17425
|
+
// write would route — and what the gate must bind.
|
|
17426
|
+
host: resolveGhHost(args.host)
|
|
16738
17427
|
});
|
|
16739
17428
|
}
|
|
16740
17429
|
__name(authorization, "authorization");
|
|
@@ -16858,7 +17547,7 @@ function runSubmit(args, cliVersion = "unknown") {
|
|
|
16858
17547
|
}
|
|
16859
17548
|
let payload;
|
|
16860
17549
|
try {
|
|
16861
|
-
payload = JSON.parse(
|
|
17550
|
+
payload = JSON.parse(readFileSync28(args.review, "utf8"));
|
|
16862
17551
|
} catch (err) {
|
|
16863
17552
|
throw new Error(
|
|
16864
17553
|
`Cannot read review JSON ${args.review}: ${err.message}`
|
|
@@ -16936,8 +17625,17 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
16936
17625
|
"--input",
|
|
16937
17626
|
"-"
|
|
16938
17627
|
);
|
|
17628
|
+
let reviewId;
|
|
17629
|
+
let reviewUrl;
|
|
17630
|
+
try {
|
|
17631
|
+
const parsed = JSON.parse(response);
|
|
17632
|
+
if (typeof parsed.id === "number") reviewId = parsed.id;
|
|
17633
|
+
if (typeof parsed.html_url === "string" && parsed.html_url.trim() !== "") {
|
|
17634
|
+
reviewUrl = parsed.html_url;
|
|
17635
|
+
}
|
|
17636
|
+
} catch {
|
|
17637
|
+
}
|
|
16939
17638
|
try {
|
|
16940
|
-
const reviewId = JSON.parse(response).id;
|
|
16941
17639
|
if (typeof reviewId === "number") {
|
|
16942
17640
|
const receiptPath = tmpFile(`pr-${args.pr}`, "submit-receipt.json");
|
|
16943
17641
|
const priorIds = readReceiptIds(receiptPath);
|
|
@@ -16952,7 +17650,7 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
16952
17650
|
} catch {
|
|
16953
17651
|
}
|
|
16954
17652
|
writeStderrLine(
|
|
16955
|
-
`Posted ${event2} to ${args.repo}#${args.pr} \u2014 ${auth.why}` + (cappedBy.length ? ` (capped by ${cappedBy.join(", ")})` : "") + "."
|
|
17653
|
+
`Posted ${event2} to ${args.repo}#${args.pr} \u2014 ${auth.why}` + (cappedBy.length ? ` (capped by ${cappedBy.join(", ")})` : "") + "." + (reviewUrl ? ` ${reviewUrl}` : "")
|
|
16956
17654
|
);
|
|
16957
17655
|
writeStdoutLine(
|
|
16958
17656
|
JSON.stringify(
|
|
@@ -16960,7 +17658,8 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
16960
17658
|
posted: true,
|
|
16961
17659
|
event: event2,
|
|
16962
17660
|
cappedBy,
|
|
16963
|
-
inlineComments: post.comments.length
|
|
17661
|
+
inlineComments: post.comments.length,
|
|
17662
|
+
...reviewUrl ? { url: reviewUrl } : {}
|
|
16964
17663
|
},
|
|
16965
17664
|
null,
|
|
16966
17665
|
2
|
|
@@ -17009,17 +17708,17 @@ init_esbuild_shims();
|
|
|
17009
17708
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
17010
17709
|
import {
|
|
17011
17710
|
mkdirSync as mkdirSync25,
|
|
17012
|
-
readdirSync as
|
|
17711
|
+
readdirSync as readdirSync7,
|
|
17013
17712
|
writeFileSync as writeFileSync24,
|
|
17014
|
-
readFileSync as
|
|
17713
|
+
readFileSync as readFileSync29,
|
|
17015
17714
|
rmSync as rmSync9,
|
|
17016
17715
|
lstatSync as lstatSync5,
|
|
17017
|
-
existsSync as
|
|
17018
|
-
statSync as
|
|
17716
|
+
existsSync as existsSync13,
|
|
17717
|
+
statSync as statSync14,
|
|
17019
17718
|
symlinkSync
|
|
17020
17719
|
} from "node:fs";
|
|
17021
17720
|
import { createRequire } from "node:module";
|
|
17022
|
-
import { dirname as
|
|
17721
|
+
import { dirname as dirname22, join as join19, isAbsolute as isAbsolute5, sep as sep7 } from "node:path";
|
|
17023
17722
|
var FIXTURE_DIR_RE = /(^|\/)(__fixtures__|__mocks__|__snapshots__|fixtures)\//;
|
|
17024
17723
|
function planTestEfficacy(files, workspaceGlobs) {
|
|
17025
17724
|
const tests = files.filter((f) => f.kind === "test").map((f) => f.path);
|
|
@@ -17543,7 +18242,7 @@ function gitOut2(cwd, ...args) {
|
|
|
17543
18242
|
}
|
|
17544
18243
|
__name(gitOut2, "gitOut");
|
|
17545
18244
|
function findVitestBin(worktree, resolveModule = createRequire(
|
|
17546
|
-
|
|
18245
|
+
join19(worktree, "noop.js")
|
|
17547
18246
|
).resolve) {
|
|
17548
18247
|
let pkgPath;
|
|
17549
18248
|
try {
|
|
@@ -17554,12 +18253,12 @@ function findVitestBin(worktree, resolveModule = createRequire(
|
|
|
17554
18253
|
}
|
|
17555
18254
|
throw error;
|
|
17556
18255
|
}
|
|
17557
|
-
const pkg = JSON.parse(
|
|
18256
|
+
const pkg = JSON.parse(readFileSync29(pkgPath, "utf8"));
|
|
17558
18257
|
const bin = pkg.bin?.vitest;
|
|
17559
18258
|
if (!bin) {
|
|
17560
18259
|
throw new Error(`vitest package at ${pkgPath} declares no "vitest" bin`);
|
|
17561
18260
|
}
|
|
17562
|
-
return
|
|
18261
|
+
return join19(dirname22(pkgPath), bin);
|
|
17563
18262
|
}
|
|
17564
18263
|
__name(findVitestBin, "findVitestBin");
|
|
17565
18264
|
function gitCapture(cwd, ...args) {
|
|
@@ -17585,7 +18284,7 @@ function safeRmWithin(worktree, relPath) {
|
|
|
17585
18284
|
const parts = relPath.split(/[/\\]+/).filter((s) => s && s !== ".");
|
|
17586
18285
|
let cur = worktree;
|
|
17587
18286
|
for (let i = 0; i < parts.length; i++) {
|
|
17588
|
-
cur =
|
|
18287
|
+
cur = join19(cur, parts[i]);
|
|
17589
18288
|
let st;
|
|
17590
18289
|
try {
|
|
17591
18290
|
st = lstatSync5(cur);
|
|
@@ -17610,15 +18309,15 @@ __name(probeCleanupFailureDetail, "probeCleanupFailureDetail");
|
|
|
17610
18309
|
function exposeDependencies(probeTree, dependencyRoot) {
|
|
17611
18310
|
const done = { linked: 0, failed: 0 };
|
|
17612
18311
|
if (probeTree === dependencyRoot) return done;
|
|
17613
|
-
const source =
|
|
17614
|
-
const target =
|
|
17615
|
-
if (!
|
|
18312
|
+
const source = join19(dependencyRoot, "node_modules");
|
|
18313
|
+
const target = join19(probeTree, "node_modules");
|
|
18314
|
+
if (!existsSync13(source) || existsSync13(target)) return done;
|
|
17616
18315
|
mkdirSync25(target);
|
|
17617
18316
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
17618
|
-
for (const entry of
|
|
18317
|
+
for (const entry of readdirSync7(source, { withFileTypes: true })) {
|
|
17619
18318
|
if (entry.name === ".vite" || entry.name === ".vite-temp") continue;
|
|
17620
|
-
const sourceEntry =
|
|
17621
|
-
const targetEntry =
|
|
18319
|
+
const sourceEntry = join19(source, entry.name);
|
|
18320
|
+
const targetEntry = join19(target, entry.name);
|
|
17622
18321
|
let sourceStats;
|
|
17623
18322
|
try {
|
|
17624
18323
|
sourceStats = lstatSync5(sourceEntry);
|
|
@@ -17628,7 +18327,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
17628
18327
|
}
|
|
17629
18328
|
if (sourceStats.isSymbolicLink()) {
|
|
17630
18329
|
try {
|
|
17631
|
-
if (!
|
|
18330
|
+
if (!statSync14(sourceEntry).isDirectory()) continue;
|
|
17632
18331
|
} catch {
|
|
17633
18332
|
continue;
|
|
17634
18333
|
}
|
|
@@ -17639,14 +18338,14 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
17639
18338
|
let pkgs;
|
|
17640
18339
|
try {
|
|
17641
18340
|
mkdirSync25(targetEntry);
|
|
17642
|
-
pkgs =
|
|
18341
|
+
pkgs = readdirSync7(sourceEntry);
|
|
17643
18342
|
} catch {
|
|
17644
18343
|
done.failed++;
|
|
17645
18344
|
continue;
|
|
17646
18345
|
}
|
|
17647
18346
|
for (const pkg of pkgs) {
|
|
17648
18347
|
try {
|
|
17649
|
-
symlinkSync(
|
|
18348
|
+
symlinkSync(join19(sourceEntry, pkg), join19(targetEntry, pkg), linkType);
|
|
17650
18349
|
done.linked++;
|
|
17651
18350
|
} catch {
|
|
17652
18351
|
done.failed++;
|
|
@@ -17792,10 +18491,10 @@ function newSideLength(header) {
|
|
|
17792
18491
|
__name(newSideLength, "newSideLength");
|
|
17793
18492
|
function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
17794
18493
|
const { patch: _patch, ...meta } = hunk;
|
|
17795
|
-
const abs =
|
|
18494
|
+
const abs = join19(probeTree, hunk.file);
|
|
17796
18495
|
let original;
|
|
17797
18496
|
try {
|
|
17798
|
-
original =
|
|
18497
|
+
original = readFileSync29(abs, "utf8");
|
|
17799
18498
|
} catch (e) {
|
|
17800
18499
|
return {
|
|
17801
18500
|
...meta,
|
|
@@ -17821,16 +18520,16 @@ function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
|
17821
18520
|
const detail = verdict === "killed" ? "the suite went red with this hunk reverted \u2014 a test covers this change" : verdict === "survived" ? "every affected test still PASSED with this hunk reverted \u2014 no test in this diff fails when the change is undone" : "the tree with this hunk reverted produced no clean verdict (likely a compile or import error) \u2014 not evidence either way";
|
|
17822
18521
|
return { ...meta, verdict, detail };
|
|
17823
18522
|
} finally {
|
|
17824
|
-
mkdirSync25(
|
|
18523
|
+
mkdirSync25(dirname22(abs), { recursive: true });
|
|
17825
18524
|
writeFileSync24(abs, original, "utf8");
|
|
17826
18525
|
}
|
|
17827
18526
|
}
|
|
17828
18527
|
__name(runOneHunkProbe, "runOneHunkProbe");
|
|
17829
18528
|
function runControlMutant(probeTree, probeFile, deadlineAt, now = Date.now) {
|
|
17830
|
-
const abs =
|
|
18529
|
+
const abs = join19(probeTree, probeFile);
|
|
17831
18530
|
let original;
|
|
17832
18531
|
try {
|
|
17833
|
-
original =
|
|
18532
|
+
original = readFileSync29(abs, "utf8");
|
|
17834
18533
|
} catch {
|
|
17835
18534
|
return null;
|
|
17836
18535
|
}
|
|
@@ -17853,8 +18552,8 @@ __qcIt('QWEN-REVIEW-POSITIVE-CONTROL', () => {
|
|
|
17853
18552
|
}
|
|
17854
18553
|
__name(runControlMutant, "runControlMutant");
|
|
17855
18554
|
function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
17856
|
-
const abs =
|
|
17857
|
-
const original =
|
|
18555
|
+
const abs = join19(probeTree, mutant.file);
|
|
18556
|
+
const original = readFileSync29(abs, "utf8");
|
|
17858
18557
|
const lines = original.split("\n");
|
|
17859
18558
|
if ((lines[mutant.line - 1] ?? "").trim() !== mutant.statement) {
|
|
17860
18559
|
return {
|
|
@@ -17921,9 +18620,9 @@ async function runTestEfficacy(args) {
|
|
|
17921
18620
|
const now = args.now ?? Date.now;
|
|
17922
18621
|
const startedAt = now();
|
|
17923
18622
|
const { report, worktree, base, out } = args;
|
|
17924
|
-
const plan = JSON.parse(
|
|
18623
|
+
const plan = JSON.parse(readFileSync29(report, "utf8"));
|
|
17925
18624
|
const rootPkg = JSON.parse(
|
|
17926
|
-
|
|
18625
|
+
readFileSync29(`${worktree}/package.json`, "utf8")
|
|
17927
18626
|
);
|
|
17928
18627
|
const globs = rootPkg.workspaces ?? [];
|
|
17929
18628
|
const { unreachable, probes, revert } = planTestEfficacy(
|
|
@@ -17931,9 +18630,9 @@ async function runTestEfficacy(args) {
|
|
|
17931
18630
|
globs
|
|
17932
18631
|
);
|
|
17933
18632
|
for (const p of revert) {
|
|
17934
|
-
const norm =
|
|
17935
|
-
const root =
|
|
17936
|
-
if (isAbsolute5(p) || norm !== root && !norm.startsWith(root +
|
|
18633
|
+
const norm = join19(worktree, p);
|
|
18634
|
+
const root = join19(worktree, ".");
|
|
18635
|
+
if (isAbsolute5(p) || norm !== root && !norm.startsWith(root + sep7)) {
|
|
17937
18636
|
throw new Error(
|
|
17938
18637
|
`refusing to run: revert path escapes the worktree: ${JSON.stringify(p)}`
|
|
17939
18638
|
);
|
|
@@ -18204,7 +18903,7 @@ async function runTestEfficacy(args) {
|
|
|
18204
18903
|
} catch (e) {
|
|
18205
18904
|
removeError = e;
|
|
18206
18905
|
}
|
|
18207
|
-
if (
|
|
18906
|
+
if (existsSync13(probeTree)) {
|
|
18208
18907
|
cleanupFailure = probeCleanupFailureDetail(
|
|
18209
18908
|
probeTree,
|
|
18210
18909
|
removeError,
|
|
@@ -18303,7 +19002,7 @@ async function runTestEfficacy(args) {
|
|
|
18303
19002
|
findings,
|
|
18304
19003
|
cleanupFailure
|
|
18305
19004
|
};
|
|
18306
|
-
mkdirSync25(
|
|
19005
|
+
mkdirSync25(dirname22(out), { recursive: true });
|
|
18307
19006
|
writeFileSync24(out, JSON.stringify(result, null, 2), "utf8");
|
|
18308
19007
|
writeStdoutLine(
|
|
18309
19008
|
`Wrote test-efficacy report to ${out} (${unreachable.length} unreachable, ${results.length} probed, ${mutantResults.length} mutant(s), ${hunkResults.length} hunk probe(s), ${findings.length} finding(s))`
|
|
@@ -18381,8 +19080,8 @@ var testEfficacyCommand = {
|
|
|
18381
19080
|
|
|
18382
19081
|
// packages/cli/src/commands/review/test-plan.ts
|
|
18383
19082
|
init_esbuild_shims();
|
|
18384
|
-
import { existsSync as
|
|
18385
|
-
import { dirname as
|
|
19083
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync26, readFileSync as readFileSync30, writeFileSync as writeFileSync25 } from "node:fs";
|
|
19084
|
+
import { dirname as dirname23, join as join20, normalize, resolve as resolve24 } from "node:path";
|
|
18386
19085
|
var PLAN_NAME_RE = /(test\s*plan|\btesting\b|how\s+(?:has\s+this|to)\s+(?:been\s+)?test(?:ed)?|测试计划|测试方案|测试步骤)/i;
|
|
18387
19086
|
var HEADING_LINE_RE = /^(#{1,6})(?:[ \t](.*))?$/;
|
|
18388
19087
|
var BOLD_LINE_RE = /^\*\*([^*\n]+)\*\*:?\s*$/;
|
|
@@ -18585,7 +19284,7 @@ function rulePath(text, worktree, changed) {
|
|
|
18585
19284
|
};
|
|
18586
19285
|
}
|
|
18587
19286
|
const ignored = isGitIgnored(worktree, path3);
|
|
18588
|
-
if (
|
|
19287
|
+
if (existsSync14(join20(worktree, path3))) {
|
|
18589
19288
|
return {
|
|
18590
19289
|
kind: "path",
|
|
18591
19290
|
text,
|
|
@@ -18656,7 +19355,7 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
18656
19355
|
let rootScripts = [];
|
|
18657
19356
|
try {
|
|
18658
19357
|
const rootPkg = JSON.parse(
|
|
18659
|
-
|
|
19358
|
+
readFileSync30(join20(worktree, "package.json"), "utf8")
|
|
18660
19359
|
);
|
|
18661
19360
|
rootScripts = Object.keys(rootPkg.scripts ?? {});
|
|
18662
19361
|
} catch {
|
|
@@ -18670,7 +19369,7 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
18670
19369
|
for (const dir of skipped) {
|
|
18671
19370
|
try {
|
|
18672
19371
|
const pkg = JSON.parse(
|
|
18673
|
-
|
|
19372
|
+
readFileSync30(join20(worktree, dir, "package.json"), "utf8")
|
|
18674
19373
|
);
|
|
18675
19374
|
for (const s of Object.keys(pkg?.scripts ?? {})) defined.add(s);
|
|
18676
19375
|
} catch {
|
|
@@ -18765,7 +19464,7 @@ __name(fetchPrBody, "fetchPrBody");
|
|
|
18765
19464
|
function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
18766
19465
|
let plan;
|
|
18767
19466
|
try {
|
|
18768
|
-
plan = JSON.parse(
|
|
19467
|
+
plan = JSON.parse(readFileSync30(args.plan, "utf8"));
|
|
18769
19468
|
} catch (err) {
|
|
18770
19469
|
throw new Error(
|
|
18771
19470
|
`test-plan: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -18792,7 +19491,7 @@ function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
|
18792
19491
|
note: "the PR description has no Test Plan section"
|
|
18793
19492
|
};
|
|
18794
19493
|
}
|
|
18795
|
-
const worktree =
|
|
19494
|
+
const worktree = resolve24(args.worktree);
|
|
18796
19495
|
const changed = new Set(
|
|
18797
19496
|
(plan.files ?? []).map((f) => normalize(String(f.path)))
|
|
18798
19497
|
);
|
|
@@ -18800,7 +19499,7 @@ function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
|
18800
19499
|
if (args.buildTest) {
|
|
18801
19500
|
try {
|
|
18802
19501
|
buildTest = JSON.parse(
|
|
18803
|
-
|
|
19502
|
+
readFileSync30(args.buildTest, "utf8")
|
|
18804
19503
|
);
|
|
18805
19504
|
} catch {
|
|
18806
19505
|
buildTest = null;
|
|
@@ -18857,8 +19556,8 @@ var testPlanCommand = {
|
|
|
18857
19556
|
try {
|
|
18858
19557
|
const report = runTestPlan(args);
|
|
18859
19558
|
if (args.out) {
|
|
18860
|
-
mkdirSync26(
|
|
18861
|
-
writeFileSync25(
|
|
19559
|
+
mkdirSync26(dirname23(resolve24(args.out)), { recursive: true });
|
|
19560
|
+
writeFileSync25(resolve24(args.out), JSON.stringify(report, null, 2));
|
|
18862
19561
|
}
|
|
18863
19562
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
18864
19563
|
writeStderrLine(`test-plan: ${report.note}`);
|
|
@@ -18872,8 +19571,8 @@ var testPlanCommand = {
|
|
|
18872
19571
|
// packages/cli/src/commands/review/cleanup.ts
|
|
18873
19572
|
init_esbuild_shims();
|
|
18874
19573
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
18875
|
-
import { existsSync as
|
|
18876
|
-
import { join as
|
|
19574
|
+
import { existsSync as existsSync15, readFileSync as readFileSync31, readdirSync as readdirSync8, rmSync as rmSync10 } from "node:fs";
|
|
19575
|
+
import { join as join21 } from "node:path";
|
|
18877
19576
|
var AUTOMATION_MARKER = "<!-- qwen-";
|
|
18878
19577
|
function isAutomationComment(body) {
|
|
18879
19578
|
return (body ?? "").trimStart().startsWith(AUTOMATION_MARKER);
|
|
@@ -18904,7 +19603,7 @@ var OWNER_REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
|
18904
19603
|
function readAuditWindow(target, expectedPrNumber) {
|
|
18905
19604
|
let raw;
|
|
18906
19605
|
try {
|
|
18907
|
-
raw =
|
|
19606
|
+
raw = readFileSync31(tmpFile(target, "fetch.json"), "utf8");
|
|
18908
19607
|
} catch (err) {
|
|
18909
19608
|
const code = err.code;
|
|
18910
19609
|
return code === "ENOENT" ? { skip: "no fetch report" } : {
|
|
@@ -18951,7 +19650,7 @@ function readSubmitReceipt(target) {
|
|
|
18951
19650
|
try {
|
|
18952
19651
|
return new Set(
|
|
18953
19652
|
parseReceiptIds(
|
|
18954
|
-
|
|
19653
|
+
readFileSync31(tmpFile(target, "submit-receipt.json"), "utf8")
|
|
18955
19654
|
)
|
|
18956
19655
|
);
|
|
18957
19656
|
} catch {
|
|
@@ -19078,7 +19777,7 @@ function runCleanup(target) {
|
|
|
19078
19777
|
const prefix = tmpPrefix(target);
|
|
19079
19778
|
let tmpEntries = [];
|
|
19080
19779
|
try {
|
|
19081
|
-
tmpEntries =
|
|
19780
|
+
tmpEntries = existsSync15(REVIEW_TMP_DIR) ? readdirSync8(REVIEW_TMP_DIR) : [];
|
|
19082
19781
|
} catch (err) {
|
|
19083
19782
|
writeStderrLine(
|
|
19084
19783
|
`Failed to read ${REVIEW_TMP_DIR}: ${err.message}`
|
|
@@ -19086,7 +19785,7 @@ function runCleanup(target) {
|
|
|
19086
19785
|
}
|
|
19087
19786
|
for (const file of tmpEntries) {
|
|
19088
19787
|
if (!file.startsWith(prefix)) continue;
|
|
19089
|
-
const full =
|
|
19788
|
+
const full = join21(REVIEW_TMP_DIR, file);
|
|
19090
19789
|
try {
|
|
19091
19790
|
rmSync10(full, { recursive: true, force: true });
|
|
19092
19791
|
writeStdoutLine(`Removed temp file: ${full}`);
|
|
@@ -19119,10 +19818,10 @@ var cleanupCommand = {
|
|
|
19119
19818
|
|
|
19120
19819
|
// packages/cli/src/commands/review/cost-ledger.ts
|
|
19121
19820
|
init_esbuild_shims();
|
|
19122
|
-
import { mkdirSync as mkdirSync27, readFileSync as
|
|
19123
|
-
import { dirname as
|
|
19821
|
+
import { mkdirSync as mkdirSync27, readFileSync as readFileSync32, statSync as statSync15, writeFileSync as writeFileSync26 } from "node:fs";
|
|
19822
|
+
import { dirname as dirname24, join as join22, resolve as resolve25 } from "node:path";
|
|
19124
19823
|
function readUsage(file, floorMs) {
|
|
19125
|
-
const raw =
|
|
19824
|
+
const raw = readFileSync32(file, "utf8");
|
|
19126
19825
|
const events = [];
|
|
19127
19826
|
let launch = "";
|
|
19128
19827
|
for (const line of raw.split("\n")) {
|
|
@@ -19240,8 +19939,8 @@ function planFloorMs(planPath) {
|
|
|
19240
19939
|
let raw;
|
|
19241
19940
|
let floorMs;
|
|
19242
19941
|
try {
|
|
19243
|
-
raw =
|
|
19244
|
-
floorMs =
|
|
19942
|
+
raw = readFileSync32(planPath, "utf8");
|
|
19943
|
+
floorMs = statSync15(planPath).mtimeMs;
|
|
19245
19944
|
} catch (err) {
|
|
19246
19945
|
throw new Error(
|
|
19247
19946
|
`could not read the plan report ${planPath}: ${err.message}`
|
|
@@ -19263,7 +19962,7 @@ __name(planFloorMs, "planFloorMs");
|
|
|
19263
19962
|
function computeLedger(planPath, env = process.env) {
|
|
19264
19963
|
const floorMs = planFloorMs(planPath);
|
|
19265
19964
|
const { projectDir, sessionId, dir } = transcriptPaths(env);
|
|
19266
|
-
const chatFile =
|
|
19965
|
+
const chatFile = join22(projectDir, "chats", `${sessionId}.jsonl`);
|
|
19267
19966
|
let mainEvents;
|
|
19268
19967
|
try {
|
|
19269
19968
|
mainEvents = readUsage(chatFile, floorMs).events;
|
|
@@ -19288,10 +19987,10 @@ function computeLedger(planPath, env = process.env) {
|
|
|
19288
19987
|
const agents = [];
|
|
19289
19988
|
const agentEvents = [];
|
|
19290
19989
|
for (const f of files) {
|
|
19291
|
-
const full =
|
|
19990
|
+
const full = join22(dir, f);
|
|
19292
19991
|
let mtimeMs;
|
|
19293
19992
|
try {
|
|
19294
|
-
mtimeMs =
|
|
19993
|
+
mtimeMs = statSync15(full).mtimeMs;
|
|
19295
19994
|
} catch {
|
|
19296
19995
|
continue;
|
|
19297
19996
|
}
|
|
@@ -19399,7 +20098,7 @@ function runCostLedger(args) {
|
|
|
19399
20098
|
}
|
|
19400
20099
|
if (args.out !== void 0 && args.out.length > 0) {
|
|
19401
20100
|
try {
|
|
19402
|
-
mkdirSync27(
|
|
20101
|
+
mkdirSync27(dirname24(resolve25(args.out)), { recursive: true });
|
|
19403
20102
|
writeFileSync26(args.out, JSON.stringify(ledger, null, 2));
|
|
19404
20103
|
} catch (err) {
|
|
19405
20104
|
writeStderrLineSafe(
|
|
@@ -19433,8 +20132,8 @@ var costLedgerCommand = {
|
|
|
19433
20132
|
// packages/cli/src/commands/review/run.ts
|
|
19434
20133
|
init_esbuild_shims();
|
|
19435
20134
|
import { spawn, execFileSync as execFileSync6 } from "node:child_process";
|
|
19436
|
-
import { readdirSync as
|
|
19437
|
-
import { dirname as
|
|
20135
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync33, realpathSync as realpathSync6, statSync as statSync16 } from "node:fs";
|
|
20136
|
+
import { dirname as dirname25, join as join23, resolve as resolve26 } from "node:path";
|
|
19438
20137
|
var COMPOSED_PATTERN = /^qwen-review-.*composed\.json$/;
|
|
19439
20138
|
var COMPOSED_POLL_MS = 250;
|
|
19440
20139
|
var SIGNAL_EXIT_CODES = {
|
|
@@ -19462,16 +20161,16 @@ function newestArtifactSince(dir, pattern, startMs) {
|
|
|
19462
20161
|
let best = null;
|
|
19463
20162
|
let names;
|
|
19464
20163
|
try {
|
|
19465
|
-
names =
|
|
20164
|
+
names = readdirSync9(dir);
|
|
19466
20165
|
} catch {
|
|
19467
20166
|
return null;
|
|
19468
20167
|
}
|
|
19469
20168
|
for (const name of names) {
|
|
19470
20169
|
if (!pattern.test(name)) continue;
|
|
19471
|
-
const path3 =
|
|
20170
|
+
const path3 = join23(dir, name);
|
|
19472
20171
|
let mtime;
|
|
19473
20172
|
try {
|
|
19474
|
-
mtime =
|
|
20173
|
+
mtime = statSync16(path3).mtimeMs;
|
|
19475
20174
|
} catch {
|
|
19476
20175
|
continue;
|
|
19477
20176
|
}
|
|
@@ -19489,7 +20188,7 @@ function exitCodeFor(completed, event2, failOn) {
|
|
|
19489
20188
|
__name(exitCodeFor, "exitCodeFor");
|
|
19490
20189
|
function readComposed(path3) {
|
|
19491
20190
|
try {
|
|
19492
|
-
const parsed = JSON.parse(
|
|
20191
|
+
const parsed = JSON.parse(readFileSync33(path3, "utf8"));
|
|
19493
20192
|
return typeof parsed.event === "string" ? parsed : null;
|
|
19494
20193
|
} catch {
|
|
19495
20194
|
return null;
|
|
@@ -19520,7 +20219,7 @@ function childEnv() {
|
|
|
19520
20219
|
return env;
|
|
19521
20220
|
}
|
|
19522
20221
|
try {
|
|
19523
|
-
if (
|
|
20222
|
+
if (dirname25(realpathSync6(inherited)) === dirname25(realpathSync6(ownEntry))) {
|
|
19524
20223
|
return env;
|
|
19525
20224
|
}
|
|
19526
20225
|
} catch {
|
|
@@ -19642,8 +20341,8 @@ async function runReview(args) {
|
|
|
19642
20341
|
downgraded: composed?.downgraded ?? false,
|
|
19643
20342
|
downgradedFrom: composed?.downgradedFrom ?? null,
|
|
19644
20343
|
remediation: composed?.remediation ?? [],
|
|
19645
|
-
composedPath: composedPath ?
|
|
19646
|
-
reportPath: reportPath ?
|
|
20344
|
+
composedPath: composedPath ? resolve26(composedPath) : null,
|
|
20345
|
+
reportPath: reportPath ? resolve26(reportPath) : null,
|
|
19647
20346
|
childExitCode,
|
|
19648
20347
|
childSignal,
|
|
19649
20348
|
timedOut,
|
|
@@ -19657,7 +20356,7 @@ async function runReview(args) {
|
|
|
19657
20356
|
writeStdoutLine(result.verdictLine ?? `Event: ${result.event}`);
|
|
19658
20357
|
if (result.reportPath) writeStdoutLine(`Report: ${result.reportPath}`);
|
|
19659
20358
|
} else {
|
|
19660
|
-
const detail = composedPath !== null ? `a composed verdict was found at ${
|
|
20359
|
+
const detail = composedPath !== null ? `a composed verdict was found at ${resolve26(composedPath)} but could not be parsed` : "no composed verdict was produced";
|
|
19661
20360
|
writeStdoutLine(
|
|
19662
20361
|
timedOut ? "Review did not complete: timed out." : `Review did not complete: ${detail}${childExitCode !== null ? ` (CLI exit ${childExitCode})` : ""}${childSignal !== null ? ` (killed by ${childSignal})` : ""}.`
|
|
19663
20362
|
);
|
|
@@ -19723,33 +20422,33 @@ var runCommand = {
|
|
|
19723
20422
|
// packages/cli/src/commands/review/save-artifact.ts
|
|
19724
20423
|
init_esbuild_shims();
|
|
19725
20424
|
import {
|
|
19726
|
-
existsSync as
|
|
20425
|
+
existsSync as existsSync16,
|
|
19727
20426
|
lstatSync as lstatSync6,
|
|
19728
20427
|
mkdirSync as mkdirSync28,
|
|
19729
|
-
readFileSync as
|
|
19730
|
-
statSync as
|
|
20428
|
+
readFileSync as readFileSync34,
|
|
20429
|
+
statSync as statSync17
|
|
19731
20430
|
} from "node:fs";
|
|
19732
20431
|
import {
|
|
19733
|
-
dirname as
|
|
20432
|
+
dirname as dirname26,
|
|
19734
20433
|
isAbsolute as isAbsolute6,
|
|
19735
|
-
join as
|
|
19736
|
-
relative as
|
|
19737
|
-
resolve as
|
|
19738
|
-
sep as
|
|
20434
|
+
join as join24,
|
|
20435
|
+
relative as relative6,
|
|
20436
|
+
resolve as resolve27,
|
|
20437
|
+
sep as sep8,
|
|
19739
20438
|
toNamespacedPath
|
|
19740
20439
|
} from "node:path";
|
|
19741
20440
|
import { isDeepStrictEqual } from "node:util";
|
|
19742
20441
|
function workspaceRoot(explicit) {
|
|
19743
|
-
return
|
|
20442
|
+
return resolve27(explicit ?? process.cwd());
|
|
19744
20443
|
}
|
|
19745
20444
|
__name(workspaceRoot, "workspaceRoot");
|
|
19746
20445
|
function isWithin(parent, child) {
|
|
19747
|
-
const rel =
|
|
19748
|
-
return rel === "" || !isAbsolute6(rel) && rel !== ".." && !rel.startsWith(`..${
|
|
20446
|
+
const rel = relative6(parent, child);
|
|
20447
|
+
return rel === "" || !isAbsolute6(rel) && rel !== ".." && !rel.startsWith(`..${sep8}`);
|
|
19749
20448
|
}
|
|
19750
20449
|
__name(isWithin, "isWithin");
|
|
19751
20450
|
function workspacePath(root, value, label2) {
|
|
19752
|
-
const absolute =
|
|
20451
|
+
const absolute = resolve27(root, value);
|
|
19753
20452
|
if (!isWithin(root, absolute)) {
|
|
19754
20453
|
throw new Error(
|
|
19755
20454
|
`${label2} must be inside the workspace: ${JSON.stringify(value)}.`
|
|
@@ -19759,11 +20458,11 @@ function workspacePath(root, value, label2) {
|
|
|
19759
20458
|
}
|
|
19760
20459
|
__name(workspacePath, "workspacePath");
|
|
19761
20460
|
function rejectSymlinkPath(root, path3, label2) {
|
|
19762
|
-
const rel =
|
|
20461
|
+
const rel = relative6(root, path3);
|
|
19763
20462
|
let current = root;
|
|
19764
|
-
for (const segment of rel.split(
|
|
19765
|
-
current =
|
|
19766
|
-
if (
|
|
20463
|
+
for (const segment of rel.split(sep8)) {
|
|
20464
|
+
current = join24(current, segment);
|
|
20465
|
+
if (existsSync16(current) && lstatSync6(current).isSymbolicLink()) {
|
|
19767
20466
|
throw new Error(`${label2} must not traverse a symbolic link.`);
|
|
19768
20467
|
}
|
|
19769
20468
|
}
|
|
@@ -19771,15 +20470,15 @@ function rejectSymlinkPath(root, path3, label2) {
|
|
|
19771
20470
|
__name(rejectSymlinkPath, "rejectSymlinkPath");
|
|
19772
20471
|
function sameFile2(left, right) {
|
|
19773
20472
|
if (left === right) return true;
|
|
19774
|
-
if (!
|
|
19775
|
-
const leftStat =
|
|
19776
|
-
const rightStat =
|
|
20473
|
+
if (!existsSync16(left) || !existsSync16(right)) return false;
|
|
20474
|
+
const leftStat = statSync17(left);
|
|
20475
|
+
const rightStat = statSync17(right);
|
|
19777
20476
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
19778
20477
|
}
|
|
19779
20478
|
__name(sameFile2, "sameFile");
|
|
19780
20479
|
function readText(path3, label2) {
|
|
19781
20480
|
try {
|
|
19782
|
-
return
|
|
20481
|
+
return readFileSync34(path3, "utf8");
|
|
19783
20482
|
} catch (error) {
|
|
19784
20483
|
throw new Error(
|
|
19785
20484
|
`Could not read the ${label2} file at ${JSON.stringify(path3)}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -19905,7 +20604,7 @@ function saveReviewArtifact(args) {
|
|
|
19905
20604
|
const composedPath = workspacePath(root, args.composed, "Composed input");
|
|
19906
20605
|
const reportPath = workspacePath(root, args.report, "Markdown report");
|
|
19907
20606
|
const outputPath = workspacePath(root, args.out, "Output");
|
|
19908
|
-
const reviewsRoot =
|
|
20607
|
+
const reviewsRoot = resolve27(root, REVIEWS_DIR);
|
|
19909
20608
|
if (!isWithin(reviewsRoot, reportPath) || reportPath === reviewsRoot) {
|
|
19910
20609
|
throw new Error(
|
|
19911
20610
|
`Markdown report must be a file under ${JSON.stringify(REVIEWS_DIR)}: ${JSON.stringify(args.report)}.`
|
|
@@ -19946,7 +20645,7 @@ function saveReviewArtifact(args) {
|
|
|
19946
20645
|
const verdict = validateVerdict(readJson2(composedPath, "composed verdict"));
|
|
19947
20646
|
let reportIsFile;
|
|
19948
20647
|
try {
|
|
19949
|
-
reportIsFile =
|
|
20648
|
+
reportIsFile = statSync17(reportPath).isFile();
|
|
19950
20649
|
} catch {
|
|
19951
20650
|
}
|
|
19952
20651
|
if (reportIsFile === false) {
|
|
@@ -19955,7 +20654,7 @@ function saveReviewArtifact(args) {
|
|
|
19955
20654
|
);
|
|
19956
20655
|
}
|
|
19957
20656
|
readText(reportPath, "Markdown report");
|
|
19958
|
-
const markdownReportPath =
|
|
20657
|
+
const markdownReportPath = relative6(root, reportPath).split(sep8).join("/");
|
|
19959
20658
|
const document = {
|
|
19960
20659
|
schemaVersion: 1,
|
|
19961
20660
|
target: args.target,
|
|
@@ -19966,7 +20665,7 @@ function saveReviewArtifact(args) {
|
|
|
19966
20665
|
outcomesRecorded: findings.outcomesRecorded,
|
|
19967
20666
|
markdownReportPath
|
|
19968
20667
|
};
|
|
19969
|
-
mkdirSync28(
|
|
20668
|
+
mkdirSync28(dirname26(outputPath), { recursive: true });
|
|
19970
20669
|
atomicWriteFileSync(
|
|
19971
20670
|
toNamespacedPath(outputPath),
|
|
19972
20671
|
`${JSON.stringify(document, null, 2)}
|
|
@@ -19975,7 +20674,7 @@ function saveReviewArtifact(args) {
|
|
|
19975
20674
|
);
|
|
19976
20675
|
return {
|
|
19977
20676
|
path: outputPath,
|
|
19978
|
-
workspacePath:
|
|
20677
|
+
workspacePath: relative6(root, outputPath).split(sep8).join("/")
|
|
19979
20678
|
};
|
|
19980
20679
|
}
|
|
19981
20680
|
__name(saveReviewArtifact, "saveReviewArtifact");
|
|
@@ -20022,9 +20721,9 @@ var saveArtifactCommand = {
|
|
|
20022
20721
|
var reviewCommand = {
|
|
20023
20722
|
command: "review",
|
|
20024
20723
|
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)",
|
|
20025
|
-
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(repoContextCommand).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(
|
|
20724
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(matchRemoteCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(repoContextCommand).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(
|
|
20026
20725
|
1,
|
|
20027
|
-
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, repo-context, 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."
|
|
20726
|
+
"Specify a subcommand: run, parse-args, match-remote, fetch-pr, capture-local, plan-diff, repo-context, 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."
|
|
20028
20727
|
).version(false), "builder"),
|
|
20029
20728
|
handler: /* @__PURE__ */ __name(() => {
|
|
20030
20729
|
}, "handler")
|
|
@@ -20224,10 +20923,10 @@ var updateCommand3 = {
|
|
|
20224
20923
|
stdioHelpers,
|
|
20225
20924
|
{ updateEventEmitter }
|
|
20226
20925
|
] = await Promise.all([
|
|
20227
|
-
import("./settings-
|
|
20228
|
-
import("./updateCheck-
|
|
20229
|
-
import("./installationInfo-
|
|
20230
|
-
import("./standalone-update-
|
|
20926
|
+
import("./settings-BRAOSJIM.js"),
|
|
20927
|
+
import("./updateCheck-EZMBTEIR.js"),
|
|
20928
|
+
import("./installationInfo-BWFHT7WU.js"),
|
|
20929
|
+
import("./standalone-update-DJN2R3YW.js"),
|
|
20231
20930
|
import("./stdioHelpers-7A2EE64Z.js"),
|
|
20232
20931
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
20233
20932
|
]);
|
|
@@ -20316,11 +21015,6 @@ var updateCommand3 = {
|
|
|
20316
21015
|
};
|
|
20317
21016
|
|
|
20318
21017
|
// packages/cli/src/config/config.ts
|
|
20319
|
-
var SESSION_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}(-agent-[a-zA-Z0-9_.-]+)?$/i;
|
|
20320
|
-
function isValidSessionId(value) {
|
|
20321
|
-
return SESSION_ID_REGEX.test(value);
|
|
20322
|
-
}
|
|
20323
|
-
__name(isValidSessionId, "isValidSessionId");
|
|
20324
21018
|
var debugLogger4 = createDebugLogger("CONFIG");
|
|
20325
21019
|
function resolveLocaleForExtensions(settings) {
|
|
20326
21020
|
const envLang = process.env["QWEN_CODE_LANG"];
|
|
@@ -20658,8 +21352,8 @@ async function parseArguments() {
|
|
|
20658
21352
|
default: false
|
|
20659
21353
|
}).option("channel", {
|
|
20660
21354
|
type: "string",
|
|
20661
|
-
choices: ["VSCode", "ACP", "SDK", "CI", "desktop"],
|
|
20662
|
-
description: "Channel identifier (VSCode, ACP, SDK, CI, desktop)"
|
|
21355
|
+
choices: ["VSCode", "ACP", "SDK", "CI", "desktop", "daemon"],
|
|
21356
|
+
description: "Channel identifier (VSCode, ACP, SDK, CI, desktop, daemon)"
|
|
20663
21357
|
}).option("allowed-mcp-server-names", {
|
|
20664
21358
|
type: "array",
|
|
20665
21359
|
string: true,
|
|
@@ -20907,7 +21601,7 @@ async function parseArguments() {
|
|
|
20907
21601
|
}
|
|
20908
21602
|
}
|
|
20909
21603
|
if ((result["acp"] || result["experimentalAcp"]) && !result["channel"]) {
|
|
20910
|
-
result["channel"] =
|
|
21604
|
+
result["channel"] = resolveAcpChannelFallback();
|
|
20911
21605
|
}
|
|
20912
21606
|
return result;
|
|
20913
21607
|
}
|
|
@@ -21394,7 +22088,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
21394
22088
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
21395
22089
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
21396
22090
|
terminalImageRenderSupportProvider: interactive ? async () => {
|
|
21397
|
-
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-
|
|
22091
|
+
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-PJM7663W.js");
|
|
21398
22092
|
return getTerminalImageRenderSupport();
|
|
21399
22093
|
} : void 0,
|
|
21400
22094
|
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|
|
@@ -21806,7 +22500,6 @@ export {
|
|
|
21806
22500
|
staleArgsWarning,
|
|
21807
22501
|
skillArgsNote,
|
|
21808
22502
|
RunBudgetEnforcer,
|
|
21809
|
-
isValidSessionId,
|
|
21810
22503
|
parseArguments,
|
|
21811
22504
|
loadHierarchicalGeminiMemory,
|
|
21812
22505
|
isDebugMode,
|