@qwen-code/qwen-code 0.21.7 → 0.21.8
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 +43 -30
- 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.md +4 -1
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
- package/bundled/review/SKILL.md +28 -5
- package/chunks/{MaxSizedBox-ANWZBPTS.js → MaxSizedBox-7PM6BGJ5.js} +26 -22
- package/chunks/{StandaloneSessionPicker-XKS3VU3A.js → StandaloneSessionPicker-3UQHM7GV.js} +44 -40
- package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
- package/chunks/{acpAgent-KUAZ3GCZ.js → acpAgent-5UWLFV6V.js} +534 -262
- package/chunks/{agent-T6PTGX5R.js → agent-624T2BLO.js} +26 -22
- package/chunks/{agent-headless-PR7YCB7S.js → agent-headless-2EE5J2KX.js} +26 -22
- 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-JENKGFFP.js} +29 -25
- package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
- package/chunks/{channel-management-service-FSQ7SHYI.js → channel-management-service-DDWUPHMU.js} +19 -10
- package/chunks/{channel-settings-store-35VQVUVV.js → channel-settings-store-SA6JZSPH.js} +34 -30
- package/chunks/{channel-worker-group-JWQK224X.js → channel-worker-group-E67EN3RV.js} +5 -5
- package/chunks/{channel-worker-manager-77E3OXRQ.js → channel-worker-manager-SW4C45CF.js} +5 -5
- package/chunks/{channel-worker-supervisor-62YWUGP2.js → channel-worker-supervisor-5SRD24FG.js} +3 -3
- package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
- package/chunks/{chunk-ZJ3VGYHK.js → chunk-2ILAOM2I.js} +34 -17
- package/chunks/{chunk-6XJMFJ4D.js → chunk-2M4K4KYS.js} +177 -120
- package/chunks/{chunk-CNIID3TV.js → chunk-2UUMVNYT.js} +1 -1
- package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
- package/chunks/{chunk-2U3WZGZG.js → chunk-3PY4LPJF.js} +19 -131
- package/chunks/{chunk-SPMY6CX6.js → chunk-3SE7J4DR.js} +3 -3
- package/chunks/{chunk-6UWFTUQL.js → chunk-3WNQOYHQ.js} +66 -22
- package/chunks/{chunk-KXSDEOFU.js → chunk-4ALIARFY.js} +1 -1
- package/chunks/{chunk-D3UEZIQH.js → chunk-4DU3NCHG.js} +48 -55
- package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
- package/chunks/{chunk-H2UQ2M5Z.js → chunk-4WU6NY7F.js} +96 -22
- package/chunks/{chunk-TLV2IMHR.js → chunk-5ZGR6RKJ.js} +3 -3
- package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
- package/chunks/{chunk-EORNAQDT.js → chunk-6TR7CFXH.js} +1 -1
- package/chunks/{chunk-NG2R4N5O.js → chunk-6ZRFAKXK.js} +1 -1
- package/chunks/{chunk-P2AJ7FTI.js → chunk-757GB46F.js} +1 -1
- package/chunks/{chunk-72LNFGUY.js → chunk-77QVBFCU.js} +3 -3
- package/chunks/{chunk-OH2VKQXH.js → chunk-7DVT4LVV.js} +37 -30
- package/chunks/{chunk-KKJJB5X6.js → chunk-7VUERJHS.js} +1503 -815
- package/chunks/{chunk-VOARQPTA.js → chunk-B52AWKBB.js} +65 -21
- package/chunks/{chunk-Y4EWSQF7.js → chunk-BF224XHL.js} +2 -2
- package/chunks/{chunk-PJOBIWUG.js → chunk-BF52U4XJ.js} +1 -1
- package/chunks/{chunk-55LYDVPU.js → chunk-C5VWPTGT.js} +1 -1
- package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
- package/chunks/chunk-COBO5EBO.js +135 -0
- package/chunks/chunk-CPG6P4GG.js +82 -0
- package/chunks/{chunk-DIEFUBV6.js → chunk-DIWZNWZT.js} +205 -35
- package/chunks/{chunk-AE77C5ZU.js → chunk-DQSDACD2.js} +1 -1
- package/chunks/{chunk-P3LEG54R.js → chunk-DX5W5AON.js} +2 -2
- package/chunks/{chunk-EUQTXRKZ.js → chunk-E4ZBKMSF.js} +5 -5
- package/chunks/{chunk-FPM27XN4.js → chunk-EIVICVHM.js} +4 -4
- package/chunks/{chunk-YHEEE624.js → chunk-EN2TKTFH.js} +1 -1
- package/chunks/chunk-F6WFNA7U.js +22 -0
- package/chunks/{chunk-FZBZSYKU.js → chunk-FN6YXJOP.js} +1 -1
- package/chunks/{chunk-KR4ZSC7K.js → chunk-FWBXMANW.js} +3 -3
- package/chunks/{chunk-LA7YLSR6.js → chunk-FYAXKJK7.js} +327 -67
- package/chunks/{chunk-CSZEXZBE.js → chunk-GBDINRIL.js} +3 -3
- package/chunks/{chunk-SCI7K3GM.js → chunk-GOEVOFQI.js} +19 -10
- package/chunks/{chunk-LEMXGVEP.js → chunk-GQCEQPYQ.js} +3 -3
- package/chunks/{chunk-Y7E5LNLO.js → chunk-GXSNGY5M.js} +1027 -876
- package/chunks/{chunk-6XU3PH66.js → chunk-HA3SAB64.js} +22 -69
- package/chunks/{chunk-Y4NGLFGJ.js → chunk-HUWENAHO.js} +1 -1
- package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
- package/chunks/{chunk-CB2464BK.js → chunk-HWX5HPUG.js} +14 -4
- package/chunks/{chunk-LZC3B5N2.js → chunk-IA7TGCN2.js} +2 -2
- package/chunks/{chunk-RERATVSK.js → chunk-IBYULW65.js} +6 -6
- package/chunks/{chunk-HYRDKNUY.js → chunk-IUQ52YJK.js} +1 -1
- package/chunks/{chunk-TDXGKHDN.js → chunk-IYES5WOT.js} +2 -2
- package/chunks/{chunk-RGSBTHSU.js → chunk-KAQCJO6Y.js} +131 -4
- package/chunks/{chunk-VWOVHOTT.js → chunk-KJZ26VBX.js} +1 -1
- package/chunks/{chunk-6GONZVLS.js → chunk-KKDVZLGL.js} +1 -1
- package/chunks/{chunk-MKVZE4ZJ.js → chunk-KTJFU7RT.js} +3 -2
- package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
- package/chunks/{chunk-6EOI4HOK.js → chunk-M3STHEMM.js} +12 -17
- package/chunks/chunk-NGYI5EF5.js +244 -0
- package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
- package/chunks/{chunk-HQB2KUAN.js → chunk-NPUXXRJI.js} +1 -1
- package/chunks/{chunk-QETYKPMG.js → chunk-NVRDQFCX.js} +1 -1
- package/chunks/{chunk-PQBHU2IA.js → chunk-OHKJVAKG.js} +10 -10
- package/chunks/{chunk-CYR3HI5X.js → chunk-OQTXYMKW.js} +2 -2
- package/chunks/{chunk-DBOFL3LQ.js → chunk-PG62DFWD.js} +10 -10
- package/chunks/{chunk-2VSTGY6M.js → chunk-PJRW65JO.js} +1 -1
- package/chunks/{chunk-33ACCIIY.js → chunk-PLFATELK.js} +1 -1
- package/chunks/{chunk-IC4Z6LX6.js → chunk-PYQADEFD.js} +5 -0
- package/chunks/{chunk-MAJS7AT4.js → chunk-QGHSP65Z.js} +2 -2
- package/chunks/{chunk-OHJLEW5J.js → chunk-QQWD7LZV.js} +4 -4
- package/chunks/{chunk-ZXU5UHMI.js → chunk-QXVSWG66.js} +2 -2
- package/chunks/{chunk-E33LOKRA.js → chunk-RPWVIXDB.js} +18 -1
- package/chunks/{chunk-TYKC75AX.js → chunk-S3Y3GBFD.js} +1 -1
- package/chunks/{chunk-7UFKAV7Y.js → chunk-S6HYI3MF.js} +2 -2
- package/chunks/chunk-SAH4BD2J.js +92 -0
- package/chunks/{chunk-OMKQH5C5.js → chunk-SNRT2TJJ.js} +6 -23
- package/chunks/chunk-SR7RZ4MS.js +202 -0
- package/chunks/{chunk-CXE7E23H.js → chunk-TE3ZAJE7.js} +45 -17
- package/chunks/{chunk-S7CV4KO6.js → chunk-TKSZJ5BV.js} +3 -3
- package/chunks/{chunk-3NB7TSE2.js → chunk-U5SLIG7E.js} +1 -1
- package/chunks/chunk-UA5H3DS2.js +203 -0
- package/chunks/{chunk-24ER7UV4.js → chunk-UFALT4LK.js} +1 -1
- package/chunks/{chunk-YJQCUTT2.js → chunk-VWMUDKLC.js} +3 -3
- package/chunks/{chunk-RMH5OWLD.js → chunk-VXZ5HAOV.js} +1 -1
- package/chunks/{chunk-BVWVWGLE.js → chunk-WAUGQKUU.js} +4 -64
- package/chunks/{chunk-SHZYHGQH.js → chunk-WG6542MA.js} +1 -1
- package/chunks/{chunk-5KH532V7.js → chunk-WV5J6Q6N.js} +1 -1
- package/chunks/{chunk-RNVQB725.js → chunk-XHD7CRP2.js} +2 -2
- package/chunks/{chunk-W4B7UBUS.js → chunk-XZKQT2B2.js} +5 -5
- package/chunks/{chunk-6HVUFDS2.js → chunk-Y4TETC74.js} +22 -13
- package/chunks/{chunk-RZHU3ILK.js → chunk-YEF7XEO2.js} +4 -4
- package/chunks/{chunk-RUL4S3K3.js → chunk-YHJFF7KH.js} +146 -45
- package/chunks/{chunk-23RZCH76.js → chunk-YOM7DEGB.js} +3 -3
- package/chunks/{chunk-OFI7IGST.js → chunk-ZCLLJARV.js} +9 -9
- package/chunks/{chunk-GSS34377.js → chunk-ZHA242R4.js} +2 -2
- package/chunks/{chunk-TRLYP7OF.js → chunk-ZPLALRXZ.js} +17 -9
- package/chunks/{chunk-WUC6ZFXO.js → chunk-ZWBUH5UP.js} +1 -1
- package/chunks/{computer-use-KEAPATUY.js → computer-use-ESQYJ3JY.js} +26 -22
- package/chunks/{config-utils-K7SCOWHD.js → config-utils-XQHBJP7G.js} +4 -4
- package/chunks/{contextCommand-ZJA6A5K5.js → contextCommand-CX3YF4ZE.js} +28 -24
- package/chunks/{core-runtime-QMJPWHCI.js → core-runtime-DIAU7JMG.js} +30 -26
- package/chunks/{create-sub-session-DJE6XICH.js → create-sub-session-HDPD6HOA.js} +26 -22
- package/chunks/{create-sub-session-E4PBYXV5.js → create-sub-session-QIDZUOPU.js} +1 -1
- 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-VZBGJUNL.js} +30 -0
- package/chunks/{daemon-status-provider-FSWDPE2G.js → daemon-status-provider-H6O4UQ4F.js} +33 -29
- package/chunks/{daemon-trust-policy-P5L5VFAY.js → daemon-trust-policy-BNUXG6MT.js} +33 -29
- package/chunks/{daemon-trust-policy-monitor-73JYN6ET.js → daemon-trust-policy-monitor-E4EQ7GF4.js} +33 -29
- package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
- package/chunks/{deferred-core-runtime-BWRCCFTE.js → deferred-core-runtime-CBMSHPAU.js} +26 -22
- package/chunks/{display-image-O2XFPQTC.js → display-image-NQRSIBXM.js} +2 -2
- package/chunks/{dist-DPPHJAVL.js → dist-EEEQGCZA.js} +918 -142
- package/chunks/{dist-K4WWQBHS.js → dist-HIACTZEK.js} +55 -15
- package/chunks/{dist-3BMEUGTG.js → dist-IRL7WA5Z.js} +1 -1
- package/chunks/{dist-HVBMEYWK.js → dist-KVISB2O2.js} +1 -1
- package/chunks/{dist-KS4O2NKE.js → dist-MBF3I5MX.js} +14 -8
- package/chunks/{dist-SFQ34F4M.js → dist-MKX5OSFF.js} +5 -4
- package/chunks/{dist-7JGAAQSC.js → dist-RCH3I7SS.js} +2 -2
- package/chunks/{dist-C5U4LJKW.js → dist-TUSWNE2I.js} +5 -4
- package/chunks/{earlyInputCapture-L5ST23A6.js → earlyInputCapture-UIOP7OIN.js} +26 -22
- package/chunks/{edit-LHHRFNFK.js → edit-ITMZYFKA.js} +26 -22
- package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
- package/chunks/{enter-worktree-6NXCRZPF.js → enter-worktree-S4PL5UV6.js} +26 -22
- package/chunks/{enterPlanMode-ZVQT4U7D.js → enterPlanMode-YV52NNJT.js} +26 -22
- package/chunks/{environment-GJ2HWJOS.js → environment-NGOWPRZV.js} +30 -26
- package/chunks/{errors-6RLH3XXC.js → errors-BU26DTDX.js} +28 -24
- package/chunks/{exit-worktree-I2YLUHHY.js → exit-worktree-XRM6LH5F.js} +26 -22
- package/chunks/{exitPlanMode-7CCWKO7I.js → exitPlanMode-ZLI5F7KR.js} +26 -22
- package/chunks/{fast-path-DVFD4HQD.js → fast-path-UJWORIED.js} +23 -3
- package/chunks/{fast-path-settings-WQJU2LAT.js → fast-path-settings-37WQD5B2.js} +6 -3
- package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
- package/chunks/{gemini-7FWGOYD4.js → gemini-ZSKNDUMU.js} +77 -65
- package/chunks/{geminiContentGenerator-V2WVLIXU.js → geminiContentGenerator-YGEXOEKD.js} +1 -1
- package/chunks/{glob-3N6GGI75.js → glob-7KZG44BR.js} +26 -22
- package/chunks/{goal-tools-APOW6UXL.js → goal-tools-PXWN5VK3.js} +4 -2
- package/chunks/{grep-V43ILZVX.js → grep-6ZFC7RJ5.js} +26 -22
- package/chunks/{handleAutoUpdate-A5WFVWIA.js → handleAutoUpdate-KSEL3TQS.js} +30 -26
- package/chunks/{i18n-PLVQ4FBZ.js → i18n-ZIUXBW5V.js} +27 -23
- package/chunks/{image-gen-7C6IK6DC.js → image-gen-AUIZJJNK.js} +7 -5
- package/chunks/{initializer-CVAIKZYL.js → initializer-7AHY3N6Q.js} +33 -29
- package/chunks/{installationInfo-J6QDHNTK.js → installationInfo-VGBXMYLY.js} +27 -23
- package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
- package/chunks/{list-ZZ4OUUWV.js → list-PSFKQHLB.js} +36 -32
- package/chunks/{list-agents-KFFIIS2G.js → list-agents-Z4WABFDZ.js} +1 -1
- package/chunks/{loadedSettingsAdapter-QRYRJSWL.js → loadedSettingsAdapter-FTMRCTOF.js} +33 -29
- package/chunks/{loggingContentGenerator-OJCO75HM.js → loggingContentGenerator-MZAN52UV.js} +7 -5
- 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/{managed-npm-update-PCOSCP2N.js → managed-npm-update-O4NHK45X.js} +27 -23
- package/chunks/{mcp-M3WKKWKY.js → mcp-6CFP2AYQ.js} +33 -29
- package/chunks/{monitor-GN24FH6C.js → monitor-DAKD6OU4.js} +26 -22
- package/chunks/{nonInteractiveCli-KPTU3VSQ.js → nonInteractiveCli-RC7VIUZL.js} +66 -60
- package/chunks/{notebook-edit-4YM65BBO.js → notebook-edit-474DPMRL.js} +34 -22
- package/chunks/{openaiContentGenerator-EDQT6GTV.js → openaiContentGenerator-2NFY2MWO.js} +19 -9
- package/chunks/{pidfile-JOIIRN2C.js → pidfile-KBFVDNQP.js} +26 -22
- package/chunks/{process-registry-2CHQBXH5.js → process-registry-PMJOA5CO.js} +15 -0
- package/chunks/{processUtils-5SV4MX3Q.js → processUtils-6GRYH4Y3.js} +2 -2
- package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
- package/chunks/{qwenContentGenerator-ODRJSUGR.js → qwenContentGenerator-KAHU6IZY.js} +33 -28
- package/chunks/{qwenOAuth2-NESCMZ47.js → qwenOAuth2-RRQTCP4W.js} +7 -5
- package/chunks/{read-file-HPSODLPK.js → read-file-3M6WXDXP.js} +6 -4
- 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-D6TAY3HX.js} +30 -26
- package/chunks/{ripGrep-ZKQGTQAO.js → ripGrep-PLPENT3E.js} +26 -22
- package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
- package/chunks/{run-qwen-serve-ZPKPKECF.js → run-qwen-serve-ZAFIJKJC.js} +168 -54
- package/chunks/{runtime-2FLNNM36.js → runtime-ZED7CYOZ.js} +38 -34
- package/chunks/{scheduler-365PJHNR.js → scheduler-MD3AL2W5.js} +26 -22
- package/chunks/{send-message-ZM7MRUGP.js → send-message-CAMSLG2L.js} +4 -3
- package/chunks/{serve-QD2RNLKJ.js → serve-E3VUDRZN.js} +33 -29
- package/chunks/{server-XLJVLTYM.js → server-OWMEMAKR.js} +450 -231
- package/chunks/{session-3VTUHH4Q.js → session-HZ57QK7K.js} +158 -97
- package/chunks/{settings-KULVPCQC.js → settings-V7BR3RKP.js} +32 -28
- package/chunks/{shell-3SWW22MH.js → shell-23OMNMW6.js} +26 -22
- package/chunks/{skill-KDHWYS7W.js → skill-6HBDYZRS.js} +7 -5
- package/chunks/{skill-settings-NMY4JEJC.js → skill-settings-HWJLTU7M.js} +32 -28
- package/chunks/{spawnChannel-ZKS4Q5OU.js → spawnChannel-N6KKUW5B.js} +27 -23
- package/chunks/{standalone-update-7CXPGAQ4.js → standalone-update-QGIKHATD.js} +28 -24
- package/chunks/{startInteractiveUI-2QQLEKM6.js → startInteractiveUI-GX2CRL42.js} +365 -155
- 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-CFFKU7KL.js} +26 -22
- package/chunks/{team-delete-MHY3UZGY.js → team-delete-MMQB4OSC.js} +1 -1
- package/chunks/{team-plan-approval-LZTYLEG4.js → team-plan-approval-6EFOKR6A.js} +26 -22
- package/chunks/{terminal-image-renderer-R5HHAFJN.js → terminal-image-renderer-TLDNACQY.js} +28 -24
- package/chunks/{theme-manager-PAUCSJFF.js → theme-manager-5LJ3H7VO.js} +26 -22
- package/chunks/{todoWrite-UPVOHYGD.js → todoWrite-JGV6VLOX.js} +1 -1
- package/chunks/{tool-search-2BFCGLI6.js → tool-search-UJV3A24H.js} +9 -6
- package/chunks/{total-session-admission-MK4SINFK.js → total-session-admission-D63QYXGO.js} +29 -25
- package/chunks/{trustedFolders-TJ5S26N7.js → trustedFolders-KZCOB53W.js} +30 -24
- package/chunks/{update-relaunch-N7AYLARF.js → update-relaunch-IFILM3SA.js} +5 -5
- package/chunks/{updateCheck-QRZ3DVT5.js → updateCheck-YZ2CRCFC.js} +29 -25
- package/chunks/{useAutoAcceptIndicator-DBJ7Y5AF.js → useAutoAcceptIndicator-AXEVNA3Q.js} +35 -31
- package/chunks/{validateNonInterActiveAuth-6ZQWUDS3.js → validateNonInterActiveAuth-3WTOJFWA.js} +61 -57
- package/chunks/{version-AJQGQWXC.js → version-GXK7OHZY.js} +1 -1
- package/chunks/{web-fetch-QWJYRXFL.js → web-fetch-ILB4GAVR.js} +12 -8
- package/chunks/{web-search-2AOXJGHU.js → web-search-HKRPGPZZ.js} +8 -6
- package/chunks/{workflow-ERH3SJG2.js → workflow-FXIPRQQA.js} +750 -147
- package/chunks/{workspace-providers-status-HZ474RA4.js → workspace-providers-status-NYHC7HSR.js} +35 -31
- package/chunks/{workspace-registration-store-6EUP4JXG.js → workspace-registration-store-AKEB7OMW.js} +1 -1
- package/chunks/{workspace-registry-R4APRRNC.js → workspace-registry-CDAS5TVZ.js} +29 -25
- package/chunks/{workspace-service-HFIFDMU7.js → workspace-service-PAMUKMAV.js} +36 -32
- package/chunks/{workspace-skills-status-HAHEIHGK.js → workspace-skills-status-YQSHCCMS.js} +33 -29
- package/chunks/{workspace-trust-reconciler-65GTAGDK.js → workspace-trust-reconciler-RPTXOIY2.js} +36 -32
- package/chunks/{write-file-B34CDELV.js → write-file-CGS57TS4.js} +26 -22
- 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-E7D72GYV.js} +6 -4
- 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-DybZaz32.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-CChqgwIb.js → architectureDiagram-3BPJPVTR-jN3qBd19.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BHN-Tfss.js → blockDiagram-GPEHLZMM-Ct5DZPrj.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BhyjzDjN.js → c4Diagram-AAUBKEIU-CUAFMlUG.js} +1 -1
- package/web-shell/assets/channel-BMwLrwLW.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BB9eyHrx.js → chunk-2J33WTMH-CuV8n90B.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BeV7ce_J.js → chunk-4BX2VUAB-BUzl_kls.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DO7kXDiV.js → chunk-55IACEB6-BnDBLX6A.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B27MPznD.js → chunk-727SXJPM-B83uTOjm.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DHIjqjD_.js → chunk-AQP2D5EJ-DM3HLgpT.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DabMqyN2.js → chunk-FMBD7UC4-CSQ5hgyb.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-Dw7Nnnxc.js → chunk-ND2GUHAM-BWOF4SxX.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-DdaZew1Q.js → chunk-QZHKN3VN-BsOH9LMi.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-CgBpCYH5.js → cose-bilkent-S5V4N54A-IENqH2iJ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-BB4IU8G0.js → dagre-BM42HDAG--dyzDTGo.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BcUTHU37.js → diagram-2AECGRRQ-BE7Dcqof.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-B6Lyihyv.js → diagram-5GNKFQAL-Cr8-5OTj.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CRIJOjpG.js → diagram-KO2AKTUF-Bzey3uAY.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DdNiwWWT.js → diagram-LMA3HP47-sErl28Xb.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Dz4b32Do.js → diagram-OG6HWLK6-Dq30ATIo.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-D-8NGw77.js → erDiagram-TEJ5UH35-BkCoEfVW.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-Dun26LyM.js → flowDiagram-I6XJVG4X-DHwO0rrI.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-F10Hu1Gc.js → ganttDiagram-6RSMTGT7-s7vAPxWq.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bf8Ez6-D.js → gitGraphDiagram-PVQCEYII-CQxhwPOU.js} +1 -1
- package/web-shell/assets/index-Bckpjr-I.css +5 -0
- package/web-shell/assets/{index-BXqw-nGq.js → index-CF4wApWp.js} +1 -1
- package/web-shell/assets/index-DwEr9HEW.js +1768 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DVgTMLvj.js → infoDiagram-5YYISTIA-BnFrD0bq.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-uT-KepvK.js → ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Vg_XadQf.js → journeyDiagram-JHISSGLW-CyGAhsxi.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-Dyv1ESBE.js → kanban-definition-UN3LZRKU-CbsK5akB.js} +1 -1
- package/web-shell/assets/{linear-BMIepYX3.js → linear-cQsF4P8D.js} +1 -1
- package/web-shell/assets/{mermaid.core-zA8pJ9ag.js → mermaid.core-Z4HVqrKY.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BCW_BZ_5.js → mindmap-definition-RKZ34NQL-CYnrBo_f.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DseNEGp2.js → pieDiagram-4H26LBE5-CBzOfhrs.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-6Z7wr1Fi.js → quadrantDiagram-W4KKPZXB-D4LK1Ebn.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CVOlCRPf.js → requirementDiagram-4Y6WPE33-Bzti2Lcj.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CGhgrUJZ.js → sankeyDiagram-5OEKKPKP-yTBw5Z2s.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-dlqmpLuQ.js → sequenceDiagram-3UESZ5HK-D07UVRiZ.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-B9EW10Xb.js → stateDiagram-AJRCARHV-UE_lHsTn.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-BBRh0mgZ.js → timeline-definition-PNZ67QCA-DRvYdiTs.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-B8Gs-REP.js → vennDiagram-CIIHVFJN-CQLIXs0u.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-D_y80Ur7.js → wardley-L42UT6IY-JZz_Xqse.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-D-CNfHJ-.js → wardleyDiagram-YWT4CUSO--i7BiJwB.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-DQ5CvELo.js → xychartDiagram-2RQKCTM6-Bkc-bW0S.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/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
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
serveCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HWX5HPUG.js";
|
|
6
6
|
import {
|
|
7
7
|
listCommand
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EIVICVHM.js";
|
|
9
9
|
import {
|
|
10
10
|
getErrorMessage as getErrorMessage2
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IYES5WOT.js";
|
|
12
12
|
import {
|
|
13
|
+
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
13
14
|
ObservedChannelContactStore
|
|
14
15
|
} from "./chunk-OWMAZHIX.js";
|
|
15
16
|
import {
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
collectProviderModelsForProtocol,
|
|
29
30
|
getAuthTypeFromEnv,
|
|
30
31
|
resolveCliGenerationConfig
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-GBDINRIL.js";
|
|
32
33
|
import {
|
|
33
34
|
resolvePath
|
|
34
35
|
} from "./chunk-AOHJKPKL.js";
|
|
@@ -51,17 +52,17 @@ import {
|
|
|
51
52
|
registerToolCallDispatch,
|
|
52
53
|
selectFirstModel,
|
|
53
54
|
sessionsPath
|
|
54
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-E4ZBKMSF.js";
|
|
55
56
|
import {
|
|
56
57
|
getExtensionManager,
|
|
57
58
|
requestChoicePluginNonInteractive,
|
|
58
59
|
requestConsentNonInteractive,
|
|
59
60
|
requestConsentOrFail,
|
|
60
61
|
resolveExtensionCommandScope
|
|
61
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-QQWD7LZV.js";
|
|
62
63
|
import {
|
|
63
64
|
parseChannelConfig
|
|
64
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-QXVSWG66.js";
|
|
65
66
|
import {
|
|
66
67
|
findCliEntryPath
|
|
67
68
|
} from "./chunk-V6WHFGST.js";
|
|
@@ -92,7 +93,7 @@ import {
|
|
|
92
93
|
import {
|
|
93
94
|
normalizeWorkerDiagnostic,
|
|
94
95
|
sanitizeWorkerDiagnostic
|
|
95
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-UFALT4LK.js";
|
|
96
97
|
import {
|
|
97
98
|
normalizeServeChannelSelection
|
|
98
99
|
} from "./chunk-ALMR3E6Q.js";
|
|
@@ -115,7 +116,7 @@ import {
|
|
|
115
116
|
clearAccount,
|
|
116
117
|
loadAccount,
|
|
117
118
|
saveAccount
|
|
118
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-ZWBUH5UP.js";
|
|
119
120
|
import {
|
|
120
121
|
AcpBridge,
|
|
121
122
|
ChannelLoopScheduler,
|
|
@@ -126,37 +127,41 @@ import {
|
|
|
126
127
|
isChannelProactiveDeliveryError,
|
|
127
128
|
sanitizeLogText,
|
|
128
129
|
sanitizePromptText
|
|
129
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-DIWZNWZT.js";
|
|
130
131
|
import {
|
|
131
132
|
assembleMcpServers,
|
|
132
133
|
getPendingGatedMcpServers,
|
|
133
134
|
mcpCommand
|
|
134
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-Y4TETC74.js";
|
|
135
136
|
import {
|
|
136
137
|
loadSettings
|
|
137
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-OHKJVAKG.js";
|
|
138
139
|
import {
|
|
139
140
|
detectSystemLanguage,
|
|
140
141
|
getCurrentLanguage,
|
|
141
142
|
initializeI18n,
|
|
142
143
|
resolveLanguageSetting,
|
|
143
144
|
t
|
|
144
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-PG62DFWD.js";
|
|
145
146
|
import {
|
|
146
147
|
loadEnvironment
|
|
147
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-B52AWKBB.js";
|
|
149
|
+
import {
|
|
150
|
+
resolveAcpChannelFallback,
|
|
151
|
+
scrubAndReportInheritedLoaderEnv
|
|
152
|
+
} from "./chunk-UA5H3DS2.js";
|
|
148
153
|
import {
|
|
149
154
|
getCliVersion
|
|
150
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-FN6YXJOP.js";
|
|
151
156
|
import {
|
|
152
157
|
getPackageJson
|
|
153
158
|
} from "./chunk-VJNBRRZG.js";
|
|
154
159
|
import {
|
|
155
160
|
isWorkspaceTrusted
|
|
156
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-HA3SAB64.js";
|
|
157
162
|
import {
|
|
158
163
|
require_strip_json_comments
|
|
159
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-NPQ5ZKRP.js";
|
|
160
165
|
import {
|
|
161
166
|
hideBin,
|
|
162
167
|
yargs_default
|
|
@@ -195,7 +200,7 @@ import {
|
|
|
195
200
|
unquoteCStylePath,
|
|
196
201
|
updateChannelMemoryEntry,
|
|
197
202
|
updateSetting
|
|
198
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-GXSNGY5M.js";
|
|
199
204
|
import {
|
|
200
205
|
nextFireTime,
|
|
201
206
|
parseCron
|
|
@@ -211,14 +216,14 @@ import {
|
|
|
211
216
|
getAllGeminiMdFilenames,
|
|
212
217
|
parseLineTolerant,
|
|
213
218
|
setGeminiMdFilename
|
|
214
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-3PY4LPJF.js";
|
|
215
220
|
import {
|
|
216
221
|
SchemaValidator,
|
|
217
222
|
ToolNames
|
|
218
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-PYQADEFD.js";
|
|
219
224
|
import {
|
|
220
225
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
221
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-F6WFNA7U.js";
|
|
222
227
|
import {
|
|
223
228
|
isTlsVerificationDisabled
|
|
224
229
|
} from "./chunk-KKBPOU75.js";
|
|
@@ -364,9 +369,9 @@ var require_command_exists = __commonJS({
|
|
|
364
369
|
cleanInput = /* @__PURE__ */ __name(function(s) {
|
|
365
370
|
var isPathName = /[\\]/.test(s);
|
|
366
371
|
if (isPathName) {
|
|
367
|
-
var
|
|
368
|
-
var
|
|
369
|
-
return
|
|
372
|
+
var dirname27 = '"' + path3.dirname(s) + '"';
|
|
373
|
+
var basename7 = '"' + path3.basename(s) + '"';
|
|
374
|
+
return dirname27 + ":" + basename7;
|
|
370
375
|
}
|
|
371
376
|
return '"' + s + '"';
|
|
372
377
|
}, "cleanInput");
|
|
@@ -374,10 +379,10 @@ var require_command_exists = __commonJS({
|
|
|
374
379
|
module.exports = /* @__PURE__ */ __name(function commandExists2(commandName, callback) {
|
|
375
380
|
var cleanedCommandName = cleanInput(commandName);
|
|
376
381
|
if (!callback && typeof Promise !== "undefined") {
|
|
377
|
-
return new Promise(function(
|
|
382
|
+
return new Promise(function(resolve29, reject) {
|
|
378
383
|
commandExists2(commandName, function(error, output) {
|
|
379
384
|
if (output) {
|
|
380
|
-
|
|
385
|
+
resolve29(commandName);
|
|
381
386
|
} else {
|
|
382
387
|
reject(error);
|
|
383
388
|
}
|
|
@@ -2324,8 +2329,8 @@ function createBridgeReadinessGate() {
|
|
|
2324
2329
|
current: /* @__PURE__ */ __name(() => pending, "current"),
|
|
2325
2330
|
block: /* @__PURE__ */ __name(() => {
|
|
2326
2331
|
if (pending) return;
|
|
2327
|
-
pending = new Promise((
|
|
2328
|
-
releasePending =
|
|
2332
|
+
pending = new Promise((resolve29) => {
|
|
2333
|
+
releasePending = resolve29;
|
|
2329
2334
|
});
|
|
2330
2335
|
}, "block"),
|
|
2331
2336
|
release: /* @__PURE__ */ __name(() => {
|
|
@@ -2407,7 +2412,7 @@ function createBridgeRecovery(options) {
|
|
|
2407
2412
|
writeStderrLine(
|
|
2408
2413
|
`[Channel] Bridge crashed (${recentCrashCount}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2409
2414
|
);
|
|
2410
|
-
await new Promise((
|
|
2415
|
+
await new Promise((resolve29) => setTimeout(resolve29, RESTART_DELAY_MS));
|
|
2411
2416
|
const bridge = new AcpBridge(bridgeOpts);
|
|
2412
2417
|
setBridge(bridge);
|
|
2413
2418
|
attachDisconnectHandler(bridge);
|
|
@@ -2725,7 +2730,7 @@ var stopCommand = {
|
|
|
2725
2730
|
if (argv["daemon-url"]) {
|
|
2726
2731
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2727
2732
|
try {
|
|
2728
|
-
const sdk = await import("./daemon-
|
|
2733
|
+
const sdk = await import("./daemon-VZBGJUNL.js");
|
|
2729
2734
|
const client = new sdk.DaemonClient({
|
|
2730
2735
|
baseUrl: argv["daemon-url"],
|
|
2731
2736
|
...token ? { token } : {}
|
|
@@ -2911,7 +2916,7 @@ var statusCommand = {
|
|
|
2911
2916
|
if (argv["daemon-url"]) {
|
|
2912
2917
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2913
2918
|
try {
|
|
2914
|
-
const sdk = await import("./daemon-
|
|
2919
|
+
const sdk = await import("./daemon-VZBGJUNL.js");
|
|
2915
2920
|
const client = new sdk.DaemonClient({
|
|
2916
2921
|
baseUrl: argv["daemon-url"],
|
|
2917
2922
|
...token ? { token } : {}
|
|
@@ -3022,7 +3027,7 @@ var reloadCommand = {
|
|
|
3022
3027
|
const token = resolveToken(argv.token);
|
|
3023
3028
|
let sdk;
|
|
3024
3029
|
try {
|
|
3025
|
-
sdk = await import("./daemon-
|
|
3030
|
+
sdk = await import("./daemon-VZBGJUNL.js");
|
|
3026
3031
|
} catch (err) {
|
|
3027
3032
|
writeStderrLine(
|
|
3028
3033
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(err)}`
|
|
@@ -3102,7 +3107,7 @@ var setCommand2 = {
|
|
|
3102
3107
|
const selection = names[0] === "all" ? { mode: "all" } : { mode: "names", names };
|
|
3103
3108
|
let sdk;
|
|
3104
3109
|
try {
|
|
3105
|
-
sdk = await import("./daemon-
|
|
3110
|
+
sdk = await import("./daemon-VZBGJUNL.js");
|
|
3106
3111
|
} catch (error) {
|
|
3107
3112
|
writeStderrLine(
|
|
3108
3113
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(error)}`
|
|
@@ -3228,7 +3233,7 @@ function createDaemonChannelBridgeFacade(bridge, opts) {
|
|
|
3228
3233
|
}
|
|
3229
3234
|
__name(createDaemonChannelBridgeFacade, "createDaemonChannelBridgeFacade");
|
|
3230
3235
|
async function loadDaemonSdk() {
|
|
3231
|
-
return await import("./daemon-
|
|
3236
|
+
return await import("./daemon-VZBGJUNL.js");
|
|
3232
3237
|
}
|
|
3233
3238
|
__name(loadDaemonSdk, "loadDaemonSdk");
|
|
3234
3239
|
function selectedChannelNames(channelsConfig, selection) {
|
|
@@ -3275,12 +3280,12 @@ async function abortableStartup(value, signal) {
|
|
|
3275
3280
|
const promise = Promise.resolve(value);
|
|
3276
3281
|
if (!signal) return await promise;
|
|
3277
3282
|
if (signal.aborted) throw startupAbortError();
|
|
3278
|
-
return await new Promise((
|
|
3283
|
+
return await new Promise((resolve29, reject) => {
|
|
3279
3284
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3280
3285
|
reject(startupAbortError());
|
|
3281
3286
|
}, "onAbort");
|
|
3282
3287
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3283
|
-
promise.then(
|
|
3288
|
+
promise.then(resolve29, reject).finally(() => {
|
|
3284
3289
|
signal.removeEventListener("abort", onAbort);
|
|
3285
3290
|
});
|
|
3286
3291
|
});
|
|
@@ -3472,7 +3477,10 @@ async function runChannelDaemonWorker(opts) {
|
|
|
3472
3477
|
observedContacts: {
|
|
3473
3478
|
observe: /* @__PURE__ */ __name((channelName, observation) => {
|
|
3474
3479
|
observedContacts.observe(channelName, observation);
|
|
3475
|
-
}, "observe")
|
|
3480
|
+
}, "observe"),
|
|
3481
|
+
list: /* @__PURE__ */ __name(() => observedContacts.list({
|
|
3482
|
+
freshWithinSeconds: OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS
|
|
3483
|
+
}), "list")
|
|
3476
3484
|
},
|
|
3477
3485
|
...loopController ? { loopController } : {}
|
|
3478
3486
|
}),
|
|
@@ -3689,7 +3697,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3689
3697
|
if (!send) {
|
|
3690
3698
|
return Promise.reject(new Error("Channel worker IPC is unavailable."));
|
|
3691
3699
|
}
|
|
3692
|
-
return new Promise((
|
|
3700
|
+
return new Promise((resolve29, reject) => {
|
|
3693
3701
|
let settled = false;
|
|
3694
3702
|
let unsubscribeMessage = /* @__PURE__ */ __name(() => {
|
|
3695
3703
|
}, "unsubscribeMessage");
|
|
@@ -3703,7 +3711,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3703
3711
|
settled = true;
|
|
3704
3712
|
cleanup();
|
|
3705
3713
|
if (error) reject(error);
|
|
3706
|
-
else
|
|
3714
|
+
else resolve29();
|
|
3707
3715
|
}, "finish");
|
|
3708
3716
|
const onMessage = /* @__PURE__ */ __name((value) => {
|
|
3709
3717
|
if (isChannelStartupReportAckMessage(value)) {
|
|
@@ -3785,6 +3793,11 @@ var daemonWorkerCommand = {
|
|
|
3785
3793
|
try {
|
|
3786
3794
|
assertInternalDaemonWorkerInvocation();
|
|
3787
3795
|
const { daemonToken, daemonUrl, workspace } = readDaemonWorkerEnv();
|
|
3796
|
+
scrubAndReportInheritedLoaderEnv(
|
|
3797
|
+
process.env,
|
|
3798
|
+
"qwen channel daemon-worker",
|
|
3799
|
+
"channel daemon worker"
|
|
3800
|
+
);
|
|
3788
3801
|
const send = process.send;
|
|
3789
3802
|
channelLoopMcpHost = new ChannelLoopMcpWorkerHost(
|
|
3790
3803
|
(message, callback) => send.call(process, message, callback ?? (() => {
|
|
@@ -3951,8 +3964,8 @@ var daemonWorkerCommand = {
|
|
|
3951
3964
|
let shuttingDown = false;
|
|
3952
3965
|
let exitCode = 0;
|
|
3953
3966
|
let finish;
|
|
3954
|
-
const finished = new Promise((
|
|
3955
|
-
finish =
|
|
3967
|
+
const finished = new Promise((resolve29) => {
|
|
3968
|
+
finish = resolve29;
|
|
3956
3969
|
});
|
|
3957
3970
|
const shutdown = /* @__PURE__ */ __name(async (reason) => {
|
|
3958
3971
|
if (shuttingDown) {
|
|
@@ -3980,8 +3993,8 @@ var daemonWorkerCommand = {
|
|
|
3980
3993
|
...activeChannelDeliveries.values(),
|
|
3981
3994
|
...activeWebhookTasks.values()
|
|
3982
3995
|
]),
|
|
3983
|
-
new Promise((
|
|
3984
|
-
const timer = setTimeout(
|
|
3996
|
+
new Promise((resolve29) => {
|
|
3997
|
+
const timer = setTimeout(resolve29, WORKER_SHUTDOWN_DRAIN_MS);
|
|
3985
3998
|
timer.unref();
|
|
3986
3999
|
})
|
|
3987
4000
|
]);
|
|
@@ -4085,9 +4098,8 @@ var pairingListCommand = {
|
|
|
4085
4098
|
`);
|
|
4086
4099
|
for (const req of pending) {
|
|
4087
4100
|
const ago = Math.round((Date.now() - req.createdAt) / 6e4);
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
);
|
|
4101
|
+
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})`;
|
|
4102
|
+
writeStdoutLine(` Code: ${req.code} ${subject} ${ago}m ago`);
|
|
4091
4103
|
}
|
|
4092
4104
|
}, "handler")
|
|
4093
4105
|
};
|
|
@@ -4113,8 +4125,9 @@ var pairingApproveCommand = {
|
|
|
4113
4125
|
process.exit(1);
|
|
4114
4126
|
return;
|
|
4115
4127
|
}
|
|
4128
|
+
const approved = request.subject.type === "group" ? `group ${request.subject.name} (${request.subject.id})` : `${request.subject.name} (${request.subject.id})`;
|
|
4116
4129
|
writeStdoutLine(
|
|
4117
|
-
`Approved: ${
|
|
4130
|
+
`Approved: ${approved} can now use channel "${argv.name}".`
|
|
4118
4131
|
);
|
|
4119
4132
|
}, "handler")
|
|
4120
4133
|
};
|
|
@@ -4265,7 +4278,7 @@ var configureWeixinCommand = {
|
|
|
4265
4278
|
// packages/cli/src/commands/channel.ts
|
|
4266
4279
|
var pairingCommand = {
|
|
4267
4280
|
command: "pairing",
|
|
4268
|
-
describe: "Manage DM pairing requests",
|
|
4281
|
+
describe: "Manage DM and group pairing requests",
|
|
4269
4282
|
builder: /* @__PURE__ */ __name((yargs) => yargs.command(pairingListCommand).command(pairingApproveCommand).demandCommand(1, "You need at least one command before continuing.").version(false), "builder"),
|
|
4270
4283
|
handler: /* @__PURE__ */ __name(() => {
|
|
4271
4284
|
}, "handler")
|
|
@@ -4336,8 +4349,211 @@ init_esbuild_shims();
|
|
|
4336
4349
|
|
|
4337
4350
|
// packages/cli/src/commands/review/parse-args.ts
|
|
4338
4351
|
init_esbuild_shims();
|
|
4339
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
4340
|
-
import { dirname } from "node:path";
|
|
4352
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4353
|
+
import { dirname as dirname2 } from "node:path";
|
|
4354
|
+
|
|
4355
|
+
// packages/cli/src/commands/review/lib/stale-bundle.ts
|
|
4356
|
+
init_esbuild_shims();
|
|
4357
|
+
import { createHash } from "node:crypto";
|
|
4358
|
+
import {
|
|
4359
|
+
existsSync as existsSync3,
|
|
4360
|
+
readFileSync as readFileSync3,
|
|
4361
|
+
readdirSync as readdirSync2,
|
|
4362
|
+
realpathSync,
|
|
4363
|
+
statSync
|
|
4364
|
+
} from "node:fs";
|
|
4365
|
+
import {
|
|
4366
|
+
basename as basename3,
|
|
4367
|
+
dirname,
|
|
4368
|
+
extname,
|
|
4369
|
+
join as join5,
|
|
4370
|
+
relative as relative2,
|
|
4371
|
+
resolve as resolve3,
|
|
4372
|
+
sep
|
|
4373
|
+
} from "node:path";
|
|
4374
|
+
var DIGEST_FILE = "review-sources.sha256";
|
|
4375
|
+
var NOT_BUNDLED_RE = /\.(?:test|spec)\.(?:d\.)?[cm]?[jt]sx?$/;
|
|
4376
|
+
var NOT_BUNDLED_DIR = /* @__PURE__ */ new Set(["__fixtures__", "__snapshots__"]);
|
|
4377
|
+
var NOT_BUNDLED_FILE = /* @__PURE__ */ new Set(["test-utils.ts"]);
|
|
4378
|
+
var NOT_BUNDLED_SKILL_FILE = /* @__PURE__ */ new Set(["DESIGN.md"]);
|
|
4379
|
+
var DIGESTED_EXTENSIONS = {
|
|
4380
|
+
code: /* @__PURE__ */ new Set([
|
|
4381
|
+
".ts",
|
|
4382
|
+
".tsx",
|
|
4383
|
+
".mts",
|
|
4384
|
+
".cts",
|
|
4385
|
+
".js",
|
|
4386
|
+
".mjs",
|
|
4387
|
+
".json",
|
|
4388
|
+
".jsx"
|
|
4389
|
+
]),
|
|
4390
|
+
skill: /* @__PURE__ */ new Set([".md"])
|
|
4391
|
+
};
|
|
4392
|
+
function isDigestedFile(kind, name) {
|
|
4393
|
+
if (!DIGESTED_EXTENSIONS[kind].has(extname(name))) return false;
|
|
4394
|
+
if (kind !== "code") return !NOT_BUNDLED_SKILL_FILE.has(name);
|
|
4395
|
+
return !NOT_BUNDLED_RE.test(name) && !NOT_BUNDLED_FILE.has(name);
|
|
4396
|
+
}
|
|
4397
|
+
__name(isDigestedFile, "isDigestedFile");
|
|
4398
|
+
function measureReviewSources(repoRoot, roots) {
|
|
4399
|
+
const state = { incomplete: false, absentRoots: 0 };
|
|
4400
|
+
const files = [];
|
|
4401
|
+
for (const root of roots) files.push(...sourceFilesUnder(root, state, false));
|
|
4402
|
+
const partial = state.absentRoots > 0 && state.absentRoots < roots.length;
|
|
4403
|
+
if (state.incomplete || files.length === 0) {
|
|
4404
|
+
return { digest: void 0, incomplete: state.incomplete, partial };
|
|
4405
|
+
}
|
|
4406
|
+
const hash = createHash("sha256");
|
|
4407
|
+
for (const file of files.sort()) {
|
|
4408
|
+
let content;
|
|
4409
|
+
try {
|
|
4410
|
+
content = readFileSync3(file);
|
|
4411
|
+
} catch {
|
|
4412
|
+
return { digest: void 0, incomplete: true, partial };
|
|
4413
|
+
}
|
|
4414
|
+
hash.update(relative2(repoRoot, file).split(sep).join("/"));
|
|
4415
|
+
hash.update("\0");
|
|
4416
|
+
hash.update(content);
|
|
4417
|
+
hash.update("\0");
|
|
4418
|
+
}
|
|
4419
|
+
return { digest: hash.digest("hex"), incomplete: false, partial };
|
|
4420
|
+
}
|
|
4421
|
+
__name(measureReviewSources, "measureReviewSources");
|
|
4422
|
+
function bundleStaleness(stampedDigest, currentDigest) {
|
|
4423
|
+
if (!stampedDigest) {
|
|
4424
|
+
return { stale: false, unmeasured: "the bundle carries no source digest" };
|
|
4425
|
+
}
|
|
4426
|
+
if (!currentDigest) {
|
|
4427
|
+
return {
|
|
4428
|
+
stale: false,
|
|
4429
|
+
unmeasured: "no review sources were found to compare"
|
|
4430
|
+
};
|
|
4431
|
+
}
|
|
4432
|
+
return { stale: stampedDigest !== currentDigest };
|
|
4433
|
+
}
|
|
4434
|
+
__name(bundleStaleness, "bundleStaleness");
|
|
4435
|
+
function* sourceFilesUnder(root, state, listed) {
|
|
4436
|
+
const { kind } = root;
|
|
4437
|
+
let entries;
|
|
4438
|
+
try {
|
|
4439
|
+
entries = readdirSync2(root.path, { withFileTypes: true });
|
|
4440
|
+
} catch {
|
|
4441
|
+
let stats;
|
|
4442
|
+
try {
|
|
4443
|
+
stats = statSync(root.path);
|
|
4444
|
+
} catch (err) {
|
|
4445
|
+
if (listed || err.code !== "ENOENT")
|
|
4446
|
+
state.incomplete = true;
|
|
4447
|
+
else state.absentRoots += 1;
|
|
4448
|
+
return;
|
|
4449
|
+
}
|
|
4450
|
+
if (stats.isDirectory()) {
|
|
4451
|
+
state.incomplete = true;
|
|
4452
|
+
return;
|
|
4453
|
+
}
|
|
4454
|
+
if (stats.isFile() && isDigestedFile(kind, basename3(root.path)))
|
|
4455
|
+
yield root.path;
|
|
4456
|
+
return;
|
|
4457
|
+
}
|
|
4458
|
+
for (const e of entries) {
|
|
4459
|
+
const full = join5(root.path, e.name);
|
|
4460
|
+
if (e.isDirectory()) {
|
|
4461
|
+
if (kind !== "code" || !NOT_BUNDLED_DIR.has(e.name))
|
|
4462
|
+
yield* sourceFilesUnder({ path: full, kind }, state, true);
|
|
4463
|
+
} else if (e.isFile() && isDigestedFile(kind, e.name)) {
|
|
4464
|
+
yield full;
|
|
4465
|
+
}
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
__name(sourceFilesUnder, "sourceFilesUnder");
|
|
4469
|
+
function reviewSourceRoots(repoRoot) {
|
|
4470
|
+
const cli = join5(repoRoot, "packages", "cli", "src", "commands");
|
|
4471
|
+
return [
|
|
4472
|
+
{ path: join5(cli, "review"), kind: "code" },
|
|
4473
|
+
// The parent file, which is where every subcommand is registered — a new
|
|
4474
|
+
// command, or a changed dispatch, lives here and nowhere under `review/`.
|
|
4475
|
+
// A root may be a single file for exactly this reason.
|
|
4476
|
+
{ path: join5(cli, "review.ts"), kind: "code" },
|
|
4477
|
+
// The worktree lease is review-only code that lives outside `review/`:
|
|
4478
|
+
// `fetch-pr` and `cleanup` import it from `services/`, so an edit to it
|
|
4479
|
+
// with a skipped rebuild is the same silent failure this check exists
|
|
4480
|
+
// for. The two shared files the closure also reaches (`stdioHelpers.ts`,
|
|
4481
|
+
// `skill-args-file.ts`) stay out for the reason SCOPE gives.
|
|
4482
|
+
{
|
|
4483
|
+
path: join5(
|
|
4484
|
+
repoRoot,
|
|
4485
|
+
"packages",
|
|
4486
|
+
"cli",
|
|
4487
|
+
"src",
|
|
4488
|
+
"services",
|
|
4489
|
+
"review-worktree-lease.ts"
|
|
4490
|
+
),
|
|
4491
|
+
kind: "code"
|
|
4492
|
+
},
|
|
4493
|
+
{
|
|
4494
|
+
path: join5(
|
|
4495
|
+
repoRoot,
|
|
4496
|
+
"packages",
|
|
4497
|
+
"core",
|
|
4498
|
+
"src",
|
|
4499
|
+
"skills",
|
|
4500
|
+
"bundled",
|
|
4501
|
+
"review"
|
|
4502
|
+
),
|
|
4503
|
+
kind: "skill"
|
|
4504
|
+
}
|
|
4505
|
+
];
|
|
4506
|
+
}
|
|
4507
|
+
__name(reviewSourceRoots, "reviewSourceRoots");
|
|
4508
|
+
function bundleStalenessNotices(entryPath, brief) {
|
|
4509
|
+
try {
|
|
4510
|
+
if (!entryPath) return void 0;
|
|
4511
|
+
let entry = entryPath;
|
|
4512
|
+
try {
|
|
4513
|
+
entry = realpathSync(entryPath);
|
|
4514
|
+
} catch {
|
|
4515
|
+
}
|
|
4516
|
+
const distDir = dirname(resolve3(entry));
|
|
4517
|
+
if (basename3(distDir) !== "dist") return void 0;
|
|
4518
|
+
const repoRoot = dirname(distDir);
|
|
4519
|
+
let stamped;
|
|
4520
|
+
try {
|
|
4521
|
+
const raw = readFileSync3(join5(distDir, DIGEST_FILE), "utf8").trim();
|
|
4522
|
+
if (/^[0-9a-f]{64}$/.test(raw)) stamped = raw;
|
|
4523
|
+
} catch {
|
|
4524
|
+
}
|
|
4525
|
+
const roots = reviewSourceRoots(repoRoot);
|
|
4526
|
+
const measured = measureReviewSources(repoRoot, roots);
|
|
4527
|
+
const current = measured.digest;
|
|
4528
|
+
if (stamped && current && measured.partial) {
|
|
4529
|
+
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.");
|
|
4530
|
+
}
|
|
4531
|
+
const staleness = bundleStaleness(stamped, current);
|
|
4532
|
+
const warning = staleBundleWarning(staleness, brief);
|
|
4533
|
+
if (warning) return warning;
|
|
4534
|
+
if (stamped && !current && (measured.incomplete || roots.some((r) => existsSync3(r.path)))) {
|
|
4535
|
+
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}.`;
|
|
4536
|
+
return `review: could not check whether the bundle is current \u2014 ${reason}`;
|
|
4537
|
+
}
|
|
4538
|
+
if (!stamped && current) {
|
|
4539
|
+
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.");
|
|
4540
|
+
}
|
|
4541
|
+
return void 0;
|
|
4542
|
+
} catch {
|
|
4543
|
+
return void 0;
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
__name(bundleStalenessNotices, "bundleStalenessNotices");
|
|
4547
|
+
function staleBundleWarning(s, brief) {
|
|
4548
|
+
if (!s.stale) return void 0;
|
|
4549
|
+
if (brief) {
|
|
4550
|
+
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.`;
|
|
4551
|
+
}
|
|
4552
|
+
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.`;
|
|
4553
|
+
}
|
|
4554
|
+
__name(staleBundleWarning, "staleBundleWarning");
|
|
4555
|
+
|
|
4556
|
+
// packages/cli/src/commands/review/parse-args.ts
|
|
4341
4557
|
var EFFORT_LEVELS = /* @__PURE__ */ new Set([
|
|
4342
4558
|
"low",
|
|
4343
4559
|
"medium",
|
|
@@ -4604,108 +4820,475 @@ var parseArgsCommand = {
|
|
|
4604
4820
|
`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
4821
|
);
|
|
4606
4822
|
}
|
|
4607
|
-
const rawStr = stdin ?
|
|
4823
|
+
const rawStr = stdin ? readFileSync4(0, "utf8").replace(/\r?\n$/, "") : raw ?? "";
|
|
4824
|
+
const bundleNotice = bundleStalenessNotices(process.argv[1]);
|
|
4825
|
+
if (bundleNotice) {
|
|
4826
|
+
writeStderrLineSafe(bundleNotice);
|
|
4827
|
+
}
|
|
4608
4828
|
const parsed = parseReviewArgs(rawStr);
|
|
4609
4829
|
const json = JSON.stringify(parsed, null, 2);
|
|
4610
4830
|
if (out) {
|
|
4611
|
-
mkdirSync2(
|
|
4831
|
+
mkdirSync2(dirname2(out), { recursive: true });
|
|
4612
4832
|
writeFileSync2(out, json, "utf8");
|
|
4613
4833
|
}
|
|
4614
4834
|
writeStdoutLine(json);
|
|
4615
4835
|
}, "handler")
|
|
4616
4836
|
};
|
|
4617
4837
|
|
|
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
|
|
4838
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
4624
4839
|
init_esbuild_shims();
|
|
4625
|
-
import { readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
4626
4840
|
|
|
4627
|
-
// packages/cli/src/commands/review/lib/
|
|
4841
|
+
// packages/cli/src/commands/review/lib/gh.ts
|
|
4628
4842
|
init_esbuild_shims();
|
|
4629
|
-
import {
|
|
4630
|
-
|
|
4631
|
-
var
|
|
4632
|
-
|
|
4633
|
-
|
|
4843
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4844
|
+
var MAX_RETRIES = 2;
|
|
4845
|
+
var BASE_DELAY_MS = 3e3;
|
|
4846
|
+
function sleepSync(ms) {
|
|
4847
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
4848
|
+
}
|
|
4849
|
+
__name(sleepSync, "sleepSync");
|
|
4850
|
+
var TRANSIENT_RE = /HTTP 5\d{2}|server is currently unavailable|service unavailable|bad gateway|internal server error/i;
|
|
4851
|
+
function isTransientGhError(err) {
|
|
4852
|
+
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
4853
|
+
const msg = err instanceof Error ? err.message : "";
|
|
4854
|
+
return TRANSIENT_RE.test(stderr) || TRANSIENT_RE.test(msg);
|
|
4855
|
+
}
|
|
4856
|
+
__name(isTransientGhError, "isTransientGhError");
|
|
4857
|
+
function execGhWithRetry(args, options) {
|
|
4858
|
+
const execOptions = {
|
|
4859
|
+
encoding: "utf8",
|
|
4860
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4861
|
+
env: ghEnv(),
|
|
4862
|
+
...options.input !== void 0 ? { input: options.input } : {}
|
|
4863
|
+
};
|
|
4864
|
+
for (let attempt = 0; ; attempt++) {
|
|
4865
|
+
try {
|
|
4866
|
+
return execFileSync2("gh", args, execOptions).replace(/\r\n/g, "\n").trim();
|
|
4867
|
+
} catch (err) {
|
|
4868
|
+
if (attempt < MAX_RETRIES && isTransientGhError(err)) {
|
|
4869
|
+
const delay = BASE_DELAY_MS * (attempt + 1);
|
|
4870
|
+
process.stderr.write(
|
|
4871
|
+
`gh transient error (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms\u2026
|
|
4872
|
+
`
|
|
4873
|
+
);
|
|
4874
|
+
sleepSync(delay);
|
|
4875
|
+
continue;
|
|
4876
|
+
}
|
|
4877
|
+
throw err;
|
|
4878
|
+
}
|
|
4634
4879
|
}
|
|
4635
|
-
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4880
|
+
}
|
|
4881
|
+
__name(execGhWithRetry, "execGhWithRetry");
|
|
4882
|
+
var ghHost;
|
|
4883
|
+
var HOSTNAME_RE = /^[A-Za-z0-9.-]+(?::\d+)?$/;
|
|
4884
|
+
function setGhHost(host) {
|
|
4885
|
+
if (host === void 0 || host === "") {
|
|
4886
|
+
ghHost = void 0;
|
|
4887
|
+
return;
|
|
4888
|
+
}
|
|
4889
|
+
if (!HOSTNAME_RE.test(host)) {
|
|
4890
|
+
throw new TypeError(
|
|
4891
|
+
`--host must be a hostname (optionally :port), got ${JSON.stringify(host)}`
|
|
4642
4892
|
);
|
|
4643
4893
|
}
|
|
4644
|
-
|
|
4645
|
-
projectDir,
|
|
4646
|
-
sessionId,
|
|
4647
|
-
dir: join5(projectDir, "subagents", sessionId)
|
|
4648
|
-
};
|
|
4894
|
+
ghHost = host;
|
|
4649
4895
|
}
|
|
4650
|
-
__name(
|
|
4651
|
-
function
|
|
4652
|
-
return
|
|
4896
|
+
__name(setGhHost, "setGhHost");
|
|
4897
|
+
function getGhHost() {
|
|
4898
|
+
return ghHost;
|
|
4653
4899
|
}
|
|
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("");
|
|
4900
|
+
__name(getGhHost, "getGhHost");
|
|
4901
|
+
function resolveGhHost(flagHost) {
|
|
4902
|
+
return flagHost ?? (process.env["GH_HOST"]?.trim() || void 0);
|
|
4659
4903
|
}
|
|
4660
|
-
__name(
|
|
4661
|
-
function
|
|
4662
|
-
|
|
4663
|
-
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
4904
|
+
__name(resolveGhHost, "resolveGhHost");
|
|
4905
|
+
function ghEnv() {
|
|
4906
|
+
return ghHost ? { ...process.env, GH_HOST: ghHost } : void 0;
|
|
4664
4907
|
}
|
|
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];
|
|
4908
|
+
__name(ghEnv, "ghEnv");
|
|
4909
|
+
function gh(...args) {
|
|
4910
|
+
return execGhWithRetry(args, {});
|
|
4674
4911
|
}
|
|
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
|
-
|
|
4912
|
+
__name(gh, "gh");
|
|
4913
|
+
function ghWithInputRetried(input, ...args) {
|
|
4914
|
+
return execGhWithRetry(args, { input });
|
|
4915
|
+
}
|
|
4916
|
+
__name(ghWithInputRetried, "ghWithInputRetried");
|
|
4917
|
+
function ghWithInput(input, ...args) {
|
|
4918
|
+
return execFileSync2("gh", args, {
|
|
4919
|
+
encoding: "utf8",
|
|
4920
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4921
|
+
env: ghEnv(),
|
|
4922
|
+
input
|
|
4923
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
4924
|
+
}
|
|
4925
|
+
__name(ghWithInput, "ghWithInput");
|
|
4926
|
+
function ghApiAll(path3) {
|
|
4927
|
+
const out = gh("api", "--paginate", path3);
|
|
4928
|
+
if (!out) return [];
|
|
4929
|
+
const parsed = JSON.parse(out);
|
|
4930
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4931
|
+
}
|
|
4932
|
+
__name(ghApiAll, "ghApiAll");
|
|
4933
|
+
function ghApiAllNested(path3, key) {
|
|
4934
|
+
return parseNdjson(gh("api", "--paginate", path3, "--jq", `.${key}[]`), {
|
|
4935
|
+
strict: true
|
|
4936
|
+
});
|
|
4937
|
+
}
|
|
4938
|
+
__name(ghApiAllNested, "ghApiAllNested");
|
|
4939
|
+
function parseNdjson(out, opts = {}) {
|
|
4940
|
+
const strict = opts.strict ?? true;
|
|
4941
|
+
if (!out) return [];
|
|
4942
|
+
const values = [];
|
|
4943
|
+
for (const line of out.split("\n")) {
|
|
4944
|
+
if (line.trim().length === 0) continue;
|
|
4945
|
+
if (strict) {
|
|
4946
|
+
values.push(JSON.parse(line));
|
|
4947
|
+
continue;
|
|
4948
|
+
}
|
|
4698
4949
|
try {
|
|
4699
|
-
|
|
4950
|
+
values.push(JSON.parse(line));
|
|
4700
4951
|
} catch {
|
|
4701
|
-
continue;
|
|
4702
4952
|
}
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4953
|
+
}
|
|
4954
|
+
return values;
|
|
4955
|
+
}
|
|
4956
|
+
__name(parseNdjson, "parseNdjson");
|
|
4957
|
+
function currentUser() {
|
|
4958
|
+
return gh("api", "user", "--jq", ".login");
|
|
4959
|
+
}
|
|
4960
|
+
__name(currentUser, "currentUser");
|
|
4961
|
+
function ensureAuthenticated() {
|
|
4962
|
+
for (let attempt = 0; ; attempt++) {
|
|
4963
|
+
try {
|
|
4964
|
+
execFileSync2("gh", ["auth", "status"], { stdio: "pipe", env: ghEnv() });
|
|
4965
|
+
return;
|
|
4966
|
+
} catch (err) {
|
|
4967
|
+
if (attempt === 0 && err.code !== "ENOENT") {
|
|
4968
|
+
sleepSync(2e3);
|
|
4969
|
+
continue;
|
|
4970
|
+
}
|
|
4971
|
+
throw new Error(
|
|
4972
|
+
"gh CLI is not authenticated. Run `gh auth login` and retry."
|
|
4973
|
+
);
|
|
4707
4974
|
}
|
|
4708
|
-
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
__name(ensureAuthenticated, "ensureAuthenticated");
|
|
4978
|
+
|
|
4979
|
+
// packages/cli/src/commands/review/lib/git.ts
|
|
4980
|
+
init_esbuild_shims();
|
|
4981
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
4982
|
+
import { existsSync as existsSync4, rmSync as rmSync2 } from "node:fs";
|
|
4983
|
+
var GIT_TIMEOUT_MS2 = 12e4;
|
|
4984
|
+
function gitOpts() {
|
|
4985
|
+
return {
|
|
4986
|
+
timeout: GIT_TIMEOUT_MS2,
|
|
4987
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
__name(gitOpts, "gitOpts");
|
|
4991
|
+
function git(...args) {
|
|
4992
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8" }).replace(/\r\n/g, "\n").trim();
|
|
4993
|
+
}
|
|
4994
|
+
__name(git, "git");
|
|
4995
|
+
function gitWithInput(input, args) {
|
|
4996
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8", input }).replace(/\r\n/g, "\n").trim();
|
|
4997
|
+
}
|
|
4998
|
+
__name(gitWithInput, "gitWithInput");
|
|
4999
|
+
function gitOpt(...args) {
|
|
5000
|
+
try {
|
|
5001
|
+
return execFileSync3("git", args, {
|
|
5002
|
+
...gitOpts(),
|
|
5003
|
+
encoding: "utf8",
|
|
5004
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5005
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
5006
|
+
} catch {
|
|
5007
|
+
return null;
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
__name(gitOpt, "gitOpt");
|
|
5011
|
+
function refExists(ref) {
|
|
5012
|
+
return gitOpt("rev-parse", "--verify", "--quiet", ref) !== null;
|
|
5013
|
+
}
|
|
5014
|
+
__name(refExists, "refExists");
|
|
5015
|
+
function worktreeReleaseResult(existed, stillThere, removeError) {
|
|
5016
|
+
const freed = existed && !stillThere;
|
|
5017
|
+
if (!existed || freed) {
|
|
5018
|
+
return { existed, freed, reason: void 0 };
|
|
5019
|
+
}
|
|
5020
|
+
return {
|
|
5021
|
+
existed,
|
|
5022
|
+
freed,
|
|
5023
|
+
reason: removeError ? removeError instanceof Error ? removeError.message : String(removeError) : "the path is still there after `git worktree remove --force` and `rm -rf`"
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
__name(worktreeReleaseResult, "worktreeReleaseResult");
|
|
5027
|
+
function releaseWorktree(worktreePath2) {
|
|
5028
|
+
const existed = existsSync4(worktreePath2);
|
|
5029
|
+
let removeError;
|
|
5030
|
+
if (existed) {
|
|
5031
|
+
gitOpt("worktree", "remove", worktreePath2, "--force");
|
|
5032
|
+
try {
|
|
5033
|
+
rmSync2(worktreePath2, { recursive: true, force: true });
|
|
5034
|
+
} catch (e) {
|
|
5035
|
+
removeError = e;
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
gitOpt("worktree", "prune");
|
|
5039
|
+
return worktreeReleaseResult(existed, existsSync4(worktreePath2), removeError);
|
|
5040
|
+
}
|
|
5041
|
+
__name(releaseWorktree, "releaseWorktree");
|
|
5042
|
+
function gitRaw(...args) {
|
|
5043
|
+
return execFileSync3("git", args, {
|
|
5044
|
+
...gitOpts(),
|
|
5045
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
5046
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
__name(gitRaw, "gitRaw");
|
|
5050
|
+
function gitRawTolerateDiff(...args) {
|
|
5051
|
+
try {
|
|
5052
|
+
return gitRaw(...args);
|
|
5053
|
+
} catch (err) {
|
|
5054
|
+
const e = err;
|
|
5055
|
+
if (e.status === 1 && e.stdout && e.stdout.length > 0) return e.stdout;
|
|
5056
|
+
throw err;
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
__name(gitRawTolerateDiff, "gitRawTolerateDiff");
|
|
5060
|
+
|
|
5061
|
+
// packages/cli/src/commands/review/lib/remote-match.ts
|
|
5062
|
+
init_esbuild_shims();
|
|
5063
|
+
function normalizeSegment(value) {
|
|
5064
|
+
const v = value.toLowerCase();
|
|
5065
|
+
return v.endsWith(".git") ? v.slice(0, -4) : v;
|
|
5066
|
+
}
|
|
5067
|
+
__name(normalizeSegment, "normalizeSegment");
|
|
5068
|
+
function parseRemoteUrl(raw) {
|
|
5069
|
+
const url = raw.trim();
|
|
5070
|
+
if (url === "") return null;
|
|
5071
|
+
let host;
|
|
5072
|
+
let pathPart;
|
|
5073
|
+
const schemeIdx = url.indexOf("://");
|
|
5074
|
+
if (schemeIdx !== -1) {
|
|
5075
|
+
let parsed;
|
|
5076
|
+
try {
|
|
5077
|
+
parsed = new URL(url);
|
|
5078
|
+
} catch {
|
|
5079
|
+
return null;
|
|
5080
|
+
}
|
|
5081
|
+
if (parsed.hostname === "") return null;
|
|
5082
|
+
host = parsed.hostname;
|
|
5083
|
+
pathPart = parsed.pathname;
|
|
5084
|
+
} else {
|
|
5085
|
+
const colonIdx = url.indexOf(":");
|
|
5086
|
+
const slashIdx = url.indexOf("/");
|
|
5087
|
+
if (colonIdx === -1 || slashIdx === -1 || colonIdx > slashIdx) {
|
|
5088
|
+
return null;
|
|
5089
|
+
}
|
|
5090
|
+
host = url.slice(0, colonIdx);
|
|
5091
|
+
const atIdx = host.lastIndexOf("@");
|
|
5092
|
+
if (atIdx !== -1) host = host.slice(atIdx + 1);
|
|
5093
|
+
pathPart = url.slice(colonIdx + 1);
|
|
5094
|
+
}
|
|
5095
|
+
const segments = pathPart.split("/").map((s) => s.trim()).filter((s) => s !== "");
|
|
5096
|
+
if (segments.length !== 2) return null;
|
|
5097
|
+
if (host === "") return null;
|
|
5098
|
+
return {
|
|
5099
|
+
host: host.toLowerCase(),
|
|
5100
|
+
owner: normalizeSegment(segments[0]),
|
|
5101
|
+
repo: normalizeSegment(segments[1])
|
|
5102
|
+
};
|
|
5103
|
+
}
|
|
5104
|
+
__name(parseRemoteUrl, "parseRemoteUrl");
|
|
5105
|
+
function matchRemotes(remoteVOutput, { owner, repo, host = "github.com" }) {
|
|
5106
|
+
const wantOwner = normalizeSegment(owner);
|
|
5107
|
+
const wantRepo = normalizeSegment(repo);
|
|
5108
|
+
const wantHost = normalizeSegment(host.replace(/:\d+$/, ""));
|
|
5109
|
+
const matched = [];
|
|
5110
|
+
for (const line of remoteVOutput.split("\n")) {
|
|
5111
|
+
const trimmed = line.trim();
|
|
5112
|
+
if (trimmed === "" || !/\(fetch\)(\s+\[[^\]]*\])?$/.test(trimmed)) {
|
|
5113
|
+
continue;
|
|
5114
|
+
}
|
|
5115
|
+
const nameMatch = trimmed.match(
|
|
5116
|
+
/^(\S+)\s+(.*)\s+\(fetch\)(\s+\[[^\]]*\])?$/
|
|
5117
|
+
);
|
|
5118
|
+
if (!nameMatch) continue;
|
|
5119
|
+
const identity = parseRemoteUrl(nameMatch[2]);
|
|
5120
|
+
if (identity === null) continue;
|
|
5121
|
+
if (identity.host === wantHost && identity.owner === wantOwner && identity.repo === wantRepo) {
|
|
5122
|
+
matched.push(nameMatch[1]);
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
return { matched };
|
|
5126
|
+
}
|
|
5127
|
+
__name(matchRemotes, "matchRemotes");
|
|
5128
|
+
|
|
5129
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
5130
|
+
function runMatchRemote(args) {
|
|
5131
|
+
try {
|
|
5132
|
+
git("rev-parse", "--is-inside-work-tree");
|
|
5133
|
+
} catch (err) {
|
|
5134
|
+
writeStderrLineSafe(
|
|
5135
|
+
`match-remote: git cannot resolve this repository: ${err.message}`
|
|
5136
|
+
);
|
|
5137
|
+
process.exitCode = 1;
|
|
5138
|
+
return;
|
|
5139
|
+
}
|
|
5140
|
+
const host = resolveGhHost(args.host) ?? "github.com";
|
|
5141
|
+
let remoteV;
|
|
5142
|
+
try {
|
|
5143
|
+
remoteV = git("remote", "-v");
|
|
5144
|
+
} catch (err) {
|
|
5145
|
+
writeStderrLineSafe(
|
|
5146
|
+
`match-remote: \`git remote -v\` failed: ${err.message}`
|
|
5147
|
+
);
|
|
5148
|
+
process.exitCode = 1;
|
|
5149
|
+
return;
|
|
5150
|
+
}
|
|
5151
|
+
const { matched } = matchRemotes(remoteV, {
|
|
5152
|
+
owner: args.owner,
|
|
5153
|
+
repo: args.repo,
|
|
5154
|
+
host
|
|
5155
|
+
});
|
|
5156
|
+
if (matched.length === 1) {
|
|
5157
|
+
writeStdoutLine(matched[0]);
|
|
5158
|
+
return;
|
|
5159
|
+
}
|
|
5160
|
+
if (matched.length === 0) {
|
|
5161
|
+
writeStdoutLine("none");
|
|
5162
|
+
writeStderrLineSafe(
|
|
5163
|
+
`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.`
|
|
5164
|
+
);
|
|
5165
|
+
process.exitCode = 6;
|
|
5166
|
+
return;
|
|
5167
|
+
}
|
|
5168
|
+
for (const name of matched) {
|
|
5169
|
+
writeStdoutLine(name);
|
|
5170
|
+
}
|
|
5171
|
+
writeStderrLineSafe(
|
|
5172
|
+
`warning: ${matched.length} remotes match ${host}/${args.owner}/${args.repo} (${matched.join(", ")}); refusing to pick one \u2014 the review stops here.`
|
|
5173
|
+
);
|
|
5174
|
+
process.exitCode = 7;
|
|
5175
|
+
}
|
|
5176
|
+
__name(runMatchRemote, "runMatchRemote");
|
|
5177
|
+
var matchRemoteCommand = {
|
|
5178
|
+
command: "match-remote",
|
|
5179
|
+
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)",
|
|
5180
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.option("owner", {
|
|
5181
|
+
type: "string",
|
|
5182
|
+
demandOption: true,
|
|
5183
|
+
describe: "The repository owner (from the PR URL, or `gh repo view`)"
|
|
5184
|
+
}).option("repo", {
|
|
5185
|
+
type: "string",
|
|
5186
|
+
demandOption: true,
|
|
5187
|
+
describe: "The repository name"
|
|
5188
|
+
}).option("host", {
|
|
5189
|
+
type: "string",
|
|
5190
|
+
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)"
|
|
5191
|
+
}), "builder"),
|
|
5192
|
+
handler: /* @__PURE__ */ __name((argv) => {
|
|
5193
|
+
runMatchRemote({
|
|
5194
|
+
owner: String(argv["owner"]),
|
|
5195
|
+
repo: String(argv["repo"]),
|
|
5196
|
+
host: argv.host
|
|
5197
|
+
});
|
|
5198
|
+
}, "handler")
|
|
5199
|
+
};
|
|
5200
|
+
|
|
5201
|
+
// packages/cli/src/commands/review/compose-review.ts
|
|
5202
|
+
init_esbuild_shims();
|
|
5203
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
5204
|
+
import { dirname as dirname5, join as join10 } from "node:path";
|
|
5205
|
+
|
|
5206
|
+
// packages/cli/src/commands/review/lib/coverage.ts
|
|
5207
|
+
init_esbuild_shims();
|
|
5208
|
+
import { readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
|
|
5209
|
+
|
|
5210
|
+
// packages/cli/src/commands/review/lib/transcripts.ts
|
|
5211
|
+
init_esbuild_shims();
|
|
5212
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
5213
|
+
import { join as join6 } from "node:path";
|
|
5214
|
+
var TranscriptsUnavailableError = class extends Error {
|
|
5215
|
+
static {
|
|
5216
|
+
__name(this, "TranscriptsUnavailableError");
|
|
5217
|
+
}
|
|
5218
|
+
};
|
|
5219
|
+
function transcriptPaths(env = process.env) {
|
|
5220
|
+
const projectDir = env["QWEN_CODE_PROJECT_DIR"]?.trim();
|
|
5221
|
+
const sessionId = env["QWEN_CODE_SESSION_ID"]?.trim();
|
|
5222
|
+
if (!projectDir || !sessionId) {
|
|
5223
|
+
throw new TranscriptsUnavailableError(
|
|
5224
|
+
"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"
|
|
5225
|
+
);
|
|
5226
|
+
}
|
|
5227
|
+
return {
|
|
5228
|
+
projectDir,
|
|
5229
|
+
sessionId,
|
|
5230
|
+
dir: join6(projectDir, "subagents", sessionId)
|
|
5231
|
+
};
|
|
5232
|
+
}
|
|
5233
|
+
__name(transcriptPaths, "transcriptPaths");
|
|
5234
|
+
function transcriptDir(env = process.env) {
|
|
5235
|
+
return transcriptPaths(env).dir;
|
|
5236
|
+
}
|
|
5237
|
+
__name(transcriptDir, "transcriptDir");
|
|
5238
|
+
function textOf(rec) {
|
|
5239
|
+
const msg = rec["message"];
|
|
5240
|
+
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
5241
|
+
return parts.map((p) => p.text).filter((t2) => typeof t2 === "string").join("");
|
|
5242
|
+
}
|
|
5243
|
+
__name(textOf, "textOf");
|
|
5244
|
+
function isErrorPart(part) {
|
|
5245
|
+
const resp = part.functionResponse?.response;
|
|
5246
|
+
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
5247
|
+
}
|
|
5248
|
+
__name(isErrorPart, "isErrorPart");
|
|
5249
|
+
function rangeOf(args) {
|
|
5250
|
+
const offset = args["offset"];
|
|
5251
|
+
const limit = args["limit"];
|
|
5252
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
|
|
5253
|
+
return null;
|
|
5254
|
+
}
|
|
5255
|
+
const off = typeof offset === "number" && Number.isInteger(offset) && offset >= 0 ? offset : 0;
|
|
5256
|
+
return [off + 1, off + limit];
|
|
5257
|
+
}
|
|
5258
|
+
__name(rangeOf, "rangeOf");
|
|
5259
|
+
function parseTranscript(file, diffPath) {
|
|
5260
|
+
let raw;
|
|
5261
|
+
try {
|
|
5262
|
+
raw = readFileSync5(file, "utf8");
|
|
5263
|
+
} catch {
|
|
5264
|
+
return null;
|
|
5265
|
+
}
|
|
5266
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
5267
|
+
if (lines.length === 0) return null;
|
|
5268
|
+
let agentId = "";
|
|
5269
|
+
let agentName = "";
|
|
5270
|
+
let launchPrompt = "";
|
|
5271
|
+
let finalText = "";
|
|
5272
|
+
let successfulToolCalls = 0;
|
|
5273
|
+
let diffToolCalls = 0;
|
|
5274
|
+
const diffReads = [];
|
|
5275
|
+
const successfulCallArgs = [];
|
|
5276
|
+
const successfulReadFileArgs = [];
|
|
5277
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5278
|
+
const anonymous = [];
|
|
5279
|
+
for (const line of lines) {
|
|
5280
|
+
let rec;
|
|
5281
|
+
try {
|
|
5282
|
+
rec = JSON.parse(line);
|
|
5283
|
+
} catch {
|
|
5284
|
+
continue;
|
|
5285
|
+
}
|
|
5286
|
+
if (!agentId && typeof rec["agentId"] === "string")
|
|
5287
|
+
agentId = rec["agentId"];
|
|
5288
|
+
if (!agentName && typeof rec["agentName"] === "string") {
|
|
5289
|
+
agentName = rec["agentName"];
|
|
5290
|
+
}
|
|
5291
|
+
const type = rec["type"];
|
|
4709
5292
|
if (!launchPrompt && type === "user") launchPrompt = textOf(rec);
|
|
4710
5293
|
const msg = rec["message"];
|
|
4711
5294
|
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
@@ -4753,7 +5336,7 @@ function parseTranscript(file, diffPath) {
|
|
|
4753
5336
|
if (!agentId) return null;
|
|
4754
5337
|
let mtimeMs = 0;
|
|
4755
5338
|
try {
|
|
4756
|
-
mtimeMs =
|
|
5339
|
+
mtimeMs = statSync2(file).mtimeMs;
|
|
4757
5340
|
} catch {
|
|
4758
5341
|
}
|
|
4759
5342
|
return {
|
|
@@ -4771,7 +5354,7 @@ function parseTranscript(file, diffPath) {
|
|
|
4771
5354
|
}
|
|
4772
5355
|
__name(parseTranscript, "parseTranscript");
|
|
4773
5356
|
function listAgentTranscriptFiles(dir) {
|
|
4774
|
-
return
|
|
5357
|
+
return readdirSync3(dir).filter((name) => name.endsWith(".jsonl"));
|
|
4775
5358
|
}
|
|
4776
5359
|
__name(listAgentTranscriptFiles, "listAgentTranscriptFiles");
|
|
4777
5360
|
function readTranscripts(since, env = process.env, diffPath) {
|
|
@@ -4786,7 +5369,7 @@ function readTranscripts(since, env = process.env, diffPath) {
|
|
|
4786
5369
|
}
|
|
4787
5370
|
const out = [];
|
|
4788
5371
|
for (const name of names) {
|
|
4789
|
-
const rec = parseTranscript(
|
|
5372
|
+
const rec = parseTranscript(join6(dir, name), diffPath);
|
|
4790
5373
|
if (!rec) continue;
|
|
4791
5374
|
if (since !== void 0 && rec.mtimeMs < since) continue;
|
|
4792
5375
|
out.push(rec);
|
|
@@ -4805,24 +5388,24 @@ __name(wasGivenTheDiff, "wasGivenTheDiff");
|
|
|
4805
5388
|
init_esbuild_shims();
|
|
4806
5389
|
import {
|
|
4807
5390
|
mkdirSync as mkdirSync3,
|
|
4808
|
-
readFileSync as
|
|
4809
|
-
readdirSync as
|
|
4810
|
-
statSync as
|
|
5391
|
+
readFileSync as readFileSync6,
|
|
5392
|
+
readdirSync as readdirSync4,
|
|
5393
|
+
statSync as statSync3,
|
|
4811
5394
|
writeFileSync as writeFileSync3
|
|
4812
5395
|
} from "node:fs";
|
|
4813
|
-
import { dirname as
|
|
5396
|
+
import { dirname as dirname3, join as join7, basename as basename4, resolve as resolve4 } from "node:path";
|
|
4814
5397
|
function promptRecordDir(planPath) {
|
|
4815
|
-
const p =
|
|
4816
|
-
return
|
|
5398
|
+
const p = resolve4(planPath);
|
|
5399
|
+
return join7(dirname3(p), `${basename4(p).replace(/\.json$/i, "")}-prompts`);
|
|
4817
5400
|
}
|
|
4818
5401
|
__name(promptRecordDir, "promptRecordDir");
|
|
4819
5402
|
var fileFor = /* @__PURE__ */ __name((key) => `${encodeURIComponent(key)}.txt`, "fileFor");
|
|
4820
5403
|
function briefPath(planPath, key) {
|
|
4821
|
-
return
|
|
5404
|
+
return join7(promptRecordDir(planPath), `${encodeURIComponent(key)}.brief.md`);
|
|
4822
5405
|
}
|
|
4823
5406
|
__name(briefPath, "briefPath");
|
|
4824
5407
|
function findingsFilePath(planPath, key) {
|
|
4825
|
-
return
|
|
5408
|
+
return join7(
|
|
4826
5409
|
promptRecordDir(planPath),
|
|
4827
5410
|
`${encodeURIComponent(key)}.findings.md`
|
|
4828
5411
|
);
|
|
@@ -4852,7 +5435,7 @@ function writeBrief(planPath, key, brief) {
|
|
|
4852
5435
|
const p = briefPath(planPath, key);
|
|
4853
5436
|
let hadRules = false;
|
|
4854
5437
|
try {
|
|
4855
|
-
hadRules =
|
|
5438
|
+
hadRules = readFileSync6(p, "utf8").includes(RULES_MARKER);
|
|
4856
5439
|
} catch {
|
|
4857
5440
|
}
|
|
4858
5441
|
if (hadRules && !brief.includes(RULES_MARKER)) {
|
|
@@ -4872,7 +5455,7 @@ function recordPrompt(planPath, key, prompt) {
|
|
|
4872
5455
|
try {
|
|
4873
5456
|
const dir = promptRecordDir(planPath);
|
|
4874
5457
|
mkdirSync3(dir, { recursive: true });
|
|
4875
|
-
writeFileSync3(
|
|
5458
|
+
writeFileSync3(join7(dir, fileFor(key)), prompt);
|
|
4876
5459
|
} catch {
|
|
4877
5460
|
}
|
|
4878
5461
|
}
|
|
@@ -4882,7 +5465,7 @@ function readRecordedPrompts(planPath, sinceMs) {
|
|
|
4882
5465
|
const dir = promptRecordDir(planPath);
|
|
4883
5466
|
let names;
|
|
4884
5467
|
try {
|
|
4885
|
-
names =
|
|
5468
|
+
names = readdirSync4(dir).sort();
|
|
4886
5469
|
} catch {
|
|
4887
5470
|
return out;
|
|
4888
5471
|
}
|
|
@@ -4895,9 +5478,9 @@ function readRecordedPrompts(planPath, sinceMs) {
|
|
|
4895
5478
|
} catch {
|
|
4896
5479
|
continue;
|
|
4897
5480
|
}
|
|
4898
|
-
const file =
|
|
4899
|
-
if (sinceMs !== void 0 &&
|
|
4900
|
-
out.set(key,
|
|
5481
|
+
const file = join7(dir, name);
|
|
5482
|
+
if (sinceMs !== void 0 && statSync3(file).mtimeMs < sinceMs) continue;
|
|
5483
|
+
out.set(key, readFileSync6(file, "utf8"));
|
|
4901
5484
|
} catch {
|
|
4902
5485
|
}
|
|
4903
5486
|
}
|
|
@@ -4963,6 +5546,10 @@ __name(isRepositoryContextRoleId, "isRepositoryContextRoleId");
|
|
|
4963
5546
|
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
5547
|
var BRIEFS = {
|
|
4965
5548
|
"0": {
|
|
5549
|
+
// Budget-exempt: Issue-sized mandatory work, not diff-sized: a small bugfix
|
|
5550
|
+
// referencing many issues would exhaust a diff-derived ceiling on
|
|
5551
|
+
// required fetches alone.
|
|
5552
|
+
budgetExempt: true,
|
|
4966
5553
|
label: "Agent 0: Issue fidelity & root-cause ownership",
|
|
4967
5554
|
publicLabel: "the linked-issue fidelity pass",
|
|
4968
5555
|
publicLabelZh: "\u5173\u8054 issue \u4E00\u81F4\u6027\u68C0\u67E5",
|
|
@@ -5253,6 +5840,10 @@ Under that framing, look at:
|
|
|
5253
5840
|
You are undirected on purpose. Do not restrict yourself to the list.`
|
|
5254
5841
|
},
|
|
5255
5842
|
"7": {
|
|
5843
|
+
// Budget-exempt: Deterministic build/test commands — the run costs what the
|
|
5844
|
+
// project scripts cost, and stopping early is the one thing it must
|
|
5845
|
+
// never do.
|
|
5846
|
+
budgetExempt: true,
|
|
5256
5847
|
label: "Agent 7: Build & test verification",
|
|
5257
5848
|
publicLabel: "the build-and-test check",
|
|
5258
5849
|
publicLabelZh: "\u6784\u5EFA\u4E0E\u6D4B\u8BD5\u9A8C\u8BC1",
|
|
@@ -5337,6 +5928,9 @@ This file is largely rewritten, and reviewing it as a diff is the wrong frame. T
|
|
|
5337
5928
|
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
5929
|
},
|
|
5339
5930
|
verify: {
|
|
5931
|
+
// Budget-exempt: Its per-finding re-trace must not stop early; `verifyShard`
|
|
5932
|
+
// already governs its load.
|
|
5933
|
+
budgetExempt: true,
|
|
5340
5934
|
reviewsCode: true,
|
|
5341
5935
|
output: "verdicts",
|
|
5342
5936
|
acceptsFindings: true,
|
|
@@ -5591,21 +6185,21 @@ __name(repositoryContextOf, "repositoryContextOf");
|
|
|
5591
6185
|
// packages/cli/src/commands/review/script-lint.ts
|
|
5592
6186
|
init_esbuild_shims();
|
|
5593
6187
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
5594
|
-
import { createHash } from "node:crypto";
|
|
6188
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
5595
6189
|
import {
|
|
5596
|
-
readFileSync as
|
|
6190
|
+
readFileSync as readFileSync7,
|
|
5597
6191
|
writeFileSync as writeFileSync4,
|
|
5598
6192
|
mkdirSync as mkdirSync4,
|
|
5599
6193
|
mkdtempSync,
|
|
5600
|
-
rmSync as
|
|
6194
|
+
rmSync as rmSync3,
|
|
5601
6195
|
lstatSync,
|
|
5602
|
-
realpathSync,
|
|
6196
|
+
realpathSync as realpathSync2,
|
|
5603
6197
|
openSync,
|
|
5604
6198
|
readSync,
|
|
5605
6199
|
closeSync
|
|
5606
6200
|
} from "node:fs";
|
|
5607
6201
|
import { tmpdir } from "node:os";
|
|
5608
|
-
import { dirname as
|
|
6202
|
+
import { dirname as dirname4, join as join8, resolve as resolve5, basename as basename5, sep as sep2 } from "node:path";
|
|
5609
6203
|
|
|
5610
6204
|
// packages/cli/src/commands/review/lib/diff-plan.ts
|
|
5611
6205
|
init_esbuild_shims();
|
|
@@ -5986,7 +6580,7 @@ __name(chunksCoverDiff, "chunksCoverDiff");
|
|
|
5986
6580
|
// packages/cli/src/commands/review/script-lint.ts
|
|
5987
6581
|
function pathTool(path3) {
|
|
5988
6582
|
const p = path3.toLowerCase();
|
|
5989
|
-
const base =
|
|
6583
|
+
const base = basename5(p);
|
|
5990
6584
|
if (/(^|\/)\.github\/workflows\/.+\.ya?ml$/.test(p)) {
|
|
5991
6585
|
return "actionlint";
|
|
5992
6586
|
}
|
|
@@ -6035,7 +6629,7 @@ function addedRangesFromDiff(diffText) {
|
|
|
6035
6629
|
__name(addedRangesFromDiff, "addedRangesFromDiff");
|
|
6036
6630
|
function realIfExists(p) {
|
|
6037
6631
|
try {
|
|
6038
|
-
return
|
|
6632
|
+
return realpathSync2(p);
|
|
6039
6633
|
} catch {
|
|
6040
6634
|
return void 0;
|
|
6041
6635
|
}
|
|
@@ -6069,14 +6663,14 @@ var hadolintEmptyConfigPath;
|
|
|
6069
6663
|
function emptyHadolintConfig() {
|
|
6070
6664
|
if (!hadolintEmptyConfigPath) {
|
|
6071
6665
|
try {
|
|
6072
|
-
const d = mkdtempSync(
|
|
6666
|
+
const d = mkdtempSync(join8(tmpdir(), "qwen-review-hadolint-"));
|
|
6073
6667
|
process.on("exit", () => {
|
|
6074
6668
|
try {
|
|
6075
|
-
|
|
6669
|
+
rmSync3(d, { recursive: true, force: true });
|
|
6076
6670
|
} catch {
|
|
6077
6671
|
}
|
|
6078
6672
|
});
|
|
6079
|
-
const p =
|
|
6673
|
+
const p = join8(d, "config.yaml");
|
|
6080
6674
|
writeFileSync4(p, "ignored: []\n");
|
|
6081
6675
|
hadolintEmptyConfigPath = p;
|
|
6082
6676
|
} catch {
|
|
@@ -6185,7 +6779,7 @@ __name(parseFindings, "parseFindings");
|
|
|
6185
6779
|
function diffHashOf(diffPath) {
|
|
6186
6780
|
if (typeof diffPath !== "string" || !diffPath) return void 0;
|
|
6187
6781
|
try {
|
|
6188
|
-
return
|
|
6782
|
+
return createHash2("sha256").update(readFileSync7(diffPath)).digest("hex");
|
|
6189
6783
|
} catch {
|
|
6190
6784
|
return void 0;
|
|
6191
6785
|
}
|
|
@@ -6194,7 +6788,7 @@ __name(diffHashOf, "diffHashOf");
|
|
|
6194
6788
|
function runScriptLint(args, runner = runTool) {
|
|
6195
6789
|
let plan;
|
|
6196
6790
|
try {
|
|
6197
|
-
plan = JSON.parse(
|
|
6791
|
+
plan = JSON.parse(readFileSync7(args.plan, "utf8"));
|
|
6198
6792
|
} catch (err) {
|
|
6199
6793
|
throw new Error(
|
|
6200
6794
|
`script-lint: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -6206,7 +6800,7 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6206
6800
|
let diffBuf;
|
|
6207
6801
|
if (typeof plan.diffPathAbsolute === "string") {
|
|
6208
6802
|
try {
|
|
6209
|
-
diffBuf =
|
|
6803
|
+
diffBuf = readFileSync7(plan.diffPathAbsolute);
|
|
6210
6804
|
} catch {
|
|
6211
6805
|
diffBuf = void 0;
|
|
6212
6806
|
}
|
|
@@ -6214,7 +6808,7 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6214
6808
|
if (diffBuf) {
|
|
6215
6809
|
try {
|
|
6216
6810
|
addedRanges = addedRangesFromDiff(diffBuf.toString("utf8"));
|
|
6217
|
-
diffHash =
|
|
6811
|
+
diffHash = createHash2("sha256").update(diffBuf).digest("hex");
|
|
6218
6812
|
} catch {
|
|
6219
6813
|
addedRanges = /* @__PURE__ */ new Map();
|
|
6220
6814
|
diffHash = void 0;
|
|
@@ -6228,13 +6822,13 @@ function runScriptLint(args, runner = runTool) {
|
|
|
6228
6822
|
const errored = [];
|
|
6229
6823
|
const deferred = [];
|
|
6230
6824
|
const missing = /* @__PURE__ */ new Set();
|
|
6231
|
-
const wt =
|
|
6825
|
+
const wt = resolve5(args.worktree);
|
|
6232
6826
|
const wtReal = realIfExists(wt);
|
|
6233
6827
|
for (const f of files) {
|
|
6234
6828
|
const path3 = typeof f?.path === "string" ? f.path : "";
|
|
6235
6829
|
if (!path3) continue;
|
|
6236
|
-
const abs =
|
|
6237
|
-
const escapes = /* @__PURE__ */ __name((p, root) => p !== root && !p.startsWith(root +
|
|
6830
|
+
const abs = resolve5(join8(args.worktree, path3));
|
|
6831
|
+
const escapes = /* @__PURE__ */ __name((p, root) => p !== root && !p.startsWith(root + sep2), "escapes");
|
|
6238
6832
|
const real = realIfExists(abs);
|
|
6239
6833
|
if (escapes(abs, wt) || wtReal && real && escapes(real, wtReal)) {
|
|
6240
6834
|
const byName = pathTool(path3);
|
|
@@ -6365,7 +6959,7 @@ var scriptLintCommand = {
|
|
|
6365
6959
|
const report = runScriptLint(args);
|
|
6366
6960
|
const json = JSON.stringify(report, null, 2);
|
|
6367
6961
|
if (args.out) {
|
|
6368
|
-
mkdirSync4(
|
|
6962
|
+
mkdirSync4(dirname4(resolve5(args.out)), { recursive: true });
|
|
6369
6963
|
writeFileSync4(args.out, json);
|
|
6370
6964
|
}
|
|
6371
6965
|
writeStdoutLine(json);
|
|
@@ -6496,8 +7090,8 @@ __name(contextRoleRunsInThisReview, "contextRoleRunsInThisReview");
|
|
|
6496
7090
|
|
|
6497
7091
|
// packages/cli/src/commands/review/lib/deadline.ts
|
|
6498
7092
|
init_esbuild_shims();
|
|
6499
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
6500
|
-
import { join as
|
|
7093
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
7094
|
+
import { join as join9 } from "node:path";
|
|
6501
7095
|
var DEADLINE_ENV = "QWEN_REVIEW_DEADLINE_EPOCH";
|
|
6502
7096
|
var RESERVE_ENV = "QWEN_REVIEW_DEADLINE_RESERVE_SECONDS";
|
|
6503
7097
|
var DEFAULT_RESERVE_SECONDS = 4800;
|
|
@@ -6508,7 +7102,7 @@ var STOP_FILE = "budget-stop.json";
|
|
|
6508
7102
|
var RUN_EPOCH_SLACK_MS = 2e3;
|
|
6509
7103
|
function runEpochMs(planPath) {
|
|
6510
7104
|
try {
|
|
6511
|
-
return
|
|
7105
|
+
return statSync4(planPath).mtimeMs - RUN_EPOCH_SLACK_MS;
|
|
6512
7106
|
} catch {
|
|
6513
7107
|
return Number.NEGATIVE_INFINITY;
|
|
6514
7108
|
}
|
|
@@ -6516,8 +7110,8 @@ function runEpochMs(planPath) {
|
|
|
6516
7110
|
__name(runEpochMs, "runEpochMs");
|
|
6517
7111
|
function readRoundStamps(planPath) {
|
|
6518
7112
|
try {
|
|
6519
|
-
const raw =
|
|
6520
|
-
|
|
7113
|
+
const raw = readFileSync8(
|
|
7114
|
+
join9(promptRecordDir(planPath), STAMPS_FILE),
|
|
6521
7115
|
"utf8"
|
|
6522
7116
|
);
|
|
6523
7117
|
const parsed = JSON.parse(raw);
|
|
@@ -6538,7 +7132,7 @@ function stampRound(planPath, round, nowMs = Date.now()) {
|
|
|
6538
7132
|
stamps.push({ round: round ?? null, atMs: nowMs });
|
|
6539
7133
|
const dir = promptRecordDir(planPath);
|
|
6540
7134
|
mkdirSync5(dir, { recursive: true });
|
|
6541
|
-
writeFileSync5(
|
|
7135
|
+
writeFileSync5(join9(dir, STAMPS_FILE), JSON.stringify(stamps));
|
|
6542
7136
|
} catch {
|
|
6543
7137
|
}
|
|
6544
7138
|
}
|
|
@@ -6613,15 +7207,15 @@ function writeBudgetStop(planPath, spent, round, nowMs = Date.now()) {
|
|
|
6613
7207
|
reserveSeconds: spent.reserveSeconds,
|
|
6614
7208
|
atMs: nowMs
|
|
6615
7209
|
};
|
|
6616
|
-
writeFileSync5(
|
|
7210
|
+
writeFileSync5(join9(dir, STOP_FILE), JSON.stringify(stop, null, 2));
|
|
6617
7211
|
} catch {
|
|
6618
7212
|
}
|
|
6619
7213
|
}
|
|
6620
7214
|
__name(writeBudgetStop, "writeBudgetStop");
|
|
6621
7215
|
function readBudgetStop(planPath) {
|
|
6622
7216
|
try {
|
|
6623
|
-
const raw =
|
|
6624
|
-
|
|
7217
|
+
const raw = readFileSync8(
|
|
7218
|
+
join9(promptRecordDir(planPath), STOP_FILE),
|
|
6625
7219
|
"utf8"
|
|
6626
7220
|
);
|
|
6627
7221
|
const parsed = JSON.parse(raw);
|
|
@@ -6643,6 +7237,157 @@ function reverseAuditBudgetMessage(spent, round) {
|
|
|
6643
7237
|
}
|
|
6644
7238
|
__name(reverseAuditBudgetMessage, "reverseAuditBudgetMessage");
|
|
6645
7239
|
|
|
7240
|
+
// packages/cli/src/commands/review/lib/budget.ts
|
|
7241
|
+
init_esbuild_shims();
|
|
7242
|
+
var SWEEP_FLOOR = 25;
|
|
7243
|
+
var SPECIALIST_FLOOR = 80;
|
|
7244
|
+
var LINES_PER_ANGLE = 60;
|
|
7245
|
+
var MIN_INLINE_ANGLES = 3;
|
|
7246
|
+
var MAX_INLINE_ANGLES = 6;
|
|
7247
|
+
var VERIFY_SHARD = 8;
|
|
7248
|
+
var MIN_AGENT_TOOL_BUDGET = 30;
|
|
7249
|
+
var MAX_AGENT_TOOL_BUDGET = 60;
|
|
7250
|
+
var LINES_PER_TOOL_CALL = 20;
|
|
7251
|
+
function reviewBudget(input) {
|
|
7252
|
+
const src = sane(input.srcDiffLines);
|
|
7253
|
+
const total = sane(input.diffLines);
|
|
7254
|
+
const effective = Math.max(src, Math.floor(total / 8));
|
|
7255
|
+
const extraAngles = Math.floor(effective / LINES_PER_ANGLE);
|
|
7256
|
+
const inlineAngles = clamp(
|
|
7257
|
+
MIN_INLINE_ANGLES + extraAngles,
|
|
7258
|
+
MIN_INLINE_ANGLES,
|
|
7259
|
+
MAX_INLINE_ANGLES
|
|
7260
|
+
);
|
|
7261
|
+
return {
|
|
7262
|
+
inlineAngles,
|
|
7263
|
+
sweep: effective >= SWEEP_FLOOR,
|
|
7264
|
+
specialistCap: src >= SPECIALIST_FLOOR ? 2 : 0,
|
|
7265
|
+
verifyShard: VERIFY_SHARD,
|
|
7266
|
+
agentToolBudget: clamp(
|
|
7267
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(effective / LINES_PER_TOOL_CALL),
|
|
7268
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7269
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7270
|
+
)
|
|
7271
|
+
};
|
|
7272
|
+
}
|
|
7273
|
+
__name(reviewBudget, "reviewBudget");
|
|
7274
|
+
var MAX_TOTAL_TOOL_CALLS = 200;
|
|
7275
|
+
function launchToolBudget(planBudget, territoryLines, mandatoryReads) {
|
|
7276
|
+
const base = clamp(
|
|
7277
|
+
sane(planBudget) || MIN_AGENT_TOOL_BUDGET,
|
|
7278
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7279
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7280
|
+
);
|
|
7281
|
+
const allowance = territoryLines === null ? base : Math.min(
|
|
7282
|
+
base,
|
|
7283
|
+
clamp(
|
|
7284
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(sane(territoryLines) / LINES_PER_TOOL_CALL),
|
|
7285
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7286
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7287
|
+
)
|
|
7288
|
+
);
|
|
7289
|
+
return Math.min(
|
|
7290
|
+
MAX_TOTAL_TOOL_CALLS,
|
|
7291
|
+
allowance + Math.max(0, Math.floor(sane(mandatoryReads)))
|
|
7292
|
+
);
|
|
7293
|
+
}
|
|
7294
|
+
__name(launchToolBudget, "launchToolBudget");
|
|
7295
|
+
var BUDGET_GAP_LINE_RE = /^[ \t]*(?:[-*+]|\d+[.)])?[ \t]*(`?)[*_~]{0,3}(?:budget gap|预算(?:缺口|不足|用尽))[*_~]{0,3}[ \t]*[::][*_~]{0,3}[ \t]*(.+?)[ \t]*$/i;
|
|
7296
|
+
var GAP_HINT_RE = /budget gap|预算(?:缺口|不足|用尽)/i;
|
|
7297
|
+
var INLINE_BUDGET_GAP_RE = /(?:budget gap|预算(?:缺口|不足|用尽))[*_~`]{0,3}[ \t]*[::]/i;
|
|
7298
|
+
var PLACEHOLDER_GAP_RE = /^(?:<[^>]*>|none\b.*|n\/a\b.*|nothing\b.*|no (?:gaps?|checks?)\b.*|[-—*_~`]+)$/i;
|
|
7299
|
+
var MAX_GAP_LENGTH = 160;
|
|
7300
|
+
var MAX_GAPS_PER_AGENT = 8;
|
|
7301
|
+
var DANGEROUS_CHARS_RE = (
|
|
7302
|
+
// eslint-disable-next-line no-control-regex
|
|
7303
|
+
/[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e]/g
|
|
7304
|
+
);
|
|
7305
|
+
var WRAPPER_PAIRS = [
|
|
7306
|
+
["**", "**"],
|
|
7307
|
+
["__", "__"],
|
|
7308
|
+
["*", "*"],
|
|
7309
|
+
["_", "_"],
|
|
7310
|
+
["~", "~"],
|
|
7311
|
+
["`", "`"]
|
|
7312
|
+
];
|
|
7313
|
+
function stripWrappers(s) {
|
|
7314
|
+
let out = s;
|
|
7315
|
+
let changed = true;
|
|
7316
|
+
while (changed) {
|
|
7317
|
+
changed = false;
|
|
7318
|
+
for (const [open, close] of WRAPPER_PAIRS) {
|
|
7319
|
+
if (out.length > open.length + close.length && out.startsWith(open) && out.endsWith(close)) {
|
|
7320
|
+
out = out.slice(open.length, out.length - close.length).trim();
|
|
7321
|
+
changed = true;
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
return out;
|
|
7326
|
+
}
|
|
7327
|
+
__name(stripWrappers, "stripWrappers");
|
|
7328
|
+
function truncateGap(s) {
|
|
7329
|
+
const points = [...s];
|
|
7330
|
+
return points.length > MAX_GAP_LENGTH ? `${points.slice(0, MAX_GAP_LENGTH).join("")}\u2026` : s;
|
|
7331
|
+
}
|
|
7332
|
+
__name(truncateGap, "truncateGap");
|
|
7333
|
+
function budgetGapDisclosures(finalText) {
|
|
7334
|
+
if (!GAP_HINT_RE.test(finalText)) return [];
|
|
7335
|
+
const gaps = [];
|
|
7336
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7337
|
+
let inFence = false;
|
|
7338
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7339
|
+
if (/^[ \t]*(?:```|~~~)/.test(line)) {
|
|
7340
|
+
inFence = !inFence;
|
|
7341
|
+
continue;
|
|
7342
|
+
}
|
|
7343
|
+
if (inFence) continue;
|
|
7344
|
+
if (/^[ \t]*>/.test(line)) continue;
|
|
7345
|
+
const m = BUDGET_GAP_LINE_RE.exec(line.replace(DANGEROUS_CHARS_RE, " "));
|
|
7346
|
+
if (!m) continue;
|
|
7347
|
+
let raw = m[2] ?? "";
|
|
7348
|
+
if (m[1] === "`") {
|
|
7349
|
+
if (!raw.endsWith("`")) continue;
|
|
7350
|
+
raw = raw.slice(0, -1);
|
|
7351
|
+
}
|
|
7352
|
+
raw = stripWrappers(raw.trim()).trim();
|
|
7353
|
+
const normalized = raw.replace(/[.!…,;:\s]+$/, "").trim();
|
|
7354
|
+
if (normalized.length === 0 || PLACEHOLDER_GAP_RE.test(normalized)) {
|
|
7355
|
+
continue;
|
|
7356
|
+
}
|
|
7357
|
+
const key = normalized.toLowerCase();
|
|
7358
|
+
if (seen.has(key)) continue;
|
|
7359
|
+
seen.add(key);
|
|
7360
|
+
gaps.push(truncateGap(raw));
|
|
7361
|
+
if (gaps.length >= MAX_GAPS_PER_AGENT) break;
|
|
7362
|
+
}
|
|
7363
|
+
return gaps;
|
|
7364
|
+
}
|
|
7365
|
+
__name(budgetGapDisclosures, "budgetGapDisclosures");
|
|
7366
|
+
function stripBudgetGapLines(finalText) {
|
|
7367
|
+
if (!GAP_HINT_RE.test(finalText)) return finalText;
|
|
7368
|
+
const kept = [];
|
|
7369
|
+
let inFence = false;
|
|
7370
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7371
|
+
const fence = /^[ \t]*(?:```|~~~)/.test(line);
|
|
7372
|
+
if (fence) inFence = !inFence;
|
|
7373
|
+
if (!fence && !inFence && !/^[ \t]*>/.test(line) && BUDGET_GAP_LINE_RE.test(line)) {
|
|
7374
|
+
continue;
|
|
7375
|
+
}
|
|
7376
|
+
kept.push(line);
|
|
7377
|
+
}
|
|
7378
|
+
return kept.join("\n");
|
|
7379
|
+
}
|
|
7380
|
+
__name(stripBudgetGapLines, "stripBudgetGapLines");
|
|
7381
|
+
function sane(n) {
|
|
7382
|
+
const v = Number(n);
|
|
7383
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 0;
|
|
7384
|
+
}
|
|
7385
|
+
__name(sane, "sane");
|
|
7386
|
+
function clamp(v, lo, hi) {
|
|
7387
|
+
return Math.min(hi, Math.max(lo, v));
|
|
7388
|
+
}
|
|
7389
|
+
__name(clamp, "clamp");
|
|
7390
|
+
|
|
6646
7391
|
// packages/cli/src/commands/review/lib/shell-quote.ts
|
|
6647
7392
|
init_esbuild_shims();
|
|
6648
7393
|
function shellQuotePath(p) {
|
|
@@ -6652,7 +7397,7 @@ __name(shellQuotePath, "shellQuotePath");
|
|
|
6652
7397
|
|
|
6653
7398
|
// packages/cli/src/commands/review/lib/coverage.ts
|
|
6654
7399
|
function readPlan(path3) {
|
|
6655
|
-
const plan = JSON.parse(
|
|
7400
|
+
const plan = JSON.parse(readFileSync9(path3, "utf8"));
|
|
6656
7401
|
if (typeof plan?.diffPathAbsolute !== "string" || !plan.diffPathAbsolute) {
|
|
6657
7402
|
throw new Error(`coverage: ${path3} has no diffPathAbsolute`);
|
|
6658
7403
|
}
|
|
@@ -6663,7 +7408,7 @@ function readPlan(path3) {
|
|
|
6663
7408
|
if (problem) {
|
|
6664
7409
|
throw new Error(`coverage: ${path3} has ${problem}`);
|
|
6665
7410
|
}
|
|
6666
|
-
return { plan, mtimeMs:
|
|
7411
|
+
return { plan, mtimeMs: statSync5(path3).mtimeMs };
|
|
6667
7412
|
}
|
|
6668
7413
|
__name(readPlan, "readPlan");
|
|
6669
7414
|
var CHUNK_RE = /\bchunk\s+(\d+)\s+of\s+\d+\b/i;
|
|
@@ -6787,6 +7532,37 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6787
7532
|
return false;
|
|
6788
7533
|
}, "keySatisfied");
|
|
6789
7534
|
const superseded = /* @__PURE__ */ __name((rec, chunk2) => chunk2 !== null ? chunkSatisfied(chunk2, rec) : keySatisfied(rec), "superseded");
|
|
7535
|
+
const gapsMemo = /* @__PURE__ */ new Map();
|
|
7536
|
+
const gapsOf = /* @__PURE__ */ __name((rec) => {
|
|
7537
|
+
let g = gapsMemo.get(rec);
|
|
7538
|
+
if (g === void 0) {
|
|
7539
|
+
g = budgetGapDisclosures(rec.finalText);
|
|
7540
|
+
gapsMemo.set(rec, g);
|
|
7541
|
+
}
|
|
7542
|
+
return g;
|
|
7543
|
+
}, "gapsOf");
|
|
7544
|
+
const gapsSuperseded = /* @__PURE__ */ __name((rec, chunk2) => {
|
|
7545
|
+
if (chunk2 !== null) {
|
|
7546
|
+
const b = builtOf(`chunk-${chunk2}`);
|
|
7547
|
+
if (b === void 0) return false;
|
|
7548
|
+
return records.some(
|
|
7549
|
+
(r) => r !== rec && assignedChunk(r) === chunk2 && wasDeliveredVerbatim(r.launchPrompt, b) && r.diffToolCalls > 0 && gapsOf(r).length === 0
|
|
7550
|
+
);
|
|
7551
|
+
}
|
|
7552
|
+
for (const key of built.keys()) {
|
|
7553
|
+
const b = builtOf(key);
|
|
7554
|
+
if (b === void 0) continue;
|
|
7555
|
+
if (!wasDeliveredVerbatim(rec.launchPrompt, b)) continue;
|
|
7556
|
+
const needle = JSON.stringify(briefPath(planPath, key));
|
|
7557
|
+
if (records.some(
|
|
7558
|
+
(r) => r !== rec && wasDeliveredVerbatim(r.launchPrompt, b) && r.successfulCallArgs.some((a) => a.includes(needle)) && gapsOf(r).length === 0
|
|
7559
|
+
)) {
|
|
7560
|
+
return true;
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
return false;
|
|
7564
|
+
}, "gapsSuperseded");
|
|
7565
|
+
const budgetGaps = [];
|
|
6790
7566
|
for (const rec of records) {
|
|
6791
7567
|
const chunk2 = assignedChunk(rec);
|
|
6792
7568
|
const name = label(rec, chunk2);
|
|
@@ -6844,6 +7620,10 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6844
7620
|
}
|
|
6845
7621
|
continue;
|
|
6846
7622
|
}
|
|
7623
|
+
const gaps = gapsOf(rec);
|
|
7624
|
+
if (gaps.length > 0 && !gapsSuperseded(rec, chunk2)) {
|
|
7625
|
+
budgetGaps.push({ agent: name, gaps });
|
|
7626
|
+
}
|
|
6847
7627
|
const ranges = merge([...told, ...rec.diffReads]);
|
|
6848
7628
|
if (ranges.length === 0) continue;
|
|
6849
7629
|
const u = UNCOVERABLE_RE.exec(rec.finalText);
|
|
@@ -7001,6 +7781,7 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
7001
7781
|
unreadBriefs,
|
|
7002
7782
|
missingChunks,
|
|
7003
7783
|
uncoverableChunks: [...uncoverable].sort((a, b) => a - b),
|
|
7784
|
+
budgetGaps,
|
|
7004
7785
|
coveredChunks: [...covered].sort((a, b) => a - b),
|
|
7005
7786
|
plannedChunks: plan.chunks.map((c) => ({
|
|
7006
7787
|
id: c.id,
|
|
@@ -7167,193 +7948,59 @@ function verificationGaps(planPath, opts, env = process.env) {
|
|
|
7167
7948
|
}
|
|
7168
7949
|
let unverifiedFindings = false;
|
|
7169
7950
|
let verify = null;
|
|
7170
|
-
if (opts.postsFindings) {
|
|
7171
|
-
const verifyKeys = [...built.keys()].filter(
|
|
7172
|
-
(k) => k === "verify" || k.startsWith("verify--")
|
|
7173
|
-
);
|
|
7174
|
-
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 {
|
|
7951
|
+
if (opts.postsFindings) {
|
|
7952
|
+
const verifyKeys = [...built.keys()].filter(
|
|
7953
|
+
(k) => k === "verify" || k.startsWith("verify--")
|
|
7954
|
+
);
|
|
7955
|
+
verify = bestDelivery(verifyKeys);
|
|
7956
|
+
if (verify !== "ok") {
|
|
7957
|
+
unverifiedFindings = true;
|
|
7958
|
+
remediation.push(
|
|
7959
|
+
`verification: ${VERIFY_GAP[verify].fix.replace(
|
|
7960
|
+
"--plan <plan>",
|
|
7961
|
+
// A function replacer: a plain string gives `$&`/`$\`` special
|
|
7962
|
+
// meaning, and a path is not a place for replacement patterns.
|
|
7963
|
+
() => `--plan ${shellQuotePath(planPath)}`
|
|
7964
|
+
)}`
|
|
7965
|
+
);
|
|
7331
7966
|
}
|
|
7332
7967
|
}
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7968
|
+
if (reverseGap && verify !== null && verify === reverse) {
|
|
7969
|
+
gaps.push({
|
|
7970
|
+
subject: "verification and reverse audit",
|
|
7971
|
+
reason: COMBINED_STEP45_GAP[reverse].en,
|
|
7972
|
+
subjectZh: "\u9A8C\u8BC1\u4E0E\u53CD\u5411\u5BA1\u8BA1",
|
|
7973
|
+
reasonZh: COMBINED_STEP45_GAP[reverse].zh
|
|
7974
|
+
});
|
|
7975
|
+
} else {
|
|
7976
|
+
if (reverseGap) {
|
|
7977
|
+
gaps.push({
|
|
7978
|
+
subject: "reverse audit",
|
|
7979
|
+
reason: REVERSE_AUDIT_GAP[reverse].gap,
|
|
7980
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7981
|
+
reasonZh: REVERSE_AUDIT_GAP[reverse].gapZh
|
|
7982
|
+
});
|
|
7983
|
+
}
|
|
7984
|
+
if (verify !== null && verify !== "ok") {
|
|
7985
|
+
gaps.push({
|
|
7986
|
+
subject: "verification",
|
|
7987
|
+
reason: VERIFY_GAP[verify].gap,
|
|
7988
|
+
subjectZh: "\u9A8C\u8BC1",
|
|
7989
|
+
reasonZh: VERIFY_GAP[verify].gapZh
|
|
7990
|
+
});
|
|
7353
7991
|
}
|
|
7354
7992
|
}
|
|
7993
|
+
if (balancedMedium) {
|
|
7994
|
+
gaps.push({
|
|
7995
|
+
subject: "reverse audit",
|
|
7996
|
+
reason: "not run \u2014 the balanced (medium) tier skips the second-look pass, so this verdict is capped at Comment rather than Approve",
|
|
7997
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7998
|
+
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"
|
|
7999
|
+
});
|
|
8000
|
+
}
|
|
8001
|
+
return { ok: gaps.length === 0, gaps, remediation, unverifiedFindings };
|
|
7355
8002
|
}
|
|
7356
|
-
__name(
|
|
8003
|
+
__name(verificationGaps, "verificationGaps");
|
|
7357
8004
|
|
|
7358
8005
|
// packages/cli/src/commands/review/lib/ledger.ts
|
|
7359
8006
|
init_esbuild_shims();
|
|
@@ -7529,16 +8176,16 @@ __name(composeReview, "composeReview");
|
|
|
7529
8176
|
function ledgerMarkerFor(input) {
|
|
7530
8177
|
try {
|
|
7531
8178
|
if (!input.planPath) return null;
|
|
7532
|
-
const plan = JSON.parse(
|
|
8179
|
+
const plan = JSON.parse(readFileSync10(input.planPath, "utf8"));
|
|
7533
8180
|
const pr = plan?.prNumber;
|
|
7534
8181
|
const isPr = typeof pr === "number" && Number.isInteger(pr) && pr > 0 || typeof pr === "string" && /^\d+$/.test(pr);
|
|
7535
8182
|
if (!isPr) return null;
|
|
7536
8183
|
let prevRound = 0;
|
|
7537
8184
|
try {
|
|
7538
8185
|
const prev = JSON.parse(
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
8186
|
+
readFileSync10(
|
|
8187
|
+
join10(
|
|
8188
|
+
dirname5(input.planPath),
|
|
7542
8189
|
`qwen-review-pr-${pr}-prev-ledger.json`
|
|
7543
8190
|
),
|
|
7544
8191
|
"utf8"
|
|
@@ -7598,6 +8245,8 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7598
8245
|
}
|
|
7599
8246
|
}
|
|
7600
8247
|
const remediation = [];
|
|
8248
|
+
const budgetGapNotes = [];
|
|
8249
|
+
const MAX_BUDGET_GAP_LINES = 5;
|
|
7601
8250
|
const planRef = input.planPath ? shellQuotePath(input.planPath) : "<plan>";
|
|
7602
8251
|
const missingReceipts = [];
|
|
7603
8252
|
let plannedChunks = [];
|
|
@@ -7676,6 +8325,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7676
8325
|
"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
8326
|
);
|
|
7678
8327
|
}
|
|
8328
|
+
budgetGapNotes.push(...cov.budgetGaps);
|
|
7679
8329
|
coverageEntries.push(...cov.disclosures);
|
|
7680
8330
|
if (cov.rewrittenPrompts.length > 0) {
|
|
7681
8331
|
remediation.push(
|
|
@@ -7740,7 +8390,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7740
8390
|
);
|
|
7741
8391
|
}
|
|
7742
8392
|
try {
|
|
7743
|
-
const findingsContent =
|
|
8393
|
+
const findingsContent = readFileSync10(findingsPath, "utf8");
|
|
7744
8394
|
unverifiedTagCount = (findingsContent.match(UNVERIFIED_FINDING_TAG_RE) ?? []).length;
|
|
7745
8395
|
findingsUnverifiedAtCompose = unverifiedTagCount > 0;
|
|
7746
8396
|
if (findingsUnverifiedAtCompose) {
|
|
@@ -7826,7 +8476,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7826
8476
|
if (event2 === "APPROVE" && input.planPath) {
|
|
7827
8477
|
let plan;
|
|
7828
8478
|
try {
|
|
7829
|
-
plan = JSON.parse(
|
|
8479
|
+
plan = JSON.parse(readFileSync10(input.planPath, "utf8"));
|
|
7830
8480
|
} catch {
|
|
7831
8481
|
}
|
|
7832
8482
|
if (plan) {
|
|
@@ -7838,10 +8488,10 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7838
8488
|
}
|
|
7839
8489
|
const footer = reviewFooter(modelId, cliVersion);
|
|
7840
8490
|
const bilingual = bilingualFromPlan(input.planPath, input.prBodyFetcher);
|
|
7841
|
-
const render = /* @__PURE__ */ __name((parts,
|
|
7842
|
-
const en = parts.map((p) => p.en).join(
|
|
8491
|
+
const render = /* @__PURE__ */ __name((parts, sep9) => {
|
|
8492
|
+
const en = parts.map((p) => p.en).join(sep9);
|
|
7843
8493
|
if (en === "") return "";
|
|
7844
|
-
const zh = parts.map((p) => p.zh).join(
|
|
8494
|
+
const zh = parts.map((p) => p.zh).join(sep9);
|
|
7845
8495
|
const text = bilingual && zh !== en ? `${en}
|
|
7846
8496
|
|
|
7847
8497
|
<details>
|
|
@@ -7913,6 +8563,23 @@ ${footer}`;
|
|
|
7913
8563
|
zh: `\u672A\u5BA1\u67E5\uFF1A${d}\u3002`
|
|
7914
8564
|
});
|
|
7915
8565
|
}
|
|
8566
|
+
const budgetGapItems = [];
|
|
8567
|
+
for (const g of budgetGapNotes) {
|
|
8568
|
+
for (const gap of g.gaps) budgetGapItems.push({ agent: g.agent, gap });
|
|
8569
|
+
}
|
|
8570
|
+
const keptBudgetGaps = budgetGapItems.filter(
|
|
8571
|
+
(it) => !unreviewed.some((d) => d.includes(it.gap))
|
|
8572
|
+
);
|
|
8573
|
+
if (keptBudgetGaps.length > 0) {
|
|
8574
|
+
const shown = keptBudgetGaps.slice(0, MAX_BUDGET_GAP_LINES);
|
|
8575
|
+
const more = keptBudgetGaps.length - shown.length;
|
|
8576
|
+
const enList = shown.map((it) => `${it.agent}: ${mdField(it.gap)}`).join("; ") + (more > 0 ? `, and ${more} more` : "");
|
|
8577
|
+
const zhList = shown.map((it) => `${it.agent}\uFF1A${mdField(it.gap)}`).join("\uFF1B") + (more > 0 ? `\uFF0C\u53E6\u6709 ${more} \u6761` : "");
|
|
8578
|
+
notReviewedParts.push({
|
|
8579
|
+
en: `Not explored to full depth (tool budget reached): ${enList}.`,
|
|
8580
|
+
zh: `\u672A\u63A2\u7D22\u5230\u5168\u90E8\u6DF1\u5EA6\uFF08\u8FBE\u5230\u5DE5\u5177\u8C03\u7528\u9884\u7B97\uFF09\uFF1A${zhList}\u3002`
|
|
8581
|
+
});
|
|
8582
|
+
}
|
|
7916
8583
|
const seenSubjects = /* @__PURE__ */ new Set();
|
|
7917
8584
|
const byReason = /* @__PURE__ */ new Map();
|
|
7918
8585
|
const reasonZhOf = /* @__PURE__ */ new Map();
|
|
@@ -8020,11 +8687,12 @@ ${footer}`;
|
|
|
8020
8687
|
body: render(
|
|
8021
8688
|
[
|
|
8022
8689
|
{ en: "No issues found. LGTM! \u2705", zh: "\u672A\u53D1\u73B0\u95EE\u9898\u3002LGTM\uFF01\u2705" },
|
|
8690
|
+
...notReviewedParts,
|
|
8023
8691
|
...deferredBlock,
|
|
8024
8692
|
...testPlanBlock,
|
|
8025
8693
|
...repositoryContextBlock2
|
|
8026
8694
|
],
|
|
8027
|
-
deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8695
|
+
notReviewedParts.length || deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8028
8696
|
),
|
|
8029
8697
|
baseEvent,
|
|
8030
8698
|
cappedBy,
|
|
@@ -8050,7 +8718,12 @@ ${footer}`;
|
|
|
8050
8718
|
// body could open "Reviewed — no blockers." two lines above "nobody read
|
|
8051
8719
|
// them." Nothing nobody read can be certified blocker-free — and neither
|
|
8052
8720
|
// can a loop that ended with findings no verifier ever ruled on.
|
|
8053
|
-
missingReceipts.length === 0 &&
|
|
8721
|
+
missingReceipts.length === 0 && // A disclosed budget gap is not a blocker, but "Reviewed — no
|
|
8722
|
+
// blockers." two lines above "Not explored to full depth" is the
|
|
8723
|
+
// opener certifying what the disclosure takes back — the exact
|
|
8724
|
+
// shape the comment below forbids. (A gap the caller promoted into
|
|
8725
|
+
// `unreviewedDimensions` already denies certification above.)
|
|
8726
|
+
keptBudgetGaps.length === 0 && !findingsUnverifiedAtCompose;
|
|
8054
8727
|
const disclosedChunkIds = /* @__PURE__ */ new Set();
|
|
8055
8728
|
for (const e of coverageEntries) {
|
|
8056
8729
|
const m = /^chunk (\d+)$/.exec(e.subject);
|
|
@@ -8139,7 +8812,7 @@ var fetchPrBodyViaGh = /* @__PURE__ */ __name((ownerRepo, prNumber) => {
|
|
|
8139
8812
|
function repositoryContextGate(planPath) {
|
|
8140
8813
|
let plan;
|
|
8141
8814
|
try {
|
|
8142
|
-
plan = JSON.parse(
|
|
8815
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8143
8816
|
} catch {
|
|
8144
8817
|
return [];
|
|
8145
8818
|
}
|
|
@@ -8161,7 +8834,7 @@ function scriptLintGate(planPath) {
|
|
|
8161
8834
|
const disclosed = [];
|
|
8162
8835
|
let plan;
|
|
8163
8836
|
try {
|
|
8164
|
-
plan = JSON.parse(
|
|
8837
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8165
8838
|
} catch {
|
|
8166
8839
|
unreviewed.push(
|
|
8167
8840
|
"the executable-script lint \u2014 could not read the plan to check the gate"
|
|
@@ -8172,13 +8845,13 @@ function scriptLintGate(planPath) {
|
|
|
8172
8845
|
return { criticals, unreviewed, disclosed };
|
|
8173
8846
|
}
|
|
8174
8847
|
const owed = hasExecutableScript(plan);
|
|
8175
|
-
const reportPath =
|
|
8176
|
-
|
|
8848
|
+
const reportPath = join10(
|
|
8849
|
+
dirname5(planPath),
|
|
8177
8850
|
scriptLintReportName(plan.prNumber)
|
|
8178
8851
|
);
|
|
8179
8852
|
let report;
|
|
8180
8853
|
try {
|
|
8181
|
-
report = JSON.parse(
|
|
8854
|
+
report = JSON.parse(readFileSync10(reportPath, "utf8"));
|
|
8182
8855
|
} catch {
|
|
8183
8856
|
if (owed) {
|
|
8184
8857
|
unreviewed.push(
|
|
@@ -8234,7 +8907,7 @@ function testPlanGate(planPath) {
|
|
|
8234
8907
|
const notes = [];
|
|
8235
8908
|
let plan;
|
|
8236
8909
|
try {
|
|
8237
|
-
plan = JSON.parse(
|
|
8910
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8238
8911
|
} catch {
|
|
8239
8912
|
return { notes };
|
|
8240
8913
|
}
|
|
@@ -8244,8 +8917,8 @@ function testPlanGate(planPath) {
|
|
|
8244
8917
|
let report;
|
|
8245
8918
|
try {
|
|
8246
8919
|
report = JSON.parse(
|
|
8247
|
-
|
|
8248
|
-
|
|
8920
|
+
readFileSync10(
|
|
8921
|
+
join10(dirname5(planPath), `qwen-review-pr-${pr}-test-plan.json`),
|
|
8249
8922
|
"utf8"
|
|
8250
8923
|
)
|
|
8251
8924
|
);
|
|
@@ -8278,7 +8951,7 @@ function bilingualFromPlan(planPath, fetchPrBody2 = fetchPrBodyViaGh) {
|
|
|
8278
8951
|
if (!planPath) return false;
|
|
8279
8952
|
let plan;
|
|
8280
8953
|
try {
|
|
8281
|
-
plan = JSON.parse(
|
|
8954
|
+
plan = JSON.parse(readFileSync10(planPath, "utf8"));
|
|
8282
8955
|
} catch {
|
|
8283
8956
|
return false;
|
|
8284
8957
|
}
|
|
@@ -8298,7 +8971,7 @@ __name(bilingualFromPlan, "bilingualFromPlan");
|
|
|
8298
8971
|
function readDraftedComments(path3) {
|
|
8299
8972
|
let raw;
|
|
8300
8973
|
try {
|
|
8301
|
-
raw =
|
|
8974
|
+
raw = readFileSync10(path3, "utf8");
|
|
8302
8975
|
} catch (err) {
|
|
8303
8976
|
throw new Error(
|
|
8304
8977
|
`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 +9025,7 @@ var composeReviewCommand = {
|
|
|
8352
9025
|
"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
9026
|
);
|
|
8354
9027
|
}
|
|
8355
|
-
const raw =
|
|
9028
|
+
const raw = readFileSync10(input ?? 0, "utf8");
|
|
8356
9029
|
const parsed = JSON.parse(raw);
|
|
8357
9030
|
delete parsed.env;
|
|
8358
9031
|
delete parsed.prBodyFetcher;
|
|
@@ -8379,7 +9052,7 @@ var composeReviewCommand = {
|
|
|
8379
9052
|
2
|
|
8380
9053
|
);
|
|
8381
9054
|
if (out) {
|
|
8382
|
-
mkdirSync6(
|
|
9055
|
+
mkdirSync6(dirname5(out), { recursive: true });
|
|
8383
9056
|
writeFileSync6(out, json, "utf8");
|
|
8384
9057
|
}
|
|
8385
9058
|
writeStdoutLine(json);
|
|
@@ -8482,8 +9155,8 @@ __name(verdictLine, "verdictLine");
|
|
|
8482
9155
|
|
|
8483
9156
|
// packages/cli/src/commands/review/findings.ts
|
|
8484
9157
|
init_esbuild_shims();
|
|
8485
|
-
import { existsSync as
|
|
8486
|
-
import { dirname as
|
|
9158
|
+
import { existsSync as existsSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
9159
|
+
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
8487
9160
|
var SEVERITIES = ["Critical", "Suggestion", "Nice to have"];
|
|
8488
9161
|
var CONFIDENCES = ["high", "low"];
|
|
8489
9162
|
var OUTCOMES = ["fixed", "skipped", "no_change_needed"];
|
|
@@ -8856,7 +9529,7 @@ __name(renderFindings, "renderFindings");
|
|
|
8856
9529
|
function readJson(path3, what) {
|
|
8857
9530
|
let text;
|
|
8858
9531
|
try {
|
|
8859
|
-
text =
|
|
9532
|
+
text = readFileSync11(resolve6(path3), "utf8");
|
|
8860
9533
|
} catch (err) {
|
|
8861
9534
|
throw new Error(
|
|
8862
9535
|
`Could not read the ${what} file at ${JSON.stringify(path3)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -8905,7 +9578,7 @@ var findingsCommand = {
|
|
|
8905
9578
|
let readjudicated = [];
|
|
8906
9579
|
if (testDelta !== void 0) {
|
|
8907
9580
|
let measurement;
|
|
8908
|
-
if (
|
|
9581
|
+
if (existsSync5(resolve6(testDelta))) {
|
|
8909
9582
|
try {
|
|
8910
9583
|
measurement = readJson(testDelta, "test-delta");
|
|
8911
9584
|
} catch (err) {
|
|
@@ -8926,8 +9599,8 @@ var findingsCommand = {
|
|
|
8926
9599
|
));
|
|
8927
9600
|
}
|
|
8928
9601
|
const report = buildReport(findings);
|
|
8929
|
-
const target =
|
|
8930
|
-
mkdirSync7(
|
|
9602
|
+
const target = resolve6(out);
|
|
9603
|
+
mkdirSync7(dirname6(target), { recursive: true });
|
|
8931
9604
|
writeFileSync7(target, `${JSON.stringify(report, null, 2)}
|
|
8932
9605
|
`, "utf8");
|
|
8933
9606
|
const { bySeverity, byConfidence } = report.counts;
|
|
@@ -8959,90 +9632,8 @@ var findingsCommand = {
|
|
|
8959
9632
|
// packages/cli/src/commands/review/fetch-pr.ts
|
|
8960
9633
|
init_esbuild_shims();
|
|
8961
9634
|
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");
|
|
9635
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
9636
|
+
import { dirname as dirname7, resolve as resolve7 } from "node:path";
|
|
9046
9637
|
|
|
9047
9638
|
// packages/cli/src/commands/review/lib/diff-flags.ts
|
|
9048
9639
|
init_esbuild_shims();
|
|
@@ -9067,11 +9658,11 @@ var LITERAL_PATHSPECS = "--literal-pathspecs";
|
|
|
9067
9658
|
|
|
9068
9659
|
// packages/cli/src/commands/review/lib/effort.ts
|
|
9069
9660
|
init_esbuild_shims();
|
|
9070
|
-
import { readFileSync as
|
|
9661
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
9071
9662
|
function resolveEffort(explicit) {
|
|
9072
9663
|
if (explicit && EFFORT_LEVELS.has(explicit)) return explicit;
|
|
9073
9664
|
try {
|
|
9074
|
-
const parsed = JSON.parse(
|
|
9665
|
+
const parsed = JSON.parse(readFileSync12(PARSE_ARGS_REPORT, "utf8"));
|
|
9075
9666
|
if (typeof parsed.effort === "string" && EFFORT_LEVELS.has(parsed.effort)) {
|
|
9076
9667
|
return parsed.effort;
|
|
9077
9668
|
}
|
|
@@ -9092,7 +9683,7 @@ __name(planEffortField, "planEffortField");
|
|
|
9092
9683
|
|
|
9093
9684
|
// packages/cli/src/commands/review/lib/report.ts
|
|
9094
9685
|
init_esbuild_shims();
|
|
9095
|
-
import { statSync as
|
|
9686
|
+
import { statSync as statSync6 } from "node:fs";
|
|
9096
9687
|
|
|
9097
9688
|
// packages/cli/src/commands/review/lib/heavy.ts
|
|
9098
9689
|
init_esbuild_shims();
|
|
@@ -9109,42 +9700,6 @@ function classifyHeavy(input) {
|
|
|
9109
9700
|
}
|
|
9110
9701
|
__name(classifyHeavy, "classifyHeavy");
|
|
9111
9702
|
|
|
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
9703
|
// packages/cli/src/commands/review/lib/report.ts
|
|
9149
9704
|
function buildPlanReport(plan, postImageLines) {
|
|
9150
9705
|
const files = plan.files.map((f) => {
|
|
@@ -9195,7 +9750,7 @@ __name(buildPlanReport, "buildPlanReport");
|
|
|
9195
9750
|
function warnOnReportSize(path3, cap) {
|
|
9196
9751
|
let size = 0;
|
|
9197
9752
|
try {
|
|
9198
|
-
size =
|
|
9753
|
+
size = statSync6(path3).size;
|
|
9199
9754
|
} catch {
|
|
9200
9755
|
return;
|
|
9201
9756
|
}
|
|
@@ -9318,7 +9873,7 @@ async function runFetchPr(args) {
|
|
|
9318
9873
|
);
|
|
9319
9874
|
}
|
|
9320
9875
|
try {
|
|
9321
|
-
mkdirSync8(
|
|
9876
|
+
mkdirSync8(dirname7(wt), { recursive: true });
|
|
9322
9877
|
git("worktree", "add", wt, ref);
|
|
9323
9878
|
} catch (err) {
|
|
9324
9879
|
tryRemove(
|
|
@@ -9355,7 +9910,7 @@ async function runFetchPr(args) {
|
|
|
9355
9910
|
writeFileSync8(diffRel, buf);
|
|
9356
9911
|
diffText = buf.toString("utf8");
|
|
9357
9912
|
diffPath = diffRel;
|
|
9358
|
-
diffPathAbsolute =
|
|
9913
|
+
diffPathAbsolute = resolve7(diffRel);
|
|
9359
9914
|
} catch (err) {
|
|
9360
9915
|
writeStderrLine(`Failed to capture diff: ${err.message}`);
|
|
9361
9916
|
}
|
|
@@ -9379,7 +9934,7 @@ async function runFetchPr(args) {
|
|
|
9379
9934
|
let auditSince = fetchedAt;
|
|
9380
9935
|
let prevRaw = null;
|
|
9381
9936
|
try {
|
|
9382
|
-
prevRaw =
|
|
9937
|
+
prevRaw = readFileSync13(out, "utf8");
|
|
9383
9938
|
} catch (err) {
|
|
9384
9939
|
const code = err.code;
|
|
9385
9940
|
if (code !== "ENOENT") {
|
|
@@ -9547,12 +10102,12 @@ var fetchPrCommand = {
|
|
|
9547
10102
|
// packages/cli/src/commands/review/capture-local.ts
|
|
9548
10103
|
init_esbuild_shims();
|
|
9549
10104
|
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
9550
|
-
import { dirname as
|
|
10105
|
+
import { dirname as dirname8, resolve as resolve9 } from "node:path";
|
|
9551
10106
|
|
|
9552
10107
|
// packages/cli/src/commands/review/lib/local-diff.ts
|
|
9553
10108
|
init_esbuild_shims();
|
|
9554
|
-
import { lstatSync as lstatSync2, statSync as
|
|
9555
|
-
import { join as
|
|
10109
|
+
import { lstatSync as lstatSync2, statSync as statSync7, realpathSync as realpathSync3 } from "node:fs";
|
|
10110
|
+
import { join as join11, relative as relative3, resolve as resolve8, isAbsolute as isAbsolute2, sep as sep3 } from "node:path";
|
|
9556
10111
|
var MAX_UNTRACKED_BYTES = 1e6;
|
|
9557
10112
|
var MAX_UNTRACKED_FILES = 500;
|
|
9558
10113
|
var MAX_UNTRACKED_TOTAL_BYTES = 1e7;
|
|
@@ -9573,7 +10128,7 @@ function describeUndiffable(abs, st) {
|
|
|
9573
10128
|
}
|
|
9574
10129
|
if (st.isSymbolicLink()) {
|
|
9575
10130
|
try {
|
|
9576
|
-
return
|
|
10131
|
+
return statSync7(abs).isDirectory() ? "is a symlink to a directory \u2014 git cannot diff it as a file" : null;
|
|
9577
10132
|
} catch {
|
|
9578
10133
|
return null;
|
|
9579
10134
|
}
|
|
@@ -9582,19 +10137,19 @@ function describeUndiffable(abs, st) {
|
|
|
9582
10137
|
}
|
|
9583
10138
|
__name(describeUndiffable, "describeUndiffable");
|
|
9584
10139
|
function toRepoPathspec(repoRoot, file) {
|
|
9585
|
-
let abs =
|
|
10140
|
+
let abs = resolve8(process.cwd(), file);
|
|
9586
10141
|
try {
|
|
9587
|
-
abs =
|
|
10142
|
+
abs = realpathSync3(abs);
|
|
9588
10143
|
} catch {
|
|
9589
10144
|
}
|
|
9590
|
-
const rel =
|
|
9591
|
-
const escapes = rel === "" || rel === ".." || rel.startsWith(".." +
|
|
10145
|
+
const rel = relative3(repoRoot, abs);
|
|
10146
|
+
const escapes = rel === "" || rel === ".." || rel.startsWith(".." + sep3) || isAbsolute2(rel);
|
|
9592
10147
|
if (escapes) {
|
|
9593
10148
|
throw new Error(
|
|
9594
10149
|
`--file ${file} resolves to ${abs}, which is outside the repository at ${repoRoot}.`
|
|
9595
10150
|
);
|
|
9596
10151
|
}
|
|
9597
|
-
return rel.split(
|
|
10152
|
+
return rel.split(sep3).join("/");
|
|
9598
10153
|
}
|
|
9599
10154
|
__name(toRepoPathspec, "toRepoPathspec");
|
|
9600
10155
|
function isBinarySection(section) {
|
|
@@ -9678,7 +10233,7 @@ function captureLocalDiff(opts) {
|
|
|
9678
10233
|
for (const path3 of candidates) {
|
|
9679
10234
|
let bytes;
|
|
9680
10235
|
try {
|
|
9681
|
-
const abs =
|
|
10236
|
+
const abs = join11(repoRoot, path3);
|
|
9682
10237
|
const st = lstatSync2(abs);
|
|
9683
10238
|
const kind = describeUndiffable(abs, st);
|
|
9684
10239
|
if (kind) {
|
|
@@ -9771,13 +10326,13 @@ function runCaptureLocal(args) {
|
|
|
9771
10326
|
});
|
|
9772
10327
|
const diffText = capture.diff.toString("utf8");
|
|
9773
10328
|
mkdirSync9(REVIEW_TMP_DIR, { recursive: true });
|
|
9774
|
-
mkdirSync9(
|
|
10329
|
+
mkdirSync9(dirname8(resolve9(out)), { recursive: true });
|
|
9775
10330
|
const diffPath = tmpFile(target, "diff.txt");
|
|
9776
10331
|
writeFileSync9(diffPath, capture.diff);
|
|
9777
10332
|
const plan = buildDiffPlan(diffText);
|
|
9778
10333
|
const result = {
|
|
9779
10334
|
diffPath,
|
|
9780
|
-
diffPathAbsolute:
|
|
10335
|
+
diffPathAbsolute: resolve9(diffPath),
|
|
9781
10336
|
// No ref to `git show` a pre-change file out of, so per-file line counts and
|
|
9782
10337
|
// heaviness are unavailable — same as `plan-diff`. Chunk coverage, which is
|
|
9783
10338
|
// what the topology needs, is not.
|
|
@@ -9844,13 +10399,13 @@ var captureLocalCommand = {
|
|
|
9844
10399
|
|
|
9845
10400
|
// packages/cli/src/commands/review/plan-diff.ts
|
|
9846
10401
|
init_esbuild_shims();
|
|
9847
|
-
import { readFileSync as
|
|
9848
|
-
import { resolve as
|
|
10402
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
10403
|
+
import { resolve as resolve10 } from "node:path";
|
|
9849
10404
|
function runPlanDiff(args) {
|
|
9850
10405
|
const { diff_path: diffPath, out } = args;
|
|
9851
10406
|
let diffText;
|
|
9852
10407
|
try {
|
|
9853
|
-
diffText =
|
|
10408
|
+
diffText = readFileSync14(diffPath, "utf8");
|
|
9854
10409
|
} catch (err) {
|
|
9855
10410
|
throw new Error(
|
|
9856
10411
|
`Cannot read diff file ${diffPath}: ${err.message}`
|
|
@@ -9864,7 +10419,7 @@ function runPlanDiff(args) {
|
|
|
9864
10419
|
const plan = buildDiffPlan(diffText, args.maxChunkLines);
|
|
9865
10420
|
const result = {
|
|
9866
10421
|
diffPath,
|
|
9867
|
-
diffPathAbsolute:
|
|
10422
|
+
diffPathAbsolute: resolve10(diffPath),
|
|
9868
10423
|
// The PR identity, when the caller resolved one. This is what lets the
|
|
9869
10424
|
// roster require Agent 0 on a lightweight cross-repo review — a diff-only
|
|
9870
10425
|
// plan without it cannot demand an agent nobody could build. Passed only
|
|
@@ -9925,18 +10480,18 @@ var planDiffCommand = {
|
|
|
9925
10480
|
// packages/cli/src/commands/review/repo-context.ts
|
|
9926
10481
|
init_esbuild_shims();
|
|
9927
10482
|
import {
|
|
9928
|
-
existsSync as
|
|
10483
|
+
existsSync as existsSync6,
|
|
9929
10484
|
mkdirSync as mkdirSync11,
|
|
9930
|
-
readFileSync as
|
|
9931
|
-
realpathSync as
|
|
9932
|
-
statSync as
|
|
10485
|
+
readFileSync as readFileSync15,
|
|
10486
|
+
realpathSync as realpathSync5,
|
|
10487
|
+
statSync as statSync9
|
|
9933
10488
|
} from "node:fs";
|
|
9934
|
-
import { dirname as
|
|
10489
|
+
import { dirname as dirname9, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve12, sep as sep5 } from "node:path";
|
|
9935
10490
|
|
|
9936
10491
|
// packages/cli/src/commands/review/lib/manifest-repository-context.ts
|
|
9937
10492
|
init_esbuild_shims();
|
|
9938
|
-
import { lstatSync as lstatSync3, readdirSync as
|
|
9939
|
-
import { isAbsolute as isAbsolute3, relative as
|
|
10493
|
+
import { lstatSync as lstatSync3, readdirSync as readdirSync5, realpathSync as realpathSync4, statSync as statSync8 } from "node:fs";
|
|
10494
|
+
import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve11, sep as sep4 } from "node:path";
|
|
9940
10495
|
var MANIFEST_PATH = ".qwen/review-context.json";
|
|
9941
10496
|
var MAX_GLOB_CANDIDATES = 16384;
|
|
9942
10497
|
var MAX_MATCH_WORK = 1024 * 1024 * 1024;
|
|
@@ -9945,12 +10500,15 @@ var MANIFEST_PREFIX = "repository context manifest ";
|
|
|
9945
10500
|
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
9946
10501
|
".git",
|
|
9947
10502
|
".next",
|
|
10503
|
+
".playwright",
|
|
9948
10504
|
".turbo",
|
|
9949
10505
|
"coverage",
|
|
9950
10506
|
"dist",
|
|
9951
10507
|
"node_modules",
|
|
9952
10508
|
"out",
|
|
9953
|
-
"
|
|
10509
|
+
"playwright-report",
|
|
10510
|
+
"target",
|
|
10511
|
+
"test-results"
|
|
9954
10512
|
]);
|
|
9955
10513
|
var MANIFEST_KEYS = ["label", "rules", "version"].sort();
|
|
9956
10514
|
var RULE_KEYS = [
|
|
@@ -10156,9 +10714,9 @@ function globMatches(pattern, path3) {
|
|
|
10156
10714
|
__name(globMatches, "globMatches");
|
|
10157
10715
|
function isContainedFile(worktree, path3) {
|
|
10158
10716
|
try {
|
|
10159
|
-
const resolved =
|
|
10160
|
-
const contained =
|
|
10161
|
-
return contained !== "" && !isAbsolute3(contained) && contained !== ".." && !contained.startsWith(`..${
|
|
10717
|
+
const resolved = realpathSync4(resolve11(worktree, path3));
|
|
10718
|
+
const contained = relative4(worktree, resolved);
|
|
10719
|
+
return contained !== "" && !isAbsolute3(contained) && contained !== ".." && !contained.startsWith(`..${sep4}`) && statSync8(resolved).isFile();
|
|
10162
10720
|
} catch {
|
|
10163
10721
|
return false;
|
|
10164
10722
|
}
|
|
@@ -10202,7 +10760,7 @@ function expandRelatedPaths(worktree, patterns, changedPaths2) {
|
|
|
10202
10760
|
const visit = /* @__PURE__ */ __name((directory) => {
|
|
10203
10761
|
let entries;
|
|
10204
10762
|
try {
|
|
10205
|
-
const stat = lstatSync3(
|
|
10763
|
+
const stat = lstatSync3(resolve11(worktree, directory));
|
|
10206
10764
|
if (stat.isSymbolicLink()) return;
|
|
10207
10765
|
if (!stat.isDirectory()) {
|
|
10208
10766
|
candidates++;
|
|
@@ -10222,7 +10780,7 @@ function expandRelatedPaths(worktree, patterns, changedPaths2) {
|
|
|
10222
10780
|
}
|
|
10223
10781
|
return;
|
|
10224
10782
|
}
|
|
10225
|
-
entries =
|
|
10783
|
+
entries = readdirSync5(resolve11(worktree, directory), {
|
|
10226
10784
|
withFileTypes: true
|
|
10227
10785
|
});
|
|
10228
10786
|
if (candidates + entries.length > MAX_GLOB_CANDIDATES) {
|
|
@@ -10345,24 +10903,24 @@ var manifestRepositoryContextProvider = {
|
|
|
10345
10903
|
var REPOSITORY_CONTEXT_PROVIDERS = [manifestRepositoryContextProvider];
|
|
10346
10904
|
function sameFile(left, right) {
|
|
10347
10905
|
if (left === right) return true;
|
|
10348
|
-
if (!
|
|
10349
|
-
const leftStat =
|
|
10350
|
-
const rightStat =
|
|
10906
|
+
if (!existsSync6(left) || !existsSync6(right)) return false;
|
|
10907
|
+
const leftStat = statSync9(left);
|
|
10908
|
+
const rightStat = statSync9(right);
|
|
10351
10909
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
10352
10910
|
}
|
|
10353
10911
|
__name(sameFile, "sameFile");
|
|
10354
10912
|
function recordedWorktreeMatches(recordedPath, worktree) {
|
|
10355
|
-
const candidates = [
|
|
10913
|
+
const candidates = [resolve12(recordedPath)];
|
|
10356
10914
|
if (!isAbsolute4(recordedPath)) {
|
|
10357
10915
|
const commonDir = gitOpt("-C", worktree, "rev-parse", "--git-common-dir");
|
|
10358
10916
|
if (commonDir !== null) {
|
|
10359
10917
|
candidates.push(
|
|
10360
|
-
|
|
10918
|
+
resolve12(dirname9(resolve12(worktree, commonDir)), recordedPath)
|
|
10361
10919
|
);
|
|
10362
10920
|
}
|
|
10363
10921
|
}
|
|
10364
10922
|
return candidates.some(
|
|
10365
|
-
(candidate) =>
|
|
10923
|
+
(candidate) => existsSync6(candidate) && realpathSync5(candidate) === worktree
|
|
10366
10924
|
);
|
|
10367
10925
|
}
|
|
10368
10926
|
__name(recordedWorktreeMatches, "recordedWorktreeMatches");
|
|
@@ -10416,7 +10974,7 @@ function readBaseBlob(worktree, mergeBase, path3) {
|
|
|
10416
10974
|
__name(readBaseBlob, "readBaseBlob");
|
|
10417
10975
|
function resolveTreeSymlinkTarget(fromPath, target) {
|
|
10418
10976
|
if (target.startsWith("/") || /^[A-Za-z]:/.test(target)) return null;
|
|
10419
|
-
const segments = `${
|
|
10977
|
+
const segments = `${dirname9(fromPath)}/${target}`.split("/");
|
|
10420
10978
|
const resolved = [];
|
|
10421
10979
|
for (const segment of segments) {
|
|
10422
10980
|
if (segment === "" || segment === ".") continue;
|
|
@@ -10472,29 +11030,29 @@ function identityReader(worktree, mergeBase) {
|
|
|
10472
11030
|
if (mergeBase !== null) {
|
|
10473
11031
|
return readBaseIdentity(worktree, mergeBase, relativePath);
|
|
10474
11032
|
}
|
|
10475
|
-
const candidate =
|
|
11033
|
+
const candidate = resolve12(worktree, relativePath);
|
|
10476
11034
|
let resolved;
|
|
10477
11035
|
try {
|
|
10478
|
-
resolved =
|
|
11036
|
+
resolved = realpathSync5(candidate);
|
|
10479
11037
|
} catch (error) {
|
|
10480
11038
|
if (isAbsentError(error)) return null;
|
|
10481
11039
|
throw error;
|
|
10482
11040
|
}
|
|
10483
|
-
const contained =
|
|
10484
|
-
if (isAbsolute4(contained) || contained === ".." || contained.startsWith(`..${
|
|
11041
|
+
const contained = relative5(worktree, resolved);
|
|
11042
|
+
if (isAbsolute4(contained) || contained === ".." || contained.startsWith(`..${sep5}`)) {
|
|
10485
11043
|
throw new Error(
|
|
10486
11044
|
`repo-context: identity path escapes the worktree: ${JSON.stringify(relativePath)}`
|
|
10487
11045
|
);
|
|
10488
11046
|
}
|
|
10489
11047
|
try {
|
|
10490
|
-
const stat =
|
|
11048
|
+
const stat = statSync9(resolved);
|
|
10491
11049
|
if (!stat.isFile()) return null;
|
|
10492
11050
|
if (stat.size > MAX_IDENTITY_BYTES) {
|
|
10493
11051
|
throw new Error(
|
|
10494
11052
|
`repo-context: identity read exceeds the size limit: ${JSON.stringify(relativePath)}`
|
|
10495
11053
|
);
|
|
10496
11054
|
}
|
|
10497
|
-
return normalizeIdentityContent(
|
|
11055
|
+
return normalizeIdentityContent(readFileSync15(resolved, "utf8"));
|
|
10498
11056
|
} catch (error) {
|
|
10499
11057
|
if (isAbsentError(error)) return null;
|
|
10500
11058
|
throw error;
|
|
@@ -10505,7 +11063,7 @@ __name(identityReader, "identityReader");
|
|
|
10505
11063
|
function readPlan2(path3) {
|
|
10506
11064
|
let value;
|
|
10507
11065
|
try {
|
|
10508
|
-
value = JSON.parse(
|
|
11066
|
+
value = JSON.parse(readFileSync15(path3, "utf8"));
|
|
10509
11067
|
} catch (error) {
|
|
10510
11068
|
throw new Error(`Cannot read plan ${path3}: ${error.message}`);
|
|
10511
11069
|
}
|
|
@@ -10543,13 +11101,13 @@ function contextFromProviders(providers, worktree, paths, readIdentityFile) {
|
|
|
10543
11101
|
}
|
|
10544
11102
|
__name(contextFromProviders, "contextFromProviders");
|
|
10545
11103
|
function runRepoContext(args, providers = REPOSITORY_CONTEXT_PROVIDERS) {
|
|
10546
|
-
const planPath =
|
|
10547
|
-
const outPath =
|
|
11104
|
+
const planPath = resolve12(args.plan);
|
|
11105
|
+
const outPath = resolve12(args.out);
|
|
10548
11106
|
if (sameFile(planPath, outPath)) {
|
|
10549
11107
|
throw new Error("repo-context: --out must differ from --plan");
|
|
10550
11108
|
}
|
|
10551
|
-
const worktree =
|
|
10552
|
-
if (!
|
|
11109
|
+
const worktree = realpathSync5(resolve12(args.worktree));
|
|
11110
|
+
if (!statSync9(worktree).isDirectory()) {
|
|
10553
11111
|
throw new Error(`repo-context: worktree is not a directory: ${worktree}`);
|
|
10554
11112
|
}
|
|
10555
11113
|
const plan = readPlan2(planPath);
|
|
@@ -10575,7 +11133,7 @@ function runRepoContext(args, providers = REPOSITORY_CONTEXT_PROVIDERS) {
|
|
|
10575
11133
|
);
|
|
10576
11134
|
if (context === null) delete plan.repositoryContext;
|
|
10577
11135
|
else plan.repositoryContext = context;
|
|
10578
|
-
mkdirSync11(
|
|
11136
|
+
mkdirSync11(dirname9(outPath), { recursive: true });
|
|
10579
11137
|
atomicWriteFileSync(outPath, `${JSON.stringify(context, null, 2)}
|
|
10580
11138
|
`);
|
|
10581
11139
|
atomicWriteFileSync(planPath, stringifyPlanReport(plan));
|
|
@@ -10608,7 +11166,7 @@ var repoContextCommand = {
|
|
|
10608
11166
|
// packages/cli/src/commands/review/pr-context.ts
|
|
10609
11167
|
init_esbuild_shims();
|
|
10610
11168
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10611
|
-
import { dirname as
|
|
11169
|
+
import { dirname as dirname10, join as join12 } from "node:path";
|
|
10612
11170
|
var SUMMARY_MARKER = "<!-- qwen-review-suggestion-summary -->";
|
|
10613
11171
|
function isLegacySuggestionSummary(body) {
|
|
10614
11172
|
return (body ?? "").includes(SUMMARY_MARKER);
|
|
@@ -11086,9 +11644,9 @@ async function runPrContext(args) {
|
|
|
11086
11644
|
}
|
|
11087
11645
|
if (prevLedger) {
|
|
11088
11646
|
try {
|
|
11089
|
-
mkdirSync12(
|
|
11647
|
+
mkdirSync12(dirname10(out), { recursive: true });
|
|
11090
11648
|
writeFileSync11(
|
|
11091
|
-
|
|
11649
|
+
join12(dirname10(out), `qwen-review-pr-${prNumber}-prev-ledger.json`),
|
|
11092
11650
|
JSON.stringify(prevLedger, null, 2)
|
|
11093
11651
|
);
|
|
11094
11652
|
} catch {
|
|
@@ -11103,7 +11661,7 @@ async function runPrContext(args) {
|
|
|
11103
11661
|
reviews,
|
|
11104
11662
|
prevLedger
|
|
11105
11663
|
);
|
|
11106
|
-
mkdirSync12(
|
|
11664
|
+
mkdirSync12(dirname10(out), { recursive: true });
|
|
11107
11665
|
writeFileSync11(out, md, "utf8");
|
|
11108
11666
|
const meaningfulReviewCount = reviews.filter(
|
|
11109
11667
|
(r) => isReviewWorthShowing(stripLedgerMarker(r.body ?? ""))
|
|
@@ -11159,7 +11717,7 @@ var prContextCommand = {
|
|
|
11159
11717
|
// packages/cli/src/commands/review/comment-status.ts
|
|
11160
11718
|
init_esbuild_shims();
|
|
11161
11719
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12 } from "node:fs";
|
|
11162
|
-
import { dirname as
|
|
11720
|
+
import { dirname as dirname11 } from "node:path";
|
|
11163
11721
|
var TOUCHED_BY_CAP = 10;
|
|
11164
11722
|
function buildThreadStatuses(comments, prAuthor, probe) {
|
|
11165
11723
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -11364,7 +11922,7 @@ async function runCommentStatus(args) {
|
|
|
11364
11922
|
summary,
|
|
11365
11923
|
threads
|
|
11366
11924
|
};
|
|
11367
|
-
mkdirSync13(
|
|
11925
|
+
mkdirSync13(dirname11(out), { recursive: true });
|
|
11368
11926
|
const json = JSON.stringify(report, null, 2) + "\n";
|
|
11369
11927
|
writeFileSync12(out, json, "utf8");
|
|
11370
11928
|
writeStdoutLine(
|
|
@@ -11394,7 +11952,7 @@ async function runCommentStatus(args) {
|
|
|
11394
11952
|
writeStdoutLine(
|
|
11395
11953
|
`warning: comment-status failed: ${msg}. It is an index, not the evidence \u2014 re-derive thread statuses per-comment if needed.`
|
|
11396
11954
|
);
|
|
11397
|
-
mkdirSync13(
|
|
11955
|
+
mkdirSync13(dirname11(out), { recursive: true });
|
|
11398
11956
|
writeFileSync12(
|
|
11399
11957
|
out,
|
|
11400
11958
|
JSON.stringify(
|
|
@@ -11458,7 +12016,7 @@ var commentStatusCommand = {
|
|
|
11458
12016
|
// packages/cli/src/commands/review/load-rules.ts
|
|
11459
12017
|
init_esbuild_shims();
|
|
11460
12018
|
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13 } from "node:fs";
|
|
11461
|
-
import { dirname as
|
|
12019
|
+
import { dirname as dirname12 } from "node:path";
|
|
11462
12020
|
function showFile(baseRef, path3) {
|
|
11463
12021
|
return gitOpt("show", `${baseRef}:${path3}`);
|
|
11464
12022
|
}
|
|
@@ -11538,7 +12096,7 @@ __name(loadCombined, "loadCombined");
|
|
|
11538
12096
|
async function runLoadRules(args) {
|
|
11539
12097
|
const { base_ref: baseRef, out } = args;
|
|
11540
12098
|
const { combined, loaded } = loadCombined(baseRef);
|
|
11541
|
-
mkdirSync14(
|
|
12099
|
+
mkdirSync14(dirname12(out), { recursive: true });
|
|
11542
12100
|
writeFileSync13(out, combined, "utf8");
|
|
11543
12101
|
if (loaded.length === 0) {
|
|
11544
12102
|
writeStdoutLine(
|
|
@@ -11570,7 +12128,7 @@ var loadRulesCommand = {
|
|
|
11570
12128
|
|
|
11571
12129
|
// packages/cli/src/commands/review/presubmit.ts
|
|
11572
12130
|
init_esbuild_shims();
|
|
11573
|
-
import { writeFileSync as writeFileSync14, readFileSync as
|
|
12131
|
+
import { writeFileSync as writeFileSync14, readFileSync as readFileSync16 } from "node:fs";
|
|
11574
12132
|
function verdictStamp(run4) {
|
|
11575
12133
|
return run4.completed_at ?? run4.started_at ?? "";
|
|
11576
12134
|
}
|
|
@@ -11606,7 +12164,7 @@ __name(isCurrentActionsRunCheck, "isCurrentActionsRunCheck");
|
|
|
11606
12164
|
function parseFindingsFile(path3) {
|
|
11607
12165
|
let parsed;
|
|
11608
12166
|
try {
|
|
11609
|
-
parsed = JSON.parse(
|
|
12167
|
+
parsed = JSON.parse(readFileSync16(path3, "utf8"));
|
|
11610
12168
|
} catch {
|
|
11611
12169
|
return null;
|
|
11612
12170
|
}
|
|
@@ -11947,13 +12505,13 @@ var presubmitCommand = {
|
|
|
11947
12505
|
|
|
11948
12506
|
// packages/cli/src/commands/review/publish-assets.ts
|
|
11949
12507
|
init_esbuild_shims();
|
|
11950
|
-
import { createHash as
|
|
11951
|
-
import { readFileSync as
|
|
11952
|
-
import { basename as
|
|
12508
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
12509
|
+
import { readFileSync as readFileSync18, statSync as statSync10, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "node:fs";
|
|
12510
|
+
import { basename as basename6, dirname as dirname13, resolve as resolve13 } from "node:path";
|
|
11953
12511
|
|
|
11954
12512
|
// packages/cli/src/commands/review/lib/authorization.ts
|
|
11955
12513
|
init_esbuild_shims();
|
|
11956
|
-
import { readFileSync as
|
|
12514
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
11957
12515
|
|
|
11958
12516
|
// packages/cli/src/services/skill-args-file.ts
|
|
11959
12517
|
init_esbuild_shims();
|
|
@@ -11964,12 +12522,12 @@ import {
|
|
|
11964
12522
|
closeSync as closeSync2,
|
|
11965
12523
|
rmSync as rmSync4,
|
|
11966
12524
|
lstatSync as lstatSync4,
|
|
11967
|
-
existsSync as
|
|
12525
|
+
existsSync as existsSync7,
|
|
11968
12526
|
constants
|
|
11969
12527
|
} from "node:fs";
|
|
11970
|
-
import { join as
|
|
12528
|
+
import { join as join13 } from "node:path";
|
|
11971
12529
|
var debugLogger3 = createDebugLogger("SKILL_ARGS_FILE");
|
|
11972
|
-
var SKILL_ARGS_DIR =
|
|
12530
|
+
var SKILL_ARGS_DIR = join13(".qwen", "tmp");
|
|
11973
12531
|
function safe(s) {
|
|
11974
12532
|
return s.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
11975
12533
|
}
|
|
@@ -11979,11 +12537,11 @@ function currentSessionId() {
|
|
|
11979
12537
|
}
|
|
11980
12538
|
__name(currentSessionId, "currentSessionId");
|
|
11981
12539
|
function skillArgsDir(sessionId = currentSessionId()) {
|
|
11982
|
-
return sessionId ?
|
|
12540
|
+
return sessionId ? join13(SKILL_ARGS_DIR, `s-${safe(sessionId)}`) : SKILL_ARGS_DIR;
|
|
11983
12541
|
}
|
|
11984
12542
|
__name(skillArgsDir, "skillArgsDir");
|
|
11985
12543
|
function skillArgsPath(skillName, sessionId = currentSessionId()) {
|
|
11986
|
-
return
|
|
12544
|
+
return join13(
|
|
11987
12545
|
skillArgsDir(sessionId),
|
|
11988
12546
|
`qwen-skill-args-${safe(skillName)}.txt`
|
|
11989
12547
|
);
|
|
@@ -12039,7 +12597,7 @@ function clearSkillArgs(skillName) {
|
|
|
12039
12597
|
);
|
|
12040
12598
|
return false;
|
|
12041
12599
|
}
|
|
12042
|
-
if (
|
|
12600
|
+
if (existsSync7(path3)) {
|
|
12043
12601
|
debugLogger3.warn(`Skill args for ${skillName} survived removal at ${path3}`);
|
|
12044
12602
|
return false;
|
|
12045
12603
|
}
|
|
@@ -12076,7 +12634,7 @@ function reviewWriteAuthorization(req) {
|
|
|
12076
12634
|
const path3 = currentSessionId() === "" && req.skillArgs ? req.skillArgs : sessionScoped;
|
|
12077
12635
|
let raw;
|
|
12078
12636
|
try {
|
|
12079
|
-
raw =
|
|
12637
|
+
raw = readFileSync17(path3, "utf8");
|
|
12080
12638
|
} catch {
|
|
12081
12639
|
return {
|
|
12082
12640
|
ok: false,
|
|
@@ -12139,8 +12697,8 @@ var EXTENSION_FORMAT = {
|
|
|
12139
12697
|
webp: "webp"
|
|
12140
12698
|
};
|
|
12141
12699
|
var ASSET_EXTENSIONS = new Set(Object.keys(EXTENSION_FORMAT));
|
|
12142
|
-
function claimedExtension(
|
|
12143
|
-
return
|
|
12700
|
+
function claimedExtension(basename7) {
|
|
12701
|
+
return basename7.includes(".") ? basename7.slice(basename7.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
12144
12702
|
}
|
|
12145
12703
|
__name(claimedExtension, "claimedExtension");
|
|
12146
12704
|
var ASSET_HEADER_BYTES = 16;
|
|
@@ -12166,18 +12724,18 @@ function sniffImageFormat(header) {
|
|
|
12166
12724
|
return null;
|
|
12167
12725
|
}
|
|
12168
12726
|
__name(sniffImageFormat, "sniffImageFormat");
|
|
12169
|
-
function refusedExtension(
|
|
12727
|
+
function refusedExtension(basename7, ext) {
|
|
12170
12728
|
return {
|
|
12171
12729
|
ok: false,
|
|
12172
|
-
reason: `${
|
|
12730
|
+
reason: `${basename7}: extension ${JSON.stringify(ext)} is not an allowed evidence image type (${[...ASSET_EXTENSIONS].join(", ")})`
|
|
12173
12731
|
};
|
|
12174
12732
|
}
|
|
12175
12733
|
__name(refusedExtension, "refusedExtension");
|
|
12176
|
-
function validateAssetContent(
|
|
12177
|
-
const ext = claimedExtension(
|
|
12734
|
+
function validateAssetContent(basename7, header) {
|
|
12735
|
+
const ext = claimedExtension(basename7);
|
|
12178
12736
|
const claimed = Object.hasOwn(EXTENSION_FORMAT, ext) ? EXTENSION_FORMAT[ext] : void 0;
|
|
12179
12737
|
if (claimed === void 0) {
|
|
12180
|
-
return refusedExtension(
|
|
12738
|
+
return refusedExtension(basename7, ext);
|
|
12181
12739
|
}
|
|
12182
12740
|
const actual = sniffImageFormat(header);
|
|
12183
12741
|
if (actual !== claimed) {
|
|
@@ -12195,8 +12753,8 @@ function assetsBranch(pr) {
|
|
|
12195
12753
|
return `pr-assets/${pr}-review`;
|
|
12196
12754
|
}
|
|
12197
12755
|
__name(assetsBranch, "assetsBranch");
|
|
12198
|
-
function remoteAssetPath(pr,
|
|
12199
|
-
const safe2 =
|
|
12756
|
+
function remoteAssetPath(pr, basename7, sha256Hex) {
|
|
12757
|
+
const safe2 = basename7.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
12200
12758
|
return `${pr}-review/${sha256Hex.slice(0, 12)}-${safe2}`;
|
|
12201
12759
|
}
|
|
12202
12760
|
__name(remoteAssetPath, "remoteAssetPath");
|
|
@@ -12222,18 +12780,18 @@ function parseAssetsRepo(value) {
|
|
|
12222
12780
|
return { repo: v };
|
|
12223
12781
|
}
|
|
12224
12782
|
__name(parseAssetsRepo, "parseAssetsRepo");
|
|
12225
|
-
function validateAssetFile(
|
|
12226
|
-
const ext = claimedExtension(
|
|
12783
|
+
function validateAssetFile(basename7, bytes) {
|
|
12784
|
+
const ext = claimedExtension(basename7);
|
|
12227
12785
|
if (!ASSET_EXTENSIONS.has(ext)) {
|
|
12228
|
-
return refusedExtension(
|
|
12786
|
+
return refusedExtension(basename7, ext);
|
|
12229
12787
|
}
|
|
12230
12788
|
if (bytes <= 0) {
|
|
12231
|
-
return { ok: false, reason: `${
|
|
12789
|
+
return { ok: false, reason: `${basename7}: empty file` };
|
|
12232
12790
|
}
|
|
12233
12791
|
if (bytes > MAX_ASSET_BYTES) {
|
|
12234
12792
|
return {
|
|
12235
12793
|
ok: false,
|
|
12236
|
-
reason: `${
|
|
12794
|
+
reason: `${basename7}: ${bytes} bytes exceeds the per-file cap of ${MAX_ASSET_BYTES} bytes`
|
|
12237
12795
|
};
|
|
12238
12796
|
}
|
|
12239
12797
|
return { ok: true };
|
|
@@ -12363,7 +12921,7 @@ function runPublishAssets(args) {
|
|
|
12363
12921
|
return;
|
|
12364
12922
|
}
|
|
12365
12923
|
const repo = repoResult.repo;
|
|
12366
|
-
const effectiveHost = args.host
|
|
12924
|
+
const effectiveHost = resolveGhHost(args.host);
|
|
12367
12925
|
const auth = reviewWriteAuthorization({
|
|
12368
12926
|
userAuthorized: args.userAuthorized,
|
|
12369
12927
|
skillArgs: args.skillArgs,
|
|
@@ -12396,7 +12954,7 @@ function runPublishAssets(args) {
|
|
|
12396
12954
|
const fileList = [...args.files ?? []];
|
|
12397
12955
|
if (args.findings) {
|
|
12398
12956
|
try {
|
|
12399
|
-
const artifact = JSON.parse(
|
|
12957
|
+
const artifact = JSON.parse(readFileSync18(resolve13(args.findings), "utf8"));
|
|
12400
12958
|
findings = validateFindings(
|
|
12401
12959
|
Array.isArray(artifact) ? artifact : artifact.findings
|
|
12402
12960
|
);
|
|
@@ -12424,11 +12982,11 @@ function runPublishAssets(args) {
|
|
|
12424
12982
|
}
|
|
12425
12983
|
const stats = [];
|
|
12426
12984
|
for (const file of unique) {
|
|
12427
|
-
const abs =
|
|
12985
|
+
const abs = resolve13(file);
|
|
12428
12986
|
try {
|
|
12429
|
-
const st =
|
|
12987
|
+
const st = statSync10(abs);
|
|
12430
12988
|
if (!st.isFile()) throw new Error("not a regular file");
|
|
12431
|
-
stats.push({ file, abs, basename:
|
|
12989
|
+
stats.push({ file, abs, basename: basename6(abs), bytes: st.size });
|
|
12432
12990
|
} catch (err) {
|
|
12433
12991
|
refuse(
|
|
12434
12992
|
`cannot read ${JSON.stringify(file)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -12445,7 +13003,7 @@ function runPublishAssets(args) {
|
|
|
12445
13003
|
for (const st of stats) {
|
|
12446
13004
|
let content;
|
|
12447
13005
|
try {
|
|
12448
|
-
content =
|
|
13006
|
+
content = readFileSync18(st.abs);
|
|
12449
13007
|
} catch (err) {
|
|
12450
13008
|
refuse(
|
|
12451
13009
|
`cannot read ${JSON.stringify(st.file)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -12460,7 +13018,7 @@ function runPublishAssets(args) {
|
|
|
12460
13018
|
refuse(`${JSON.stringify(st.file)}: ${contentRuling.reason}`);
|
|
12461
13019
|
return;
|
|
12462
13020
|
}
|
|
12463
|
-
const sha256 =
|
|
13021
|
+
const sha256 = createHash3("sha256").update(content).digest("hex");
|
|
12464
13022
|
prepared.push({
|
|
12465
13023
|
file: st.file,
|
|
12466
13024
|
bytes: st.bytes,
|
|
@@ -12499,8 +13057,8 @@ function runPublishAssets(args) {
|
|
|
12499
13057
|
pr: args.pr,
|
|
12500
13058
|
published
|
|
12501
13059
|
};
|
|
12502
|
-
const outPath =
|
|
12503
|
-
mkdirSync16(
|
|
13060
|
+
const outPath = resolve13(args.out);
|
|
13061
|
+
mkdirSync16(dirname13(outPath), { recursive: true });
|
|
12504
13062
|
writeFileSync15(outPath, `${JSON.stringify(manifest, null, 2)}
|
|
12505
13063
|
`, "utf8");
|
|
12506
13064
|
if (findings && !args.findingsOut) {
|
|
@@ -12515,8 +13073,8 @@ function runPublishAssets(args) {
|
|
|
12515
13073
|
return urls.length > 0 ? { ...f, assets: urls } : f;
|
|
12516
13074
|
});
|
|
12517
13075
|
const report = buildReport(updated);
|
|
12518
|
-
const fOut =
|
|
12519
|
-
mkdirSync16(
|
|
13076
|
+
const fOut = resolve13(args.findingsOut);
|
|
13077
|
+
mkdirSync16(dirname13(fOut), { recursive: true });
|
|
12520
13078
|
writeFileSync15(fOut, `${JSON.stringify(report, null, 2)}
|
|
12521
13079
|
`, "utf8");
|
|
12522
13080
|
}
|
|
@@ -12579,8 +13137,8 @@ var publishAssetsCommand = {
|
|
|
12579
13137
|
|
|
12580
13138
|
// packages/cli/src/commands/review/resolve-anchors.ts
|
|
12581
13139
|
init_esbuild_shims();
|
|
12582
|
-
import { readFileSync as
|
|
12583
|
-
import { dirname as
|
|
13140
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17 } from "node:fs";
|
|
13141
|
+
import { dirname as dirname14, resolve as resolve14 } from "node:path";
|
|
12584
13142
|
|
|
12585
13143
|
// packages/cli/src/commands/review/lib/anchors.ts
|
|
12586
13144
|
init_esbuild_shims();
|
|
@@ -12804,7 +13362,7 @@ __name(validateRequests, "validateRequests");
|
|
|
12804
13362
|
function runResolveAnchors(args) {
|
|
12805
13363
|
let diffText;
|
|
12806
13364
|
try {
|
|
12807
|
-
diffText =
|
|
13365
|
+
diffText = readFileSync19(args.diff, "utf8");
|
|
12808
13366
|
} catch (err) {
|
|
12809
13367
|
throw new Error(
|
|
12810
13368
|
`Cannot read diff file ${args.diff}: ${err.message}`
|
|
@@ -12812,7 +13370,7 @@ function runResolveAnchors(args) {
|
|
|
12812
13370
|
}
|
|
12813
13371
|
let rawText;
|
|
12814
13372
|
try {
|
|
12815
|
-
rawText =
|
|
13373
|
+
rawText = readFileSync19(args.input, "utf8");
|
|
12816
13374
|
} catch (err) {
|
|
12817
13375
|
throw new Error(
|
|
12818
13376
|
`Cannot read findings file ${args.input}: ${err.message}`
|
|
@@ -12843,7 +13401,7 @@ function runResolveAnchors(args) {
|
|
|
12843
13401
|
loose: resolved.filter((r) => r.tier?.startsWith("loose")).length
|
|
12844
13402
|
}
|
|
12845
13403
|
};
|
|
12846
|
-
mkdirSync17(
|
|
13404
|
+
mkdirSync17(dirname14(resolve14(args.out)), { recursive: true });
|
|
12847
13405
|
writeFileSync16(args.out, JSON.stringify(report, null, 2), "utf8");
|
|
12848
13406
|
writeStdoutLine(`Wrote resolved anchors to ${args.out}`);
|
|
12849
13407
|
const s = report.stats;
|
|
@@ -12892,7 +13450,7 @@ var resolveAnchorsCommand = {
|
|
|
12892
13450
|
// packages/cli/src/commands/review/check-coverage.ts
|
|
12893
13451
|
init_esbuild_shims();
|
|
12894
13452
|
import { writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "node:fs";
|
|
12895
|
-
import { dirname as
|
|
13453
|
+
import { dirname as dirname15, resolve as resolve15 } from "node:path";
|
|
12896
13454
|
function runCheckCoverage(args) {
|
|
12897
13455
|
let report;
|
|
12898
13456
|
try {
|
|
@@ -12908,7 +13466,7 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12908
13466
|
}
|
|
12909
13467
|
throw err;
|
|
12910
13468
|
}
|
|
12911
|
-
mkdirSync18(
|
|
13469
|
+
mkdirSync18(dirname15(resolve15(args.out)), { recursive: true });
|
|
12912
13470
|
writeFileSync17(args.out, JSON.stringify(report, null, 2));
|
|
12913
13471
|
writeStdoutLine(`Wrote coverage report to ${args.out}`);
|
|
12914
13472
|
const totalChunks = report.coveredChunks.length + report.missingChunks.length + report.uncoverableChunks.length;
|
|
@@ -12965,7 +13523,7 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12965
13523
|
}
|
|
12966
13524
|
if (report.missingChunks.length > 0) {
|
|
12967
13525
|
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.
|
|
13526
|
+
`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
13527
|
);
|
|
12970
13528
|
}
|
|
12971
13529
|
if (report.idleAgents.length > 0) {
|
|
@@ -12983,6 +13541,12 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
12983
13541
|
`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
13542
|
);
|
|
12985
13543
|
}
|
|
13544
|
+
if (report.budgetGaps.length > 0) {
|
|
13545
|
+
const total = report.budgetGaps.reduce((n, g) => n + g.gaps.length, 0);
|
|
13546
|
+
writeStderrLine(
|
|
13547
|
+
`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(" | ")
|
|
13548
|
+
);
|
|
13549
|
+
}
|
|
12986
13550
|
if (!report.ok) {
|
|
12987
13551
|
process.exitCode = 3;
|
|
12988
13552
|
}
|
|
@@ -13007,14 +13571,14 @@ var checkCoverageCommand = {
|
|
|
13007
13571
|
|
|
13008
13572
|
// packages/cli/src/commands/review/agent-prompt.ts
|
|
13009
13573
|
init_esbuild_shims();
|
|
13010
|
-
import { createHash as
|
|
13011
|
-
import { readFileSync as
|
|
13012
|
-
import { dirname as
|
|
13574
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
13575
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
13576
|
+
import { dirname as dirname16, join as join14, resolve as resolve17 } from "node:path";
|
|
13013
13577
|
|
|
13014
13578
|
// packages/cli/src/commands/review/lib/retirement.ts
|
|
13015
13579
|
init_esbuild_shims();
|
|
13016
|
-
import { readFileSync as
|
|
13017
|
-
import { resolve as
|
|
13580
|
+
import { readFileSync as readFileSync20, statSync as statSync11 } from "node:fs";
|
|
13581
|
+
import { resolve as resolve16, sep as sep6 } from "node:path";
|
|
13018
13582
|
var REVERSE_AUDIT_MAX_ROUNDS = 5;
|
|
13019
13583
|
var RECORD_KEY_RE = /^reverse-audit--chunk-(\d+)--round-(\d+)--[0-9a-f]+$/;
|
|
13020
13584
|
var REVERSE_AUDIT_MARKER = "reverse-audit";
|
|
@@ -13056,13 +13620,13 @@ __name(substantiveClause, "substantiveClause");
|
|
|
13056
13620
|
function findingsListFor(prompt, recordDir, memo) {
|
|
13057
13621
|
const pointer = findingsPointerOf(prompt);
|
|
13058
13622
|
if (pointer === null) return prompt;
|
|
13059
|
-
const root =
|
|
13060
|
-
const target =
|
|
13061
|
-
if (target !== root && !target.startsWith(root +
|
|
13623
|
+
const root = resolve16(recordDir);
|
|
13624
|
+
const target = resolve16(pointer);
|
|
13625
|
+
if (target !== root && !target.startsWith(root + sep6)) return prompt;
|
|
13062
13626
|
const cached = memo.get(pointer);
|
|
13063
13627
|
if (cached !== void 0) return cached;
|
|
13064
13628
|
try {
|
|
13065
|
-
const content =
|
|
13629
|
+
const content = readFileSync20(target, "utf8");
|
|
13066
13630
|
memo.set(pointer, content);
|
|
13067
13631
|
return content;
|
|
13068
13632
|
} catch {
|
|
@@ -13080,8 +13644,12 @@ function classifyReturn(rec, territory, findingsList) {
|
|
|
13080
13644
|
return "yielded";
|
|
13081
13645
|
}
|
|
13082
13646
|
}
|
|
13083
|
-
const
|
|
13084
|
-
|
|
13647
|
+
const judged = stripBudgetGapLines(text);
|
|
13648
|
+
const receipt = DRY_RECEIPT_RE.exec(judged);
|
|
13649
|
+
const clause = receipt?.[1] ?? "";
|
|
13650
|
+
const inlineGap = INLINE_BUDGET_GAP_RE.exec(clause);
|
|
13651
|
+
const judgedClause = inlineGap === null ? clause : clause.slice(0, inlineGap.index);
|
|
13652
|
+
if (rec.successfulToolCalls > 0 && rec.diffToolCalls > 0 && openedTheTerritory(rec.diffReads, territory) && receipt !== null && substantiveClause(judgedClause)) {
|
|
13085
13653
|
return "dry";
|
|
13086
13654
|
}
|
|
13087
13655
|
return "unknown";
|
|
@@ -13109,7 +13677,7 @@ function scheduleReverseAuditRound(planPath, chunkIds, round, env = process.env,
|
|
|
13109
13677
|
converged: false
|
|
13110
13678
|
};
|
|
13111
13679
|
}
|
|
13112
|
-
const since =
|
|
13680
|
+
const since = statSync11(planPath).mtimeMs;
|
|
13113
13681
|
const transcripts = readTranscripts(since, env, diffPath);
|
|
13114
13682
|
const built = readRecordedPrompts(planPath, since);
|
|
13115
13683
|
const recordDir = promptRecordDir(planPath);
|
|
@@ -13381,6 +13949,60 @@ function chunkFrom(report, id) {
|
|
|
13381
13949
|
return { diffPath, chunk: chunk2, total: chunks.length };
|
|
13382
13950
|
}
|
|
13383
13951
|
__name(chunkFrom, "chunkFrom");
|
|
13952
|
+
var FINDINGS_LIST_READS = 3;
|
|
13953
|
+
var LINES_PER_FILE_READ = 500;
|
|
13954
|
+
function wholeDiffReadPages(report) {
|
|
13955
|
+
return (Array.isArray(report.chunks) ? report.chunks : []).reduce(
|
|
13956
|
+
(n, c) => {
|
|
13957
|
+
const chars = c?.chars;
|
|
13958
|
+
return n + Math.max(
|
|
13959
|
+
1,
|
|
13960
|
+
Math.ceil(
|
|
13961
|
+
(typeof chars === "number" && Number.isFinite(chars) ? chars : 0) / READ_FILE_CHAR_CAP
|
|
13962
|
+
)
|
|
13963
|
+
);
|
|
13964
|
+
},
|
|
13965
|
+
0
|
|
13966
|
+
);
|
|
13967
|
+
}
|
|
13968
|
+
__name(wholeDiffReadPages, "wholeDiffReadPages");
|
|
13969
|
+
function weightedTerritoryLines(report, chunk2) {
|
|
13970
|
+
const lines = typeof chunk2.lines === "number" && Number.isFinite(chunk2.lines) ? Math.max(0, Math.floor(chunk2.lines)) : 0;
|
|
13971
|
+
if (lines === 0) return 0;
|
|
13972
|
+
const kinds = new Map(
|
|
13973
|
+
(Array.isArray(report.files) ? report.files : []).filter((f) => !!f && typeof f.path === "string").map((f) => [f.path, f.kind])
|
|
13974
|
+
);
|
|
13975
|
+
let src = 0;
|
|
13976
|
+
let other = 0;
|
|
13977
|
+
for (const f of Array.isArray(chunk2.files) ? chunk2.files : []) {
|
|
13978
|
+
const e = f;
|
|
13979
|
+
const span = typeof e?.newStart === "number" && typeof e?.newEnd === "number" ? e.newEnd - e.newStart + 1 : 0;
|
|
13980
|
+
if (!(span > 0)) continue;
|
|
13981
|
+
const kind = typeof e.path === "string" ? kinds.get(e.path) : void 0;
|
|
13982
|
+
if (kind === void 0 || kind === "source") src += span;
|
|
13983
|
+
else other += span;
|
|
13984
|
+
}
|
|
13985
|
+
const total = src + other;
|
|
13986
|
+
if (total === 0) return lines;
|
|
13987
|
+
return Math.max(1, Math.round(lines * (src + other / 8) / total));
|
|
13988
|
+
}
|
|
13989
|
+
__name(weightedTerritoryLines, "weightedTerritoryLines");
|
|
13990
|
+
function toolBudgetBlock(report, launch) {
|
|
13991
|
+
const base = report.budget?.agentToolBudget;
|
|
13992
|
+
if (typeof base !== "number" || !Number.isFinite(base) || base <= 0) {
|
|
13993
|
+
return [];
|
|
13994
|
+
}
|
|
13995
|
+
const reads = Number.isFinite(launch.mandatoryReads) ? Math.max(0, Math.floor(launch.mandatoryReads)) : 0;
|
|
13996
|
+
const territory = typeof launch.territoryLines === "number" && Number.isFinite(launch.territoryLines) ? launch.territoryLines : launch.territoryLines === null || launch.territoryLines === void 0 ? null : 0;
|
|
13997
|
+
const total = launchToolBudget(base, territory, reads);
|
|
13998
|
+
return [
|
|
13999
|
+
"",
|
|
14000
|
+
"## Tool budget",
|
|
14001
|
+
"",
|
|
14002
|
+
`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).`
|
|
14003
|
+
];
|
|
14004
|
+
}
|
|
14005
|
+
__name(toolBudgetBlock, "toolBudgetBlock");
|
|
13384
14006
|
function buildChunkAgentPrompt(report, id, rules) {
|
|
13385
14007
|
const { chunk: chunk2, total } = chunkFrom(report, id);
|
|
13386
14008
|
const files = (Array.isArray(chunk2.files) ? chunk2.files : []).filter(
|
|
@@ -13436,6 +14058,21 @@ function buildChunkAgentPrompt(report, id, rules) {
|
|
|
13436
14058
|
if (repositoryContext) {
|
|
13437
14059
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13438
14060
|
}
|
|
14061
|
+
if (!unreachable) {
|
|
14062
|
+
parts.push(
|
|
14063
|
+
...toolBudgetBlock(report, {
|
|
14064
|
+
territoryLines: weightedTerritoryLines(report, chunk2),
|
|
14065
|
+
// The launch's whole reading list: the brief file, plus the diff pages
|
|
14066
|
+
// this chunk takes.
|
|
14067
|
+
mandatoryReads: 1 + Math.max(
|
|
14068
|
+
1,
|
|
14069
|
+
Math.ceil(
|
|
14070
|
+
(Number.isFinite(chunk2.chars) ? chunk2.chars : 0) / READ_FILE_CHAR_CAP
|
|
14071
|
+
)
|
|
14072
|
+
)
|
|
14073
|
+
})
|
|
14074
|
+
);
|
|
14075
|
+
}
|
|
13439
14076
|
parts.push(
|
|
13440
14077
|
"",
|
|
13441
14078
|
"## When you are done",
|
|
@@ -13485,6 +14122,9 @@ function buildWholeDiffBlock(report, rules) {
|
|
|
13485
14122
|
if (repositoryContext) {
|
|
13486
14123
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13487
14124
|
}
|
|
14125
|
+
parts.push(
|
|
14126
|
+
...toolBudgetBlock(report, { mandatoryReads: wholeDiffReadPages(report) })
|
|
14127
|
+
);
|
|
13488
14128
|
parts.push(...tail(rules));
|
|
13489
14129
|
return parts.join("\n");
|
|
13490
14130
|
}
|
|
@@ -13672,6 +14312,56 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13672
14312
|
parts.push("");
|
|
13673
14313
|
}
|
|
13674
14314
|
parts.push("## Your dimension", "", brief.brief);
|
|
14315
|
+
if (!brief.budgetExempt) {
|
|
14316
|
+
const chunks = Array.isArray(report.chunks) ? report.chunks : [];
|
|
14317
|
+
if (typeof opts.chunk === "number") {
|
|
14318
|
+
const c = chunks.find((x) => x?.id === opts.chunk);
|
|
14319
|
+
parts.push(
|
|
14320
|
+
...toolBudgetBlock(report, {
|
|
14321
|
+
territoryLines: weightedTerritoryLines(report, c ?? {}),
|
|
14322
|
+
// Its reading list: the brief file, the chunk's diff pages, and
|
|
14323
|
+
// the cumulative findings list its brief orders read in full —
|
|
14324
|
+
// measured at 65-82 KB on real runs, several pages of it.
|
|
14325
|
+
mandatoryReads: 1 + Math.max(
|
|
14326
|
+
1,
|
|
14327
|
+
Math.ceil(
|
|
14328
|
+
(typeof c?.chars === "number" && Number.isFinite(c.chars) ? c.chars : 0) / READ_FILE_CHAR_CAP
|
|
14329
|
+
)
|
|
14330
|
+
) + FINDINGS_LIST_READS
|
|
14331
|
+
})
|
|
14332
|
+
);
|
|
14333
|
+
} else if (role.startsWith("invariant-") && opts.file) {
|
|
14334
|
+
const files = Array.isArray(report.files) ? report.files : [];
|
|
14335
|
+
const f = files.find((x) => x?.path === opts.file);
|
|
14336
|
+
const added = typeof f?.addedLines === "number" ? f.addedLines : 0;
|
|
14337
|
+
const fileLines = typeof f?.fileLines === "number" && Number.isFinite(f.fileLines) ? f.fileLines : 0;
|
|
14338
|
+
const changed = added + (typeof f?.removedLines === "number" ? f.removedLines : 0);
|
|
14339
|
+
parts.push(
|
|
14340
|
+
...toolBudgetBlock(report, {
|
|
14341
|
+
territoryLines: changed,
|
|
14342
|
+
// Its reading list: the brief, its own diff slice, and the whole
|
|
14343
|
+
// post-change file paged to the end. The pages come from
|
|
14344
|
+
// `fileLines` — the post-change length the plan records for
|
|
14345
|
+
// every file — with `addedLines` as the fallback lower bound
|
|
14346
|
+
// for an older plan without it: a file can go heavy by VOLUME
|
|
14347
|
+
// in a large file it barely rewrote, and estimating its paging
|
|
14348
|
+
// from added lines alone told exactly that agent its mandatory
|
|
14349
|
+
// reading was already overspending. Floors at the old flat 4 so
|
|
14350
|
+
// no launch gets less than before.
|
|
14351
|
+
mandatoryReads: Math.max(
|
|
14352
|
+
4,
|
|
14353
|
+
2 + Math.ceil(Math.max(added, fileLines) / LINES_PER_FILE_READ)
|
|
14354
|
+
)
|
|
14355
|
+
})
|
|
14356
|
+
);
|
|
14357
|
+
} else {
|
|
14358
|
+
parts.push(
|
|
14359
|
+
...toolBudgetBlock(report, {
|
|
14360
|
+
mandatoryReads: 1 + wholeDiffReadPages(report) + (brief.acceptsFindings ? FINDINGS_LIST_READS : 0)
|
|
14361
|
+
})
|
|
14362
|
+
);
|
|
14363
|
+
}
|
|
14364
|
+
}
|
|
13675
14365
|
const repositoryContext = repositoryContextOf(report);
|
|
13676
14366
|
if (role === "7") {
|
|
13677
14367
|
if (repositoryContext) {
|
|
@@ -13702,7 +14392,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13702
14392
|
"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
14393
|
);
|
|
13704
14394
|
}
|
|
13705
|
-
const ctx = opts.planPath ?
|
|
14395
|
+
const ctx = opts.planPath ? join14(dirname16(resolve17(opts.planPath)), `qwen-review-pr-${pr}-context.md`) : null;
|
|
13706
14396
|
parts.push(
|
|
13707
14397
|
"",
|
|
13708
14398
|
`**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 +14414,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13724
14414
|
}
|
|
13725
14415
|
const base = report.mergeBaseSha;
|
|
13726
14416
|
const pr = report.prNumber;
|
|
13727
|
-
const buildTree = typeof wt === "string" && wt ?
|
|
14417
|
+
const buildTree = typeof wt === "string" && wt ? resolve17(wt) : pr === void 0 && opts.planPath ? "." : null;
|
|
13728
14418
|
if (buildTree && opts.planPath) {
|
|
13729
14419
|
const outName = pr !== void 0 ? `qwen-review-pr-${pr}-build-test.json` : "qwen-review-build-test.json";
|
|
13730
14420
|
parts.push(
|
|
@@ -13740,9 +14430,9 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13740
14430
|
// that an old global lacks it entirely, wedging Agent 7 between its
|
|
13741
14431
|
// mandate (no hand-run `npm run build`) and a command that does not exist.
|
|
13742
14432
|
`"\${QWEN_CODE_CLI:-qwen}" review build-test \\`,
|
|
13743
|
-
` --plan ${
|
|
13744
|
-
` --worktree ${
|
|
13745
|
-
` --out ${
|
|
14433
|
+
` --plan ${resolve17(opts.planPath)} \\`,
|
|
14434
|
+
` --worktree ${resolve17(buildTree)} \\`,
|
|
14435
|
+
` --out ${resolve17(dirname16(opts.planPath), outName)}`,
|
|
13746
14436
|
"```"
|
|
13747
14437
|
);
|
|
13748
14438
|
}
|
|
@@ -13752,10 +14442,10 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13752
14442
|
"**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
14443
|
"",
|
|
13754
14444
|
"```bash",
|
|
13755
|
-
`"\${QWEN_CODE_CLI:-qwen}" review test-efficacy ${
|
|
13756
|
-
` --worktree ${typeof wt === "string" ?
|
|
14445
|
+
`"\${QWEN_CODE_CLI:-qwen}" review test-efficacy ${resolve17(opts.planPath)} \\`,
|
|
14446
|
+
` --worktree ${typeof wt === "string" ? resolve17(wt) : "<worktree>"} \\`,
|
|
13757
14447
|
` --base ${base} \\`,
|
|
13758
|
-
` --out ${
|
|
14448
|
+
` --out ${resolve17(dirname16(opts.planPath), `qwen-review-pr-${pr}-efficacy.json`)}`,
|
|
13759
14449
|
"```",
|
|
13760
14450
|
"",
|
|
13761
14451
|
'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 +14611,7 @@ function buildLaunch(report, planPath, spec, rules) {
|
|
|
13921
14611
|
}
|
|
13922
14612
|
__name(buildLaunch, "buildLaunch");
|
|
13923
14613
|
function findingsDigest(content, rules) {
|
|
13924
|
-
return
|
|
14614
|
+
return createHash4("sha256").update(JSON.stringify([content, rules ?? null])).digest("hex").slice(0, 12);
|
|
13925
14615
|
}
|
|
13926
14616
|
__name(findingsDigest, "findingsDigest");
|
|
13927
14617
|
function foldFindings(role, content, prompt, findingsFile) {
|
|
@@ -14215,7 +14905,7 @@ function runAgentPrompt(args) {
|
|
|
14215
14905
|
}
|
|
14216
14906
|
let report;
|
|
14217
14907
|
try {
|
|
14218
|
-
report = JSON.parse(
|
|
14908
|
+
report = JSON.parse(readFileSync21(args.plan, "utf8"));
|
|
14219
14909
|
} catch (err) {
|
|
14220
14910
|
throw new Error(
|
|
14221
14911
|
`agent-prompt: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -14224,7 +14914,7 @@ function runAgentPrompt(args) {
|
|
|
14224
14914
|
let rules;
|
|
14225
14915
|
if (args.rules) {
|
|
14226
14916
|
try {
|
|
14227
|
-
rules =
|
|
14917
|
+
rules = readFileSync21(args.rules, "utf8");
|
|
14228
14918
|
} catch (err) {
|
|
14229
14919
|
throw new Error(
|
|
14230
14920
|
`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 +14929,7 @@ function runAgentPrompt(args) {
|
|
|
14239
14929
|
if (hasFindings && args.role) {
|
|
14240
14930
|
const role = args.role;
|
|
14241
14931
|
try {
|
|
14242
|
-
findingsContent =
|
|
14932
|
+
findingsContent = readFileSync21(args.findings, "utf8");
|
|
14243
14933
|
} catch (err) {
|
|
14244
14934
|
throw new Error(
|
|
14245
14935
|
`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 +15074,18 @@ var agentPromptCommand = {
|
|
|
14384
15074
|
init_esbuild_shims();
|
|
14385
15075
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
14386
15076
|
import {
|
|
14387
|
-
existsSync as
|
|
14388
|
-
readFileSync as
|
|
15077
|
+
existsSync as existsSync9,
|
|
15078
|
+
readFileSync as readFileSync23,
|
|
14389
15079
|
rmSync as rmSync5,
|
|
14390
15080
|
statfsSync,
|
|
14391
15081
|
writeFileSync as writeFileSync18
|
|
14392
15082
|
} from "node:fs";
|
|
14393
|
-
import { join as
|
|
15083
|
+
import { join as join16, resolve as resolve18 } from "node:path";
|
|
14394
15084
|
|
|
14395
15085
|
// packages/cli/src/commands/review/lib/workspaces.ts
|
|
14396
15086
|
init_esbuild_shims();
|
|
14397
|
-
import { existsSync as
|
|
14398
|
-
import { join as
|
|
15087
|
+
import { existsSync as existsSync8, readFileSync as readFileSync22, readdirSync as readdirSync6 } from "node:fs";
|
|
15088
|
+
import { join as join15 } from "node:path";
|
|
14399
15089
|
function isWorkspaceMember(filePath, workspaceGlobs) {
|
|
14400
15090
|
return workspaceDirFor(filePath, workspaceGlobs) !== null;
|
|
14401
15091
|
}
|
|
@@ -14447,7 +15137,7 @@ __name(hasUnmodeledWorkspaceGlob, "hasUnmodeledWorkspaceGlob");
|
|
|
14447
15137
|
function readWorkspaceGlobs(root) {
|
|
14448
15138
|
try {
|
|
14449
15139
|
const pkg = JSON.parse(
|
|
14450
|
-
|
|
15140
|
+
readFileSync22(join15(root, "package.json"), "utf8")
|
|
14451
15141
|
);
|
|
14452
15142
|
const ws = pkg.workspaces;
|
|
14453
15143
|
const globs = Array.isArray(ws) ? ws : Array.isArray(ws?.packages) ? ws.packages : [];
|
|
@@ -14460,7 +15150,7 @@ __name(readWorkspaceGlobs, "readWorkspaceGlobs");
|
|
|
14460
15150
|
function readRootPackage(root) {
|
|
14461
15151
|
let pkg;
|
|
14462
15152
|
try {
|
|
14463
|
-
pkg = JSON.parse(
|
|
15153
|
+
pkg = JSON.parse(readFileSync22(join15(root, "package.json"), "utf8"));
|
|
14464
15154
|
} catch {
|
|
14465
15155
|
return null;
|
|
14466
15156
|
}
|
|
@@ -14502,8 +15192,8 @@ function workspaceDirCandidates(root, globs) {
|
|
|
14502
15192
|
const base = g.slice(0, -2);
|
|
14503
15193
|
let entries;
|
|
14504
15194
|
try {
|
|
14505
|
-
entries =
|
|
14506
|
-
(e) => e.isDirectory() || e.isSymbolicLink() &&
|
|
15195
|
+
entries = readdirSync6(join15(root, base), { withFileTypes: true }).filter(
|
|
15196
|
+
(e) => e.isDirectory() || e.isSymbolicLink() && existsSync8(join15(root, base, e.name, "package.json"))
|
|
14507
15197
|
).map((e) => e.name);
|
|
14508
15198
|
} catch {
|
|
14509
15199
|
continue;
|
|
@@ -14521,8 +15211,8 @@ function readWorkspacePackages(root) {
|
|
|
14521
15211
|
const packages = [];
|
|
14522
15212
|
const skipped = [];
|
|
14523
15213
|
for (const dir of workspaceDirCandidates(root, globs)) {
|
|
14524
|
-
const manifest =
|
|
14525
|
-
if (!
|
|
15214
|
+
const manifest = join15(root, dir, "package.json");
|
|
15215
|
+
if (!existsSync8(manifest)) continue;
|
|
14526
15216
|
if (workspaceDirFor(`${dir}/package.json`, globs) !== dir) {
|
|
14527
15217
|
const positives = globs.filter((g) => !g.startsWith("!"));
|
|
14528
15218
|
if (workspaceDirFor(`${dir}/package.json`, positives) === dir) continue;
|
|
@@ -14531,7 +15221,7 @@ function readWorkspacePackages(root) {
|
|
|
14531
15221
|
}
|
|
14532
15222
|
let pkg;
|
|
14533
15223
|
try {
|
|
14534
|
-
pkg = JSON.parse(
|
|
15224
|
+
pkg = JSON.parse(readFileSync22(manifest, "utf8"));
|
|
14535
15225
|
} catch {
|
|
14536
15226
|
skipped.push(dir);
|
|
14537
15227
|
continue;
|
|
@@ -14788,7 +15478,7 @@ __name(unresolvedWorkspaceDeps, "unresolvedWorkspaceDeps");
|
|
|
14788
15478
|
function changedFilesFrom(planPath) {
|
|
14789
15479
|
let parsed;
|
|
14790
15480
|
try {
|
|
14791
|
-
parsed = JSON.parse(
|
|
15481
|
+
parsed = JSON.parse(readFileSync23(planPath, "utf8"));
|
|
14792
15482
|
} catch (err) {
|
|
14793
15483
|
throw new Error(
|
|
14794
15484
|
`build-test: cannot read the plan ${planPath}: ${err.message}`
|
|
@@ -14805,7 +15495,7 @@ function changedFilesFrom(planPath) {
|
|
|
14805
15495
|
}
|
|
14806
15496
|
__name(changedFilesFrom, "changedFilesFrom");
|
|
14807
15497
|
function runBuildTest(args) {
|
|
14808
|
-
const root =
|
|
15498
|
+
const root = resolve18(args.worktree);
|
|
14809
15499
|
const perCommandMs = args.timeout * 1e3;
|
|
14810
15500
|
const callBudgetMs = (args.budget ?? Math.max(args.timeout, args.timeout * 2 - 30)) * 1e3;
|
|
14811
15501
|
const runStarted = Date.now();
|
|
@@ -14883,15 +15573,15 @@ function runBuildTest(args) {
|
|
|
14883
15573
|
timedOut: [],
|
|
14884
15574
|
note: ""
|
|
14885
15575
|
};
|
|
14886
|
-
const npmLock =
|
|
14887
|
-
const installComplete = /* @__PURE__ */ __name(() =>
|
|
14888
|
-
if (args.install && !npmLock && !
|
|
15576
|
+
const npmLock = existsSync9(join16(root, "package-lock.json"));
|
|
15577
|
+
const installComplete = /* @__PURE__ */ __name(() => existsSync9(join16(root, "node_modules", ".package-lock.json")), "installComplete");
|
|
15578
|
+
if (args.install && !npmLock && !existsSync9(join16(root, "node_modules"))) {
|
|
14889
15579
|
const altLock = [
|
|
14890
15580
|
["yarn.lock", "yarn install --frozen-lockfile"],
|
|
14891
15581
|
["pnpm-lock.yaml", "pnpm install --frozen-lockfile"],
|
|
14892
15582
|
["bun.lockb", "bun install --frozen-lockfile"],
|
|
14893
15583
|
["bun.lock", "bun install --frozen-lockfile"]
|
|
14894
|
-
].find(([f]) =>
|
|
15584
|
+
].find(([f]) => existsSync9(join16(root, f)));
|
|
14895
15585
|
return unsupportedReport(
|
|
14896
15586
|
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
15587
|
);
|
|
@@ -14918,7 +15608,7 @@ function runBuildTest(args) {
|
|
|
14918
15608
|
if (install.timedOut) results.timedOut.push(install.command);
|
|
14919
15609
|
if (install.timedOut) {
|
|
14920
15610
|
try {
|
|
14921
|
-
rmSync5(
|
|
15611
|
+
rmSync5(join16(root, "node_modules"), {
|
|
14922
15612
|
recursive: true,
|
|
14923
15613
|
force: true,
|
|
14924
15614
|
maxRetries: 3
|
|
@@ -15131,14 +15821,14 @@ var buildTestCommand = {
|
|
|
15131
15821
|
init_esbuild_shims();
|
|
15132
15822
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
15133
15823
|
import {
|
|
15134
|
-
existsSync as
|
|
15824
|
+
existsSync as existsSync10,
|
|
15135
15825
|
mkdirSync as mkdirSync19,
|
|
15136
|
-
readFileSync as
|
|
15826
|
+
readFileSync as readFileSync24,
|
|
15137
15827
|
rmSync as rmSync7,
|
|
15138
|
-
statSync as
|
|
15828
|
+
statSync as statSync12,
|
|
15139
15829
|
writeFileSync as writeFileSync19
|
|
15140
15830
|
} from "node:fs";
|
|
15141
|
-
import { dirname as
|
|
15831
|
+
import { dirname as dirname17, join as join17, resolve as resolve19 } from "node:path";
|
|
15142
15832
|
|
|
15143
15833
|
// packages/cli/src/commands/review/lib/worktree.ts
|
|
15144
15834
|
init_esbuild_shims();
|
|
@@ -15185,7 +15875,7 @@ function runBaseTree(args) {
|
|
|
15185
15875
|
}), "unavailable");
|
|
15186
15876
|
let plan;
|
|
15187
15877
|
try {
|
|
15188
|
-
plan = JSON.parse(
|
|
15878
|
+
plan = JSON.parse(readFileSync24(args.plan, "utf8"));
|
|
15189
15879
|
} catch (err) {
|
|
15190
15880
|
return unavailable(
|
|
15191
15881
|
`cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -15202,15 +15892,15 @@ function runBaseTree(args) {
|
|
|
15202
15892
|
"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
15893
|
);
|
|
15204
15894
|
}
|
|
15205
|
-
const worktree =
|
|
15206
|
-
if (!
|
|
15895
|
+
const worktree = resolve19(args.worktree);
|
|
15896
|
+
if (!existsSync10(worktree)) {
|
|
15207
15897
|
return unavailable(`the review worktree ${worktree} does not exist`);
|
|
15208
15898
|
}
|
|
15209
15899
|
const tree = baseWorktreePath(worktree);
|
|
15210
|
-
const marker = /* @__PURE__ */ __name(() =>
|
|
15211
|
-
const failedMarker = /* @__PURE__ */ __name(() =>
|
|
15900
|
+
const marker = /* @__PURE__ */ __name(() => join17(tree, ".qwen-review-base-ok"), "marker");
|
|
15901
|
+
const failedMarker = /* @__PURE__ */ __name(() => join17(tree, ".qwen-review-base-failed"), "failedMarker");
|
|
15212
15902
|
try {
|
|
15213
|
-
if (
|
|
15903
|
+
if (existsSync10(tree) && readFileSync24(marker(), "utf8").trim() === baseSha && gitOut(tree, "rev-parse", "HEAD") === baseSha) {
|
|
15214
15904
|
return {
|
|
15215
15905
|
available: true,
|
|
15216
15906
|
path: tree,
|
|
@@ -15222,7 +15912,7 @@ function runBaseTree(args) {
|
|
|
15222
15912
|
} catch {
|
|
15223
15913
|
}
|
|
15224
15914
|
try {
|
|
15225
|
-
if (
|
|
15915
|
+
if (existsSync10(tree) && readFileSync24(failedMarker(), "utf8").trim() === baseSha) {
|
|
15226
15916
|
return {
|
|
15227
15917
|
available: false,
|
|
15228
15918
|
path: tree,
|
|
@@ -15235,7 +15925,7 @@ function runBaseTree(args) {
|
|
|
15235
15925
|
}
|
|
15236
15926
|
const lock = `${tree}.lock`;
|
|
15237
15927
|
try {
|
|
15238
|
-
const age = Date.now() -
|
|
15928
|
+
const age = Date.now() - statSync12(lock).mtimeMs;
|
|
15239
15929
|
if (age > 30 * 60 * 1e3) {
|
|
15240
15930
|
rmSync7(lock, { recursive: true, force: true });
|
|
15241
15931
|
}
|
|
@@ -15342,8 +16032,8 @@ var baseTreeCommand = {
|
|
|
15342
16032
|
try {
|
|
15343
16033
|
const report = runBaseTree(args);
|
|
15344
16034
|
if (args.out) {
|
|
15345
|
-
mkdirSync19(
|
|
15346
|
-
writeFileSync19(
|
|
16035
|
+
mkdirSync19(dirname17(resolve19(args.out)), { recursive: true });
|
|
16036
|
+
writeFileSync19(resolve19(args.out), JSON.stringify(report, null, 2));
|
|
15347
16037
|
}
|
|
15348
16038
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15349
16039
|
writeStderrLine(`base-tree: ${report.note}`);
|
|
@@ -15357,8 +16047,8 @@ var baseTreeCommand = {
|
|
|
15357
16047
|
// packages/cli/src/commands/review/test-delta.ts
|
|
15358
16048
|
init_esbuild_shims();
|
|
15359
16049
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
15360
|
-
import { existsSync as
|
|
15361
|
-
import { dirname as
|
|
16050
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync20, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "node:fs";
|
|
16051
|
+
import { dirname as dirname18, resolve as resolve20 } from "node:path";
|
|
15362
16052
|
var ANSI_SGR_RE2 = /\x1b\[[0-9;]*m/g;
|
|
15363
16053
|
var RERUNNABLE_COMMAND_RE = /^npm test(?: --workspace="[\w@./-]+")?$/;
|
|
15364
16054
|
var TRIM_MARKER_RE = /\.\.\. \[\d+ characters omitted/;
|
|
@@ -15421,7 +16111,7 @@ var TOTAL_BUDGET_MS = 54e4;
|
|
|
15421
16111
|
var DEFAULT_TIMEOUT_S = 300;
|
|
15422
16112
|
function runTestDelta(args) {
|
|
15423
16113
|
const exec = args.exec ?? run2;
|
|
15424
|
-
const baseline =
|
|
16114
|
+
const baseline = resolve20(args.baseline);
|
|
15425
16115
|
const empty = /* @__PURE__ */ __name((note) => ({
|
|
15426
16116
|
entries: [],
|
|
15427
16117
|
netNew: [],
|
|
@@ -15431,13 +16121,13 @@ function runTestDelta(args) {
|
|
|
15431
16121
|
}), "empty");
|
|
15432
16122
|
let report;
|
|
15433
16123
|
try {
|
|
15434
|
-
report = JSON.parse(
|
|
16124
|
+
report = JSON.parse(readFileSync25(args.report, "utf8"));
|
|
15435
16125
|
} catch (err) {
|
|
15436
16126
|
return empty(
|
|
15437
16127
|
`cannot read the build-test report ${args.report}: ${err.message}`
|
|
15438
16128
|
);
|
|
15439
16129
|
}
|
|
15440
|
-
if (!
|
|
16130
|
+
if (!existsSync11(baseline)) {
|
|
15441
16131
|
return empty(
|
|
15442
16132
|
`the base tree ${baseline} does not exist \u2014 run \`qwen review base-tree\` first`
|
|
15443
16133
|
);
|
|
@@ -15573,8 +16263,8 @@ var testDeltaCommand = {
|
|
|
15573
16263
|
const args = argv;
|
|
15574
16264
|
const report = runTestDelta(args);
|
|
15575
16265
|
if (args.out) {
|
|
15576
|
-
mkdirSync20(
|
|
15577
|
-
writeFileSync20(
|
|
16266
|
+
mkdirSync20(dirname18(resolve20(args.out)), { recursive: true });
|
|
16267
|
+
writeFileSync20(resolve20(args.out), JSON.stringify(report, null, 2));
|
|
15578
16268
|
}
|
|
15579
16269
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15580
16270
|
writeStderrLine(`test-delta: ${report.note}`);
|
|
@@ -15587,12 +16277,12 @@ import { spawnSync as spawnSync7 } from "node:child_process";
|
|
|
15587
16277
|
import {
|
|
15588
16278
|
mkdirSync as mkdirSync21,
|
|
15589
16279
|
writeFileSync as writeFileSync21,
|
|
15590
|
-
readFileSync as
|
|
15591
|
-
existsSync as
|
|
16280
|
+
readFileSync as readFileSync26,
|
|
16281
|
+
existsSync as existsSync12,
|
|
15592
16282
|
rmSync as rmSync8,
|
|
15593
|
-
statSync as
|
|
16283
|
+
statSync as statSync13
|
|
15594
16284
|
} from "node:fs";
|
|
15595
|
-
import { dirname as
|
|
16285
|
+
import { dirname as dirname19, join as join18, resolve as resolve21 } from "node:path";
|
|
15596
16286
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
15597
16287
|
var SERVER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
15598
16288
|
function shellQuote(v) {
|
|
@@ -15604,7 +16294,7 @@ var LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
|
15604
16294
|
var POLL_MS = 250;
|
|
15605
16295
|
function logBytes(p) {
|
|
15606
16296
|
try {
|
|
15607
|
-
return
|
|
16297
|
+
return statSync13(p).size;
|
|
15608
16298
|
} catch {
|
|
15609
16299
|
return 0;
|
|
15610
16300
|
}
|
|
@@ -15710,11 +16400,11 @@ function runDrive(args) {
|
|
|
15710
16400
|
waitMs(POLL_MS);
|
|
15711
16401
|
}
|
|
15712
16402
|
}
|
|
15713
|
-
const dir =
|
|
16403
|
+
const dir = join18(tmpdir2(), `qwen-review-drive-${server}`);
|
|
15714
16404
|
mkdirSync21(dir, { recursive: true });
|
|
15715
|
-
const scriptPath =
|
|
15716
|
-
const logPath = args.logPath ??
|
|
15717
|
-
const sentinelPath =
|
|
16405
|
+
const scriptPath = join18(dir, "drive.sh");
|
|
16406
|
+
const logPath = args.logPath ?? join18(dir, "drive.log");
|
|
16407
|
+
const sentinelPath = join18(dir, "drive.rc");
|
|
15718
16408
|
rmSync8(sentinelPath, { force: true });
|
|
15719
16409
|
writeFileSync21(scriptPath, wrapScript(args.script, sentinelPath), "utf8");
|
|
15720
16410
|
const droveFrom = Date.now();
|
|
@@ -15746,8 +16436,8 @@ function runDrive(args) {
|
|
|
15746
16436
|
}
|
|
15747
16437
|
const deadline = droveFrom + args.timeout * 1e3;
|
|
15748
16438
|
for (; ; ) {
|
|
15749
|
-
output =
|
|
15750
|
-
exitCode =
|
|
16439
|
+
output = existsSync12(logPath) ? readFileSync26(logPath, "utf8") : "";
|
|
16440
|
+
exitCode = existsSync12(sentinelPath) ? sentinelExitCode(readFileSync26(sentinelPath, "utf8")) : null;
|
|
15751
16441
|
if (exitCode !== null) {
|
|
15752
16442
|
outcome = "completed";
|
|
15753
16443
|
break;
|
|
@@ -15811,11 +16501,13 @@ var driveCommand = {
|
|
|
15811
16501
|
}), "builder"),
|
|
15812
16502
|
handler: /* @__PURE__ */ __name((argv) => {
|
|
15813
16503
|
try {
|
|
16504
|
+
const bundleNotice = bundleStalenessNotices(process.argv[1], true);
|
|
16505
|
+
if (bundleNotice) writeStderrLineSafe(bundleNotice);
|
|
15814
16506
|
const args = argv;
|
|
15815
16507
|
const report = runDrive(args);
|
|
15816
16508
|
if (args.out) {
|
|
15817
|
-
mkdirSync21(
|
|
15818
|
-
writeFileSync21(
|
|
16509
|
+
mkdirSync21(dirname19(resolve21(args.out)), { recursive: true });
|
|
16510
|
+
writeFileSync21(resolve21(args.out), JSON.stringify(report, null, 2));
|
|
15819
16511
|
}
|
|
15820
16512
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
15821
16513
|
writeStderrLine(`drive: ${report.note}`);
|
|
@@ -15833,7 +16525,7 @@ import {
|
|
|
15833
16525
|
createServer
|
|
15834
16526
|
} from "node:http";
|
|
15835
16527
|
import { appendFileSync, mkdirSync as mkdirSync22, writeFileSync as writeFileSync22 } from "node:fs";
|
|
15836
|
-
import { dirname as
|
|
16528
|
+
import { dirname as dirname20, resolve as resolve22 } from "node:path";
|
|
15837
16529
|
import { pathToFileURL } from "node:url";
|
|
15838
16530
|
function messagesText(body) {
|
|
15839
16531
|
const msgs = Array.isArray(body?.["messages"]) ? body["messages"] : [];
|
|
@@ -16079,7 +16771,7 @@ var DEFAULT_REPLY = { text: "ok" };
|
|
|
16079
16771
|
async function startMockProvider(args, respondOverride) {
|
|
16080
16772
|
let respond = respondOverride ?? (() => DEFAULT_REPLY);
|
|
16081
16773
|
if (!respondOverride && args.responder) {
|
|
16082
|
-
const mod = await import(pathToFileURL(
|
|
16774
|
+
const mod = await import(pathToFileURL(resolve22(args.responder)).href);
|
|
16083
16775
|
const fn = mod.respond ?? mod.default;
|
|
16084
16776
|
if (typeof fn !== "function") {
|
|
16085
16777
|
throw new Error(
|
|
@@ -16088,8 +16780,8 @@ async function startMockProvider(args, respondOverride) {
|
|
|
16088
16780
|
}
|
|
16089
16781
|
respond = fn;
|
|
16090
16782
|
}
|
|
16091
|
-
const logPath =
|
|
16092
|
-
mkdirSync22(
|
|
16783
|
+
const logPath = resolve22(args.log);
|
|
16784
|
+
mkdirSync22(dirname20(logPath), { recursive: true });
|
|
16093
16785
|
writeFileSync22(logPath, "");
|
|
16094
16786
|
let n = 0;
|
|
16095
16787
|
const record = /* @__PURE__ */ __name((entry) => appendFileSync(logPath, `${JSON.stringify(entry)}
|
|
@@ -16252,8 +16944,8 @@ var mockProviderCommand = {
|
|
|
16252
16944
|
const args = argv;
|
|
16253
16945
|
const { report, close } = await startMockProvider(args);
|
|
16254
16946
|
if (args.out) {
|
|
16255
|
-
mkdirSync22(
|
|
16256
|
-
writeFileSync22(
|
|
16947
|
+
mkdirSync22(dirname20(resolve22(args.out)), { recursive: true });
|
|
16948
|
+
writeFileSync22(resolve22(args.out), JSON.stringify(report, null, 2));
|
|
16257
16949
|
}
|
|
16258
16950
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
16259
16951
|
writeStderrLine(`mock-provider: ${report.note}`);
|
|
@@ -16271,8 +16963,8 @@ var mockProviderCommand = {
|
|
|
16271
16963
|
// packages/cli/src/commands/review/extract-step.ts
|
|
16272
16964
|
init_esbuild_shims();
|
|
16273
16965
|
var import_yaml = __toESM(require_dist(), 1);
|
|
16274
|
-
import { mkdirSync as mkdirSync23, readFileSync as
|
|
16275
|
-
import { dirname as
|
|
16966
|
+
import { mkdirSync as mkdirSync23, readFileSync as readFileSync27, writeFileSync as writeFileSync23, chmodSync } from "node:fs";
|
|
16967
|
+
import { dirname as dirname21, resolve as resolve23 } from "node:path";
|
|
16276
16968
|
function expressionsOf(...texts) {
|
|
16277
16969
|
const seen = /* @__PURE__ */ new Set();
|
|
16278
16970
|
for (const t2 of texts) {
|
|
@@ -16516,10 +17208,10 @@ function nearestFirst(env, sources) {
|
|
|
16516
17208
|
}
|
|
16517
17209
|
__name(nearestFirst, "nearestFirst");
|
|
16518
17210
|
function runExtractStep(args) {
|
|
16519
|
-
const wfPath =
|
|
17211
|
+
const wfPath = resolve23(args.workflow);
|
|
16520
17212
|
let text;
|
|
16521
17213
|
try {
|
|
16522
|
-
text =
|
|
17214
|
+
text = readFileSync27(wfPath, "utf8");
|
|
16523
17215
|
} catch (err) {
|
|
16524
17216
|
throw new Error(
|
|
16525
17217
|
`extract-step: cannot read ${args.workflow}: ${err.message}`
|
|
@@ -16585,8 +17277,8 @@ function runExtractStep(args) {
|
|
|
16585
17277
|
const workingDirectory = workingDir?.value;
|
|
16586
17278
|
const script = step.run;
|
|
16587
17279
|
const stepLabel = String(step.name ?? step.id ?? index);
|
|
16588
|
-
const outPath =
|
|
16589
|
-
mkdirSync23(
|
|
17280
|
+
const outPath = resolve23(args.out);
|
|
17281
|
+
mkdirSync23(dirname21(outPath), { recursive: true });
|
|
16590
17282
|
const header = [
|
|
16591
17283
|
`#!/usr/bin/env ${shellCommand}`,
|
|
16592
17284
|
...commentLines(
|
|
@@ -16671,7 +17363,7 @@ var extractStepCommand = {
|
|
|
16671
17363
|
|
|
16672
17364
|
// packages/cli/src/commands/review/submit.ts
|
|
16673
17365
|
init_esbuild_shims();
|
|
16674
|
-
import { mkdirSync as mkdirSync24, readFileSync as
|
|
17366
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync28 } from "node:fs";
|
|
16675
17367
|
|
|
16676
17368
|
// packages/cli/src/commands/review/lib/receipt.ts
|
|
16677
17369
|
init_esbuild_shims();
|
|
@@ -16693,7 +17385,7 @@ __name(parseReceiptIds, "parseReceiptIds");
|
|
|
16693
17385
|
var EVENTS = /* @__PURE__ */ new Set(["APPROVE", "REQUEST_CHANGES", "COMMENT"]);
|
|
16694
17386
|
function readReceiptIds(receiptPath) {
|
|
16695
17387
|
try {
|
|
16696
|
-
return parseReceiptIds(
|
|
17388
|
+
return parseReceiptIds(readFileSync28(receiptPath, "utf8"));
|
|
16697
17389
|
} catch {
|
|
16698
17390
|
return [];
|
|
16699
17391
|
}
|
|
@@ -16729,12 +17421,8 @@ function authorization(args) {
|
|
|
16729
17421
|
repo: args.repo,
|
|
16730
17422
|
// The EFFECTIVE host, not merely the flag: with --host absent the gh
|
|
16731
17423
|
// 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)
|
|
17424
|
+
// write would route — and what the gate must bind.
|
|
17425
|
+
host: resolveGhHost(args.host)
|
|
16738
17426
|
});
|
|
16739
17427
|
}
|
|
16740
17428
|
__name(authorization, "authorization");
|
|
@@ -16858,7 +17546,7 @@ function runSubmit(args, cliVersion = "unknown") {
|
|
|
16858
17546
|
}
|
|
16859
17547
|
let payload;
|
|
16860
17548
|
try {
|
|
16861
|
-
payload = JSON.parse(
|
|
17549
|
+
payload = JSON.parse(readFileSync28(args.review, "utf8"));
|
|
16862
17550
|
} catch (err) {
|
|
16863
17551
|
throw new Error(
|
|
16864
17552
|
`Cannot read review JSON ${args.review}: ${err.message}`
|
|
@@ -17009,17 +17697,17 @@ init_esbuild_shims();
|
|
|
17009
17697
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
17010
17698
|
import {
|
|
17011
17699
|
mkdirSync as mkdirSync25,
|
|
17012
|
-
readdirSync as
|
|
17700
|
+
readdirSync as readdirSync7,
|
|
17013
17701
|
writeFileSync as writeFileSync24,
|
|
17014
|
-
readFileSync as
|
|
17702
|
+
readFileSync as readFileSync29,
|
|
17015
17703
|
rmSync as rmSync9,
|
|
17016
17704
|
lstatSync as lstatSync5,
|
|
17017
|
-
existsSync as
|
|
17018
|
-
statSync as
|
|
17705
|
+
existsSync as existsSync13,
|
|
17706
|
+
statSync as statSync14,
|
|
17019
17707
|
symlinkSync
|
|
17020
17708
|
} from "node:fs";
|
|
17021
17709
|
import { createRequire } from "node:module";
|
|
17022
|
-
import { dirname as
|
|
17710
|
+
import { dirname as dirname22, join as join19, isAbsolute as isAbsolute5, sep as sep7 } from "node:path";
|
|
17023
17711
|
var FIXTURE_DIR_RE = /(^|\/)(__fixtures__|__mocks__|__snapshots__|fixtures)\//;
|
|
17024
17712
|
function planTestEfficacy(files, workspaceGlobs) {
|
|
17025
17713
|
const tests = files.filter((f) => f.kind === "test").map((f) => f.path);
|
|
@@ -17543,7 +18231,7 @@ function gitOut2(cwd, ...args) {
|
|
|
17543
18231
|
}
|
|
17544
18232
|
__name(gitOut2, "gitOut");
|
|
17545
18233
|
function findVitestBin(worktree, resolveModule = createRequire(
|
|
17546
|
-
|
|
18234
|
+
join19(worktree, "noop.js")
|
|
17547
18235
|
).resolve) {
|
|
17548
18236
|
let pkgPath;
|
|
17549
18237
|
try {
|
|
@@ -17554,12 +18242,12 @@ function findVitestBin(worktree, resolveModule = createRequire(
|
|
|
17554
18242
|
}
|
|
17555
18243
|
throw error;
|
|
17556
18244
|
}
|
|
17557
|
-
const pkg = JSON.parse(
|
|
18245
|
+
const pkg = JSON.parse(readFileSync29(pkgPath, "utf8"));
|
|
17558
18246
|
const bin = pkg.bin?.vitest;
|
|
17559
18247
|
if (!bin) {
|
|
17560
18248
|
throw new Error(`vitest package at ${pkgPath} declares no "vitest" bin`);
|
|
17561
18249
|
}
|
|
17562
|
-
return
|
|
18250
|
+
return join19(dirname22(pkgPath), bin);
|
|
17563
18251
|
}
|
|
17564
18252
|
__name(findVitestBin, "findVitestBin");
|
|
17565
18253
|
function gitCapture(cwd, ...args) {
|
|
@@ -17585,7 +18273,7 @@ function safeRmWithin(worktree, relPath) {
|
|
|
17585
18273
|
const parts = relPath.split(/[/\\]+/).filter((s) => s && s !== ".");
|
|
17586
18274
|
let cur = worktree;
|
|
17587
18275
|
for (let i = 0; i < parts.length; i++) {
|
|
17588
|
-
cur =
|
|
18276
|
+
cur = join19(cur, parts[i]);
|
|
17589
18277
|
let st;
|
|
17590
18278
|
try {
|
|
17591
18279
|
st = lstatSync5(cur);
|
|
@@ -17610,15 +18298,15 @@ __name(probeCleanupFailureDetail, "probeCleanupFailureDetail");
|
|
|
17610
18298
|
function exposeDependencies(probeTree, dependencyRoot) {
|
|
17611
18299
|
const done = { linked: 0, failed: 0 };
|
|
17612
18300
|
if (probeTree === dependencyRoot) return done;
|
|
17613
|
-
const source =
|
|
17614
|
-
const target =
|
|
17615
|
-
if (!
|
|
18301
|
+
const source = join19(dependencyRoot, "node_modules");
|
|
18302
|
+
const target = join19(probeTree, "node_modules");
|
|
18303
|
+
if (!existsSync13(source) || existsSync13(target)) return done;
|
|
17616
18304
|
mkdirSync25(target);
|
|
17617
18305
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
17618
|
-
for (const entry of
|
|
18306
|
+
for (const entry of readdirSync7(source, { withFileTypes: true })) {
|
|
17619
18307
|
if (entry.name === ".vite" || entry.name === ".vite-temp") continue;
|
|
17620
|
-
const sourceEntry =
|
|
17621
|
-
const targetEntry =
|
|
18308
|
+
const sourceEntry = join19(source, entry.name);
|
|
18309
|
+
const targetEntry = join19(target, entry.name);
|
|
17622
18310
|
let sourceStats;
|
|
17623
18311
|
try {
|
|
17624
18312
|
sourceStats = lstatSync5(sourceEntry);
|
|
@@ -17628,7 +18316,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
17628
18316
|
}
|
|
17629
18317
|
if (sourceStats.isSymbolicLink()) {
|
|
17630
18318
|
try {
|
|
17631
|
-
if (!
|
|
18319
|
+
if (!statSync14(sourceEntry).isDirectory()) continue;
|
|
17632
18320
|
} catch {
|
|
17633
18321
|
continue;
|
|
17634
18322
|
}
|
|
@@ -17639,14 +18327,14 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
17639
18327
|
let pkgs;
|
|
17640
18328
|
try {
|
|
17641
18329
|
mkdirSync25(targetEntry);
|
|
17642
|
-
pkgs =
|
|
18330
|
+
pkgs = readdirSync7(sourceEntry);
|
|
17643
18331
|
} catch {
|
|
17644
18332
|
done.failed++;
|
|
17645
18333
|
continue;
|
|
17646
18334
|
}
|
|
17647
18335
|
for (const pkg of pkgs) {
|
|
17648
18336
|
try {
|
|
17649
|
-
symlinkSync(
|
|
18337
|
+
symlinkSync(join19(sourceEntry, pkg), join19(targetEntry, pkg), linkType);
|
|
17650
18338
|
done.linked++;
|
|
17651
18339
|
} catch {
|
|
17652
18340
|
done.failed++;
|
|
@@ -17792,10 +18480,10 @@ function newSideLength(header) {
|
|
|
17792
18480
|
__name(newSideLength, "newSideLength");
|
|
17793
18481
|
function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
17794
18482
|
const { patch: _patch, ...meta } = hunk;
|
|
17795
|
-
const abs =
|
|
18483
|
+
const abs = join19(probeTree, hunk.file);
|
|
17796
18484
|
let original;
|
|
17797
18485
|
try {
|
|
17798
|
-
original =
|
|
18486
|
+
original = readFileSync29(abs, "utf8");
|
|
17799
18487
|
} catch (e) {
|
|
17800
18488
|
return {
|
|
17801
18489
|
...meta,
|
|
@@ -17821,16 +18509,16 @@ function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
|
17821
18509
|
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
18510
|
return { ...meta, verdict, detail };
|
|
17823
18511
|
} finally {
|
|
17824
|
-
mkdirSync25(
|
|
18512
|
+
mkdirSync25(dirname22(abs), { recursive: true });
|
|
17825
18513
|
writeFileSync24(abs, original, "utf8");
|
|
17826
18514
|
}
|
|
17827
18515
|
}
|
|
17828
18516
|
__name(runOneHunkProbe, "runOneHunkProbe");
|
|
17829
18517
|
function runControlMutant(probeTree, probeFile, deadlineAt, now = Date.now) {
|
|
17830
|
-
const abs =
|
|
18518
|
+
const abs = join19(probeTree, probeFile);
|
|
17831
18519
|
let original;
|
|
17832
18520
|
try {
|
|
17833
|
-
original =
|
|
18521
|
+
original = readFileSync29(abs, "utf8");
|
|
17834
18522
|
} catch {
|
|
17835
18523
|
return null;
|
|
17836
18524
|
}
|
|
@@ -17853,8 +18541,8 @@ __qcIt('QWEN-REVIEW-POSITIVE-CONTROL', () => {
|
|
|
17853
18541
|
}
|
|
17854
18542
|
__name(runControlMutant, "runControlMutant");
|
|
17855
18543
|
function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
17856
|
-
const abs =
|
|
17857
|
-
const original =
|
|
18544
|
+
const abs = join19(probeTree, mutant.file);
|
|
18545
|
+
const original = readFileSync29(abs, "utf8");
|
|
17858
18546
|
const lines = original.split("\n");
|
|
17859
18547
|
if ((lines[mutant.line - 1] ?? "").trim() !== mutant.statement) {
|
|
17860
18548
|
return {
|
|
@@ -17921,9 +18609,9 @@ async function runTestEfficacy(args) {
|
|
|
17921
18609
|
const now = args.now ?? Date.now;
|
|
17922
18610
|
const startedAt = now();
|
|
17923
18611
|
const { report, worktree, base, out } = args;
|
|
17924
|
-
const plan = JSON.parse(
|
|
18612
|
+
const plan = JSON.parse(readFileSync29(report, "utf8"));
|
|
17925
18613
|
const rootPkg = JSON.parse(
|
|
17926
|
-
|
|
18614
|
+
readFileSync29(`${worktree}/package.json`, "utf8")
|
|
17927
18615
|
);
|
|
17928
18616
|
const globs = rootPkg.workspaces ?? [];
|
|
17929
18617
|
const { unreachable, probes, revert } = planTestEfficacy(
|
|
@@ -17931,9 +18619,9 @@ async function runTestEfficacy(args) {
|
|
|
17931
18619
|
globs
|
|
17932
18620
|
);
|
|
17933
18621
|
for (const p of revert) {
|
|
17934
|
-
const norm =
|
|
17935
|
-
const root =
|
|
17936
|
-
if (isAbsolute5(p) || norm !== root && !norm.startsWith(root +
|
|
18622
|
+
const norm = join19(worktree, p);
|
|
18623
|
+
const root = join19(worktree, ".");
|
|
18624
|
+
if (isAbsolute5(p) || norm !== root && !norm.startsWith(root + sep7)) {
|
|
17937
18625
|
throw new Error(
|
|
17938
18626
|
`refusing to run: revert path escapes the worktree: ${JSON.stringify(p)}`
|
|
17939
18627
|
);
|
|
@@ -18204,7 +18892,7 @@ async function runTestEfficacy(args) {
|
|
|
18204
18892
|
} catch (e) {
|
|
18205
18893
|
removeError = e;
|
|
18206
18894
|
}
|
|
18207
|
-
if (
|
|
18895
|
+
if (existsSync13(probeTree)) {
|
|
18208
18896
|
cleanupFailure = probeCleanupFailureDetail(
|
|
18209
18897
|
probeTree,
|
|
18210
18898
|
removeError,
|
|
@@ -18303,7 +18991,7 @@ async function runTestEfficacy(args) {
|
|
|
18303
18991
|
findings,
|
|
18304
18992
|
cleanupFailure
|
|
18305
18993
|
};
|
|
18306
|
-
mkdirSync25(
|
|
18994
|
+
mkdirSync25(dirname22(out), { recursive: true });
|
|
18307
18995
|
writeFileSync24(out, JSON.stringify(result, null, 2), "utf8");
|
|
18308
18996
|
writeStdoutLine(
|
|
18309
18997
|
`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 +19069,8 @@ var testEfficacyCommand = {
|
|
|
18381
19069
|
|
|
18382
19070
|
// packages/cli/src/commands/review/test-plan.ts
|
|
18383
19071
|
init_esbuild_shims();
|
|
18384
|
-
import { existsSync as
|
|
18385
|
-
import { dirname as
|
|
19072
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync26, readFileSync as readFileSync30, writeFileSync as writeFileSync25 } from "node:fs";
|
|
19073
|
+
import { dirname as dirname23, join as join20, normalize, resolve as resolve24 } from "node:path";
|
|
18386
19074
|
var PLAN_NAME_RE = /(test\s*plan|\btesting\b|how\s+(?:has\s+this|to)\s+(?:been\s+)?test(?:ed)?|测试计划|测试方案|测试步骤)/i;
|
|
18387
19075
|
var HEADING_LINE_RE = /^(#{1,6})(?:[ \t](.*))?$/;
|
|
18388
19076
|
var BOLD_LINE_RE = /^\*\*([^*\n]+)\*\*:?\s*$/;
|
|
@@ -18585,7 +19273,7 @@ function rulePath(text, worktree, changed) {
|
|
|
18585
19273
|
};
|
|
18586
19274
|
}
|
|
18587
19275
|
const ignored = isGitIgnored(worktree, path3);
|
|
18588
|
-
if (
|
|
19276
|
+
if (existsSync14(join20(worktree, path3))) {
|
|
18589
19277
|
return {
|
|
18590
19278
|
kind: "path",
|
|
18591
19279
|
text,
|
|
@@ -18656,7 +19344,7 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
18656
19344
|
let rootScripts = [];
|
|
18657
19345
|
try {
|
|
18658
19346
|
const rootPkg = JSON.parse(
|
|
18659
|
-
|
|
19347
|
+
readFileSync30(join20(worktree, "package.json"), "utf8")
|
|
18660
19348
|
);
|
|
18661
19349
|
rootScripts = Object.keys(rootPkg.scripts ?? {});
|
|
18662
19350
|
} catch {
|
|
@@ -18670,7 +19358,7 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
18670
19358
|
for (const dir of skipped) {
|
|
18671
19359
|
try {
|
|
18672
19360
|
const pkg = JSON.parse(
|
|
18673
|
-
|
|
19361
|
+
readFileSync30(join20(worktree, dir, "package.json"), "utf8")
|
|
18674
19362
|
);
|
|
18675
19363
|
for (const s of Object.keys(pkg?.scripts ?? {})) defined.add(s);
|
|
18676
19364
|
} catch {
|
|
@@ -18765,7 +19453,7 @@ __name(fetchPrBody, "fetchPrBody");
|
|
|
18765
19453
|
function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
18766
19454
|
let plan;
|
|
18767
19455
|
try {
|
|
18768
|
-
plan = JSON.parse(
|
|
19456
|
+
plan = JSON.parse(readFileSync30(args.plan, "utf8"));
|
|
18769
19457
|
} catch (err) {
|
|
18770
19458
|
throw new Error(
|
|
18771
19459
|
`test-plan: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -18792,7 +19480,7 @@ function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
|
18792
19480
|
note: "the PR description has no Test Plan section"
|
|
18793
19481
|
};
|
|
18794
19482
|
}
|
|
18795
|
-
const worktree =
|
|
19483
|
+
const worktree = resolve24(args.worktree);
|
|
18796
19484
|
const changed = new Set(
|
|
18797
19485
|
(plan.files ?? []).map((f) => normalize(String(f.path)))
|
|
18798
19486
|
);
|
|
@@ -18800,7 +19488,7 @@ function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
|
18800
19488
|
if (args.buildTest) {
|
|
18801
19489
|
try {
|
|
18802
19490
|
buildTest = JSON.parse(
|
|
18803
|
-
|
|
19491
|
+
readFileSync30(args.buildTest, "utf8")
|
|
18804
19492
|
);
|
|
18805
19493
|
} catch {
|
|
18806
19494
|
buildTest = null;
|
|
@@ -18857,8 +19545,8 @@ var testPlanCommand = {
|
|
|
18857
19545
|
try {
|
|
18858
19546
|
const report = runTestPlan(args);
|
|
18859
19547
|
if (args.out) {
|
|
18860
|
-
mkdirSync26(
|
|
18861
|
-
writeFileSync25(
|
|
19548
|
+
mkdirSync26(dirname23(resolve24(args.out)), { recursive: true });
|
|
19549
|
+
writeFileSync25(resolve24(args.out), JSON.stringify(report, null, 2));
|
|
18862
19550
|
}
|
|
18863
19551
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
18864
19552
|
writeStderrLine(`test-plan: ${report.note}`);
|
|
@@ -18872,8 +19560,8 @@ var testPlanCommand = {
|
|
|
18872
19560
|
// packages/cli/src/commands/review/cleanup.ts
|
|
18873
19561
|
init_esbuild_shims();
|
|
18874
19562
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
18875
|
-
import { existsSync as
|
|
18876
|
-
import { join as
|
|
19563
|
+
import { existsSync as existsSync15, readFileSync as readFileSync31, readdirSync as readdirSync8, rmSync as rmSync10 } from "node:fs";
|
|
19564
|
+
import { join as join21 } from "node:path";
|
|
18877
19565
|
var AUTOMATION_MARKER = "<!-- qwen-";
|
|
18878
19566
|
function isAutomationComment(body) {
|
|
18879
19567
|
return (body ?? "").trimStart().startsWith(AUTOMATION_MARKER);
|
|
@@ -18904,7 +19592,7 @@ var OWNER_REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
|
18904
19592
|
function readAuditWindow(target, expectedPrNumber) {
|
|
18905
19593
|
let raw;
|
|
18906
19594
|
try {
|
|
18907
|
-
raw =
|
|
19595
|
+
raw = readFileSync31(tmpFile(target, "fetch.json"), "utf8");
|
|
18908
19596
|
} catch (err) {
|
|
18909
19597
|
const code = err.code;
|
|
18910
19598
|
return code === "ENOENT" ? { skip: "no fetch report" } : {
|
|
@@ -18951,7 +19639,7 @@ function readSubmitReceipt(target) {
|
|
|
18951
19639
|
try {
|
|
18952
19640
|
return new Set(
|
|
18953
19641
|
parseReceiptIds(
|
|
18954
|
-
|
|
19642
|
+
readFileSync31(tmpFile(target, "submit-receipt.json"), "utf8")
|
|
18955
19643
|
)
|
|
18956
19644
|
);
|
|
18957
19645
|
} catch {
|
|
@@ -19078,7 +19766,7 @@ function runCleanup(target) {
|
|
|
19078
19766
|
const prefix = tmpPrefix(target);
|
|
19079
19767
|
let tmpEntries = [];
|
|
19080
19768
|
try {
|
|
19081
|
-
tmpEntries =
|
|
19769
|
+
tmpEntries = existsSync15(REVIEW_TMP_DIR) ? readdirSync8(REVIEW_TMP_DIR) : [];
|
|
19082
19770
|
} catch (err) {
|
|
19083
19771
|
writeStderrLine(
|
|
19084
19772
|
`Failed to read ${REVIEW_TMP_DIR}: ${err.message}`
|
|
@@ -19086,7 +19774,7 @@ function runCleanup(target) {
|
|
|
19086
19774
|
}
|
|
19087
19775
|
for (const file of tmpEntries) {
|
|
19088
19776
|
if (!file.startsWith(prefix)) continue;
|
|
19089
|
-
const full =
|
|
19777
|
+
const full = join21(REVIEW_TMP_DIR, file);
|
|
19090
19778
|
try {
|
|
19091
19779
|
rmSync10(full, { recursive: true, force: true });
|
|
19092
19780
|
writeStdoutLine(`Removed temp file: ${full}`);
|
|
@@ -19119,10 +19807,10 @@ var cleanupCommand = {
|
|
|
19119
19807
|
|
|
19120
19808
|
// packages/cli/src/commands/review/cost-ledger.ts
|
|
19121
19809
|
init_esbuild_shims();
|
|
19122
|
-
import { mkdirSync as mkdirSync27, readFileSync as
|
|
19123
|
-
import { dirname as
|
|
19810
|
+
import { mkdirSync as mkdirSync27, readFileSync as readFileSync32, statSync as statSync15, writeFileSync as writeFileSync26 } from "node:fs";
|
|
19811
|
+
import { dirname as dirname24, join as join22, resolve as resolve25 } from "node:path";
|
|
19124
19812
|
function readUsage(file, floorMs) {
|
|
19125
|
-
const raw =
|
|
19813
|
+
const raw = readFileSync32(file, "utf8");
|
|
19126
19814
|
const events = [];
|
|
19127
19815
|
let launch = "";
|
|
19128
19816
|
for (const line of raw.split("\n")) {
|
|
@@ -19240,8 +19928,8 @@ function planFloorMs(planPath) {
|
|
|
19240
19928
|
let raw;
|
|
19241
19929
|
let floorMs;
|
|
19242
19930
|
try {
|
|
19243
|
-
raw =
|
|
19244
|
-
floorMs =
|
|
19931
|
+
raw = readFileSync32(planPath, "utf8");
|
|
19932
|
+
floorMs = statSync15(planPath).mtimeMs;
|
|
19245
19933
|
} catch (err) {
|
|
19246
19934
|
throw new Error(
|
|
19247
19935
|
`could not read the plan report ${planPath}: ${err.message}`
|
|
@@ -19263,7 +19951,7 @@ __name(planFloorMs, "planFloorMs");
|
|
|
19263
19951
|
function computeLedger(planPath, env = process.env) {
|
|
19264
19952
|
const floorMs = planFloorMs(planPath);
|
|
19265
19953
|
const { projectDir, sessionId, dir } = transcriptPaths(env);
|
|
19266
|
-
const chatFile =
|
|
19954
|
+
const chatFile = join22(projectDir, "chats", `${sessionId}.jsonl`);
|
|
19267
19955
|
let mainEvents;
|
|
19268
19956
|
try {
|
|
19269
19957
|
mainEvents = readUsage(chatFile, floorMs).events;
|
|
@@ -19288,10 +19976,10 @@ function computeLedger(planPath, env = process.env) {
|
|
|
19288
19976
|
const agents = [];
|
|
19289
19977
|
const agentEvents = [];
|
|
19290
19978
|
for (const f of files) {
|
|
19291
|
-
const full =
|
|
19979
|
+
const full = join22(dir, f);
|
|
19292
19980
|
let mtimeMs;
|
|
19293
19981
|
try {
|
|
19294
|
-
mtimeMs =
|
|
19982
|
+
mtimeMs = statSync15(full).mtimeMs;
|
|
19295
19983
|
} catch {
|
|
19296
19984
|
continue;
|
|
19297
19985
|
}
|
|
@@ -19399,7 +20087,7 @@ function runCostLedger(args) {
|
|
|
19399
20087
|
}
|
|
19400
20088
|
if (args.out !== void 0 && args.out.length > 0) {
|
|
19401
20089
|
try {
|
|
19402
|
-
mkdirSync27(
|
|
20090
|
+
mkdirSync27(dirname24(resolve25(args.out)), { recursive: true });
|
|
19403
20091
|
writeFileSync26(args.out, JSON.stringify(ledger, null, 2));
|
|
19404
20092
|
} catch (err) {
|
|
19405
20093
|
writeStderrLineSafe(
|
|
@@ -19433,8 +20121,8 @@ var costLedgerCommand = {
|
|
|
19433
20121
|
// packages/cli/src/commands/review/run.ts
|
|
19434
20122
|
init_esbuild_shims();
|
|
19435
20123
|
import { spawn, execFileSync as execFileSync6 } from "node:child_process";
|
|
19436
|
-
import { readdirSync as
|
|
19437
|
-
import { dirname as
|
|
20124
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync33, realpathSync as realpathSync6, statSync as statSync16 } from "node:fs";
|
|
20125
|
+
import { dirname as dirname25, join as join23, resolve as resolve26 } from "node:path";
|
|
19438
20126
|
var COMPOSED_PATTERN = /^qwen-review-.*composed\.json$/;
|
|
19439
20127
|
var COMPOSED_POLL_MS = 250;
|
|
19440
20128
|
var SIGNAL_EXIT_CODES = {
|
|
@@ -19462,16 +20150,16 @@ function newestArtifactSince(dir, pattern, startMs) {
|
|
|
19462
20150
|
let best = null;
|
|
19463
20151
|
let names;
|
|
19464
20152
|
try {
|
|
19465
|
-
names =
|
|
20153
|
+
names = readdirSync9(dir);
|
|
19466
20154
|
} catch {
|
|
19467
20155
|
return null;
|
|
19468
20156
|
}
|
|
19469
20157
|
for (const name of names) {
|
|
19470
20158
|
if (!pattern.test(name)) continue;
|
|
19471
|
-
const path3 =
|
|
20159
|
+
const path3 = join23(dir, name);
|
|
19472
20160
|
let mtime;
|
|
19473
20161
|
try {
|
|
19474
|
-
mtime =
|
|
20162
|
+
mtime = statSync16(path3).mtimeMs;
|
|
19475
20163
|
} catch {
|
|
19476
20164
|
continue;
|
|
19477
20165
|
}
|
|
@@ -19489,7 +20177,7 @@ function exitCodeFor(completed, event2, failOn) {
|
|
|
19489
20177
|
__name(exitCodeFor, "exitCodeFor");
|
|
19490
20178
|
function readComposed(path3) {
|
|
19491
20179
|
try {
|
|
19492
|
-
const parsed = JSON.parse(
|
|
20180
|
+
const parsed = JSON.parse(readFileSync33(path3, "utf8"));
|
|
19493
20181
|
return typeof parsed.event === "string" ? parsed : null;
|
|
19494
20182
|
} catch {
|
|
19495
20183
|
return null;
|
|
@@ -19520,7 +20208,7 @@ function childEnv() {
|
|
|
19520
20208
|
return env;
|
|
19521
20209
|
}
|
|
19522
20210
|
try {
|
|
19523
|
-
if (
|
|
20211
|
+
if (dirname25(realpathSync6(inherited)) === dirname25(realpathSync6(ownEntry))) {
|
|
19524
20212
|
return env;
|
|
19525
20213
|
}
|
|
19526
20214
|
} catch {
|
|
@@ -19642,8 +20330,8 @@ async function runReview(args) {
|
|
|
19642
20330
|
downgraded: composed?.downgraded ?? false,
|
|
19643
20331
|
downgradedFrom: composed?.downgradedFrom ?? null,
|
|
19644
20332
|
remediation: composed?.remediation ?? [],
|
|
19645
|
-
composedPath: composedPath ?
|
|
19646
|
-
reportPath: reportPath ?
|
|
20333
|
+
composedPath: composedPath ? resolve26(composedPath) : null,
|
|
20334
|
+
reportPath: reportPath ? resolve26(reportPath) : null,
|
|
19647
20335
|
childExitCode,
|
|
19648
20336
|
childSignal,
|
|
19649
20337
|
timedOut,
|
|
@@ -19657,7 +20345,7 @@ async function runReview(args) {
|
|
|
19657
20345
|
writeStdoutLine(result.verdictLine ?? `Event: ${result.event}`);
|
|
19658
20346
|
if (result.reportPath) writeStdoutLine(`Report: ${result.reportPath}`);
|
|
19659
20347
|
} else {
|
|
19660
|
-
const detail = composedPath !== null ? `a composed verdict was found at ${
|
|
20348
|
+
const detail = composedPath !== null ? `a composed verdict was found at ${resolve26(composedPath)} but could not be parsed` : "no composed verdict was produced";
|
|
19661
20349
|
writeStdoutLine(
|
|
19662
20350
|
timedOut ? "Review did not complete: timed out." : `Review did not complete: ${detail}${childExitCode !== null ? ` (CLI exit ${childExitCode})` : ""}${childSignal !== null ? ` (killed by ${childSignal})` : ""}.`
|
|
19663
20351
|
);
|
|
@@ -19723,33 +20411,33 @@ var runCommand = {
|
|
|
19723
20411
|
// packages/cli/src/commands/review/save-artifact.ts
|
|
19724
20412
|
init_esbuild_shims();
|
|
19725
20413
|
import {
|
|
19726
|
-
existsSync as
|
|
20414
|
+
existsSync as existsSync16,
|
|
19727
20415
|
lstatSync as lstatSync6,
|
|
19728
20416
|
mkdirSync as mkdirSync28,
|
|
19729
|
-
readFileSync as
|
|
19730
|
-
statSync as
|
|
20417
|
+
readFileSync as readFileSync34,
|
|
20418
|
+
statSync as statSync17
|
|
19731
20419
|
} from "node:fs";
|
|
19732
20420
|
import {
|
|
19733
|
-
dirname as
|
|
20421
|
+
dirname as dirname26,
|
|
19734
20422
|
isAbsolute as isAbsolute6,
|
|
19735
|
-
join as
|
|
19736
|
-
relative as
|
|
19737
|
-
resolve as
|
|
19738
|
-
sep as
|
|
20423
|
+
join as join24,
|
|
20424
|
+
relative as relative6,
|
|
20425
|
+
resolve as resolve27,
|
|
20426
|
+
sep as sep8,
|
|
19739
20427
|
toNamespacedPath
|
|
19740
20428
|
} from "node:path";
|
|
19741
20429
|
import { isDeepStrictEqual } from "node:util";
|
|
19742
20430
|
function workspaceRoot(explicit) {
|
|
19743
|
-
return
|
|
20431
|
+
return resolve27(explicit ?? process.cwd());
|
|
19744
20432
|
}
|
|
19745
20433
|
__name(workspaceRoot, "workspaceRoot");
|
|
19746
20434
|
function isWithin(parent, child) {
|
|
19747
|
-
const rel =
|
|
19748
|
-
return rel === "" || !isAbsolute6(rel) && rel !== ".." && !rel.startsWith(`..${
|
|
20435
|
+
const rel = relative6(parent, child);
|
|
20436
|
+
return rel === "" || !isAbsolute6(rel) && rel !== ".." && !rel.startsWith(`..${sep8}`);
|
|
19749
20437
|
}
|
|
19750
20438
|
__name(isWithin, "isWithin");
|
|
19751
20439
|
function workspacePath(root, value, label2) {
|
|
19752
|
-
const absolute =
|
|
20440
|
+
const absolute = resolve27(root, value);
|
|
19753
20441
|
if (!isWithin(root, absolute)) {
|
|
19754
20442
|
throw new Error(
|
|
19755
20443
|
`${label2} must be inside the workspace: ${JSON.stringify(value)}.`
|
|
@@ -19759,11 +20447,11 @@ function workspacePath(root, value, label2) {
|
|
|
19759
20447
|
}
|
|
19760
20448
|
__name(workspacePath, "workspacePath");
|
|
19761
20449
|
function rejectSymlinkPath(root, path3, label2) {
|
|
19762
|
-
const rel =
|
|
20450
|
+
const rel = relative6(root, path3);
|
|
19763
20451
|
let current = root;
|
|
19764
|
-
for (const segment of rel.split(
|
|
19765
|
-
current =
|
|
19766
|
-
if (
|
|
20452
|
+
for (const segment of rel.split(sep8)) {
|
|
20453
|
+
current = join24(current, segment);
|
|
20454
|
+
if (existsSync16(current) && lstatSync6(current).isSymbolicLink()) {
|
|
19767
20455
|
throw new Error(`${label2} must not traverse a symbolic link.`);
|
|
19768
20456
|
}
|
|
19769
20457
|
}
|
|
@@ -19771,15 +20459,15 @@ function rejectSymlinkPath(root, path3, label2) {
|
|
|
19771
20459
|
__name(rejectSymlinkPath, "rejectSymlinkPath");
|
|
19772
20460
|
function sameFile2(left, right) {
|
|
19773
20461
|
if (left === right) return true;
|
|
19774
|
-
if (!
|
|
19775
|
-
const leftStat =
|
|
19776
|
-
const rightStat =
|
|
20462
|
+
if (!existsSync16(left) || !existsSync16(right)) return false;
|
|
20463
|
+
const leftStat = statSync17(left);
|
|
20464
|
+
const rightStat = statSync17(right);
|
|
19777
20465
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
19778
20466
|
}
|
|
19779
20467
|
__name(sameFile2, "sameFile");
|
|
19780
20468
|
function readText(path3, label2) {
|
|
19781
20469
|
try {
|
|
19782
|
-
return
|
|
20470
|
+
return readFileSync34(path3, "utf8");
|
|
19783
20471
|
} catch (error) {
|
|
19784
20472
|
throw new Error(
|
|
19785
20473
|
`Could not read the ${label2} file at ${JSON.stringify(path3)}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -19905,7 +20593,7 @@ function saveReviewArtifact(args) {
|
|
|
19905
20593
|
const composedPath = workspacePath(root, args.composed, "Composed input");
|
|
19906
20594
|
const reportPath = workspacePath(root, args.report, "Markdown report");
|
|
19907
20595
|
const outputPath = workspacePath(root, args.out, "Output");
|
|
19908
|
-
const reviewsRoot =
|
|
20596
|
+
const reviewsRoot = resolve27(root, REVIEWS_DIR);
|
|
19909
20597
|
if (!isWithin(reviewsRoot, reportPath) || reportPath === reviewsRoot) {
|
|
19910
20598
|
throw new Error(
|
|
19911
20599
|
`Markdown report must be a file under ${JSON.stringify(REVIEWS_DIR)}: ${JSON.stringify(args.report)}.`
|
|
@@ -19946,7 +20634,7 @@ function saveReviewArtifact(args) {
|
|
|
19946
20634
|
const verdict = validateVerdict(readJson2(composedPath, "composed verdict"));
|
|
19947
20635
|
let reportIsFile;
|
|
19948
20636
|
try {
|
|
19949
|
-
reportIsFile =
|
|
20637
|
+
reportIsFile = statSync17(reportPath).isFile();
|
|
19950
20638
|
} catch {
|
|
19951
20639
|
}
|
|
19952
20640
|
if (reportIsFile === false) {
|
|
@@ -19955,7 +20643,7 @@ function saveReviewArtifact(args) {
|
|
|
19955
20643
|
);
|
|
19956
20644
|
}
|
|
19957
20645
|
readText(reportPath, "Markdown report");
|
|
19958
|
-
const markdownReportPath =
|
|
20646
|
+
const markdownReportPath = relative6(root, reportPath).split(sep8).join("/");
|
|
19959
20647
|
const document = {
|
|
19960
20648
|
schemaVersion: 1,
|
|
19961
20649
|
target: args.target,
|
|
@@ -19966,7 +20654,7 @@ function saveReviewArtifact(args) {
|
|
|
19966
20654
|
outcomesRecorded: findings.outcomesRecorded,
|
|
19967
20655
|
markdownReportPath
|
|
19968
20656
|
};
|
|
19969
|
-
mkdirSync28(
|
|
20657
|
+
mkdirSync28(dirname26(outputPath), { recursive: true });
|
|
19970
20658
|
atomicWriteFileSync(
|
|
19971
20659
|
toNamespacedPath(outputPath),
|
|
19972
20660
|
`${JSON.stringify(document, null, 2)}
|
|
@@ -19975,7 +20663,7 @@ function saveReviewArtifact(args) {
|
|
|
19975
20663
|
);
|
|
19976
20664
|
return {
|
|
19977
20665
|
path: outputPath,
|
|
19978
|
-
workspacePath:
|
|
20666
|
+
workspacePath: relative6(root, outputPath).split(sep8).join("/")
|
|
19979
20667
|
};
|
|
19980
20668
|
}
|
|
19981
20669
|
__name(saveReviewArtifact, "saveReviewArtifact");
|
|
@@ -20022,9 +20710,9 @@ var saveArtifactCommand = {
|
|
|
20022
20710
|
var reviewCommand = {
|
|
20023
20711
|
command: "review",
|
|
20024
20712
|
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(
|
|
20713
|
+
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
20714
|
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."
|
|
20715
|
+
"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
20716
|
).version(false), "builder"),
|
|
20029
20717
|
handler: /* @__PURE__ */ __name(() => {
|
|
20030
20718
|
}, "handler")
|
|
@@ -20224,10 +20912,10 @@ var updateCommand3 = {
|
|
|
20224
20912
|
stdioHelpers,
|
|
20225
20913
|
{ updateEventEmitter }
|
|
20226
20914
|
] = await Promise.all([
|
|
20227
|
-
import("./settings-
|
|
20228
|
-
import("./updateCheck-
|
|
20229
|
-
import("./installationInfo-
|
|
20230
|
-
import("./standalone-update-
|
|
20915
|
+
import("./settings-V7BR3RKP.js"),
|
|
20916
|
+
import("./updateCheck-YZ2CRCFC.js"),
|
|
20917
|
+
import("./installationInfo-VGBXMYLY.js"),
|
|
20918
|
+
import("./standalone-update-QGIKHATD.js"),
|
|
20231
20919
|
import("./stdioHelpers-7A2EE64Z.js"),
|
|
20232
20920
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
20233
20921
|
]);
|
|
@@ -20658,8 +21346,8 @@ async function parseArguments() {
|
|
|
20658
21346
|
default: false
|
|
20659
21347
|
}).option("channel", {
|
|
20660
21348
|
type: "string",
|
|
20661
|
-
choices: ["VSCode", "ACP", "SDK", "CI", "desktop"],
|
|
20662
|
-
description: "Channel identifier (VSCode, ACP, SDK, CI, desktop)"
|
|
21349
|
+
choices: ["VSCode", "ACP", "SDK", "CI", "desktop", "daemon"],
|
|
21350
|
+
description: "Channel identifier (VSCode, ACP, SDK, CI, desktop, daemon)"
|
|
20663
21351
|
}).option("allowed-mcp-server-names", {
|
|
20664
21352
|
type: "array",
|
|
20665
21353
|
string: true,
|
|
@@ -20907,7 +21595,7 @@ async function parseArguments() {
|
|
|
20907
21595
|
}
|
|
20908
21596
|
}
|
|
20909
21597
|
if ((result["acp"] || result["experimentalAcp"]) && !result["channel"]) {
|
|
20910
|
-
result["channel"] =
|
|
21598
|
+
result["channel"] = resolveAcpChannelFallback();
|
|
20911
21599
|
}
|
|
20912
21600
|
return result;
|
|
20913
21601
|
}
|
|
@@ -21394,7 +22082,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
21394
22082
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
21395
22083
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
21396
22084
|
terminalImageRenderSupportProvider: interactive ? async () => {
|
|
21397
|
-
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-
|
|
22085
|
+
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-TLDNACQY.js");
|
|
21398
22086
|
return getTerminalImageRenderSupport();
|
|
21399
22087
|
} : void 0,
|
|
21400
22088
|
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|