@qwen-code/qwen-code 0.21.4 → 0.21.5-nightly.20260805.32e274157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/configuration/model-providers.md +8 -7
- package/bundled/qc-helper/docs/configuration/settings.md +16 -16
- package/bundled/qc-helper/docs/features/code-review.md +4 -0
- package/bundled/qc-helper/docs/features/headless.md +31 -0
- package/bundled/qc-helper/docs/features/mcp.md +11 -3
- package/bundled/qc-helper/docs/qwen-serve.md +75 -0
- package/bundled/review/SKILL.md +90 -52
- package/chunks/{MaxSizedBox-5XDFQHTQ.js → MaxSizedBox-H44SGRP7.js} +17 -16
- package/chunks/{StandaloneSessionPicker-DLADA54K.js → StandaloneSessionPicker-T5FQMYD3.js} +31 -30
- package/chunks/{acpAgent-MVEFZSBS.js → acpAgent-J474KXVM.js} +849 -313
- package/chunks/{agent-RB6LCRZX.js → agent-SC23IV5L.js} +17 -16
- package/chunks/{agent-headless-272ZACJV.js → agent-headless-2CHR5WJP.js} +17 -16
- package/chunks/{artifact-tool-TBOYEKTY.js → artifact-tool-RROCCJDA.js} +1 -1
- package/chunks/{askUserQuestion-23Y5WZFJ.js → askUserQuestion-2EPPBPUZ.js} +1 -1
- package/chunks/{bridge-GXUXFSHK.js → bridge-BLHYPCCR.js} +21 -19
- package/chunks/{channel-settings-store-5UA2SABE.js → channel-settings-store-CDOZ7GCP.js} +22 -21
- package/chunks/{channel-worker-group-NDG4WOOZ.js → channel-worker-group-SVGPDH2C.js} +3 -2
- package/chunks/{channel-worker-manager-ZCW6UW34.js → channel-worker-manager-72ZK2GTS.js} +3 -2
- package/chunks/{channel-worker-supervisor-ATGFTZRN.js → channel-worker-supervisor-NUEDVHX4.js} +2 -1
- package/chunks/{chunk-PWCQRLM5.js → chunk-2AGOQ7QO.js} +1 -1
- package/chunks/{chunk-AFJSRJTO.js → chunk-2B6FBVWE.js} +1 -1
- package/chunks/{chunk-XPAY4EMH.js → chunk-2OSE7Q5O.js} +3 -3
- package/chunks/{chunk-DHNFB7NC.js → chunk-2QOLRESU.js} +5 -5
- package/chunks/{chunk-UWSXFI6E.js → chunk-2U7GPHA6.js} +6 -2
- package/chunks/{chunk-CIUUYB23.js → chunk-3DTM3RPU.js} +1 -1
- package/chunks/{chunk-X6QNZOTC.js → chunk-3PRJYMXC.js} +2 -2
- package/chunks/{chunk-6KQUOXT5.js → chunk-3XDH6PZM.js} +7 -7
- package/chunks/{chunk-DJA7YBLJ.js → chunk-56MC5OM7.js} +2 -2
- package/chunks/{chunk-B3EBXISV.js → chunk-5DVP76WL.js} +90 -7
- package/chunks/{chunk-2T3RYG4L.js → chunk-5KDLX7ER.js} +919 -323
- package/chunks/{chunk-O2ZYHG33.js → chunk-5L6CQ4ZU.js} +131 -67
- package/chunks/{chunk-E2SYUEIA.js → chunk-5OAMVWFL.js} +874 -375
- package/chunks/{chunk-LPLMUGIM.js → chunk-5X76FZLI.js} +5 -5
- package/chunks/{chunk-M2L4TMH3.js → chunk-6HTEECQY.js} +3 -3
- package/chunks/{chunk-KHSJSMFS.js → chunk-6I6WUVYI.js} +1 -1
- package/chunks/{chunk-LLMGP5IC.js → chunk-6WBWIPBF.js} +2 -2
- package/chunks/{chunk-PQ5JFCNL.js → chunk-762UTZQZ.js} +3 -3
- package/chunks/{chunk-HBCKZF2A.js → chunk-7EW7CYLA.js} +1 -1
- package/chunks/{chunk-4PZ7SPD5.js → chunk-7FKLLD4X.js} +1 -1
- package/chunks/{chunk-XSOAW7FC.js → chunk-AE7AKP3E.js} +6 -6
- package/chunks/{chunk-UATJZOAJ.js → chunk-ASS3UQB5.js} +3 -3
- package/chunks/{chunk-XGA6XHH3.js → chunk-AXOFMDZC.js} +3 -3
- package/chunks/chunk-BKHCW2BI.js +41 -0
- package/chunks/{chunk-DZPOYHBT.js → chunk-D6FISK43.js} +1 -1
- package/chunks/{chunk-CFDR3GNL.js → chunk-D7D7RXIJ.js} +11 -0
- package/chunks/{chunk-FPPVCCAH.js → chunk-DNPP267F.js} +1 -1
- package/chunks/{chunk-I32URQI7.js → chunk-EA2CKB6L.js} +5 -5
- package/chunks/{chunk-C5YFS6VR.js → chunk-EL4W7MGQ.js} +4 -4
- package/chunks/{chunk-QXTGHZCX.js → chunk-FDLXWNCE.js} +3 -3
- package/chunks/{chunk-PCVMRBLN.js → chunk-FFCSRU3F.js} +1 -1
- package/chunks/{chunk-SV5X2EUV.js → chunk-FMU2QVA5.js} +1 -1
- package/chunks/{chunk-2ON2O4MD.js → chunk-FV2JYSWS.js} +28 -3
- package/chunks/{chunk-KB6VSG2U.js → chunk-GXP44JOS.js} +7 -7
- package/chunks/{chunk-BC4LTKEG.js → chunk-HP6MKLWU.js} +1 -1
- package/chunks/{chunk-YXEVDA66.js → chunk-HU5TUALO.js} +110 -22
- package/chunks/{chunk-2JN5V3I7.js → chunk-ITZK3L4S.js} +1 -1
- package/chunks/{chunk-5XGI4IPK.js → chunk-JEVHOCCA.js} +4 -4
- package/chunks/{chunk-6ME3PVMM.js → chunk-JNFWMBG6.js} +5 -5
- package/chunks/{chunk-3PHUGFPH.js → chunk-JXPOBM4B.js} +1 -1
- package/chunks/{chunk-TXZDRD36.js → chunk-LCCBAGRT.js} +5 -5
- package/chunks/{chunk-G7XXKQYS.js → chunk-LKRMNRSN.js} +27 -1
- package/chunks/{chunk-DOCBJIBL.js → chunk-MB3ILUB7.js} +1 -1
- package/chunks/{chunk-HFVW54NL.js → chunk-MBEMTXQT.js} +9 -2
- package/chunks/{chunk-RNKGMZEW.js → chunk-MFTOMYE2.js} +1 -1
- package/chunks/{chunk-RPYYTL7E.js → chunk-MGSSJT27.js} +2 -2
- package/chunks/{chunk-URVJ4AZC.js → chunk-MKMUBBEX.js} +1 -1
- package/chunks/{chunk-RL2NPV5E.js → chunk-N5QPOGRQ.js} +1 -1
- package/chunks/{chunk-2CCUHZP5.js → chunk-N7PF4KZR.js} +2 -2
- package/chunks/{chunk-JDJ7SC4E.js → chunk-NMBDPO63.js} +255 -197
- package/chunks/{chunk-M6RNMBUO.js → chunk-NQZ5IVLH.js} +4 -4
- package/chunks/{chunk-FV4TUUDE.js → chunk-O4WOWHMZ.js} +1 -1
- package/chunks/{chunk-GDREW3U5.js → chunk-OIVG6IHL.js} +2 -2
- package/chunks/{chunk-IMGNGOGC.js → chunk-PQ2J56BJ.js} +3 -3
- package/chunks/{chunk-EJXATV5R.js → chunk-PWFDZA5A.js} +2 -2
- package/chunks/{chunk-OOPFAIWP.js → chunk-Q7EXR3W2.js} +1 -1
- package/chunks/{chunk-4CTV3FZH.js → chunk-QJL2AQZI.js} +23 -19
- package/chunks/{chunk-SBBHZ3YT.js → chunk-QKWPXGW4.js} +1 -1
- package/chunks/{chunk-HI4YGRJD.js → chunk-RDICVTQC.js} +3 -3
- package/chunks/{chunk-ZRQY5BBS.js → chunk-REAWLQAU.js} +10 -10
- package/chunks/{chunk-BOWKLLWA.js → chunk-SOBA6GIW.js} +3 -3
- package/chunks/{chunk-WDLQGFWP.js → chunk-TYWI5NXY.js} +27 -27
- package/chunks/{chunk-A7PONO5G.js → chunk-URJHXOSO.js} +2 -2
- package/chunks/{chunk-C6FU76AA.js → chunk-V3BNVUFI.js} +1 -1
- package/chunks/{chunk-G6KI6B5L.js → chunk-VF6WPN4R.js} +1 -1
- package/chunks/{chunk-AWTLFUVN.js → chunk-VT27B2XS.js} +13 -13
- package/chunks/{chunk-O4IWFYUW.js → chunk-VY4TEQQ6.js} +4 -4
- package/chunks/{chunk-EIAPOG76.js → chunk-WECYW5EE.js} +4 -4
- package/chunks/{chunk-PDDYAXL2.js → chunk-WIRAPZ62.js} +7 -0
- package/chunks/chunk-WOJZWRAZ.js +123 -0
- package/chunks/{chunk-7UXI6P72.js → chunk-WVAESIM6.js} +2 -2
- package/chunks/{chunk-P5UJMCVS.js → chunk-XIDYVC4P.js} +4 -4
- package/chunks/{chunk-THLV7YGY.js → chunk-XIKKANF4.js} +2 -2
- package/chunks/{chunk-FHPKHXHT.js → chunk-XNZBXQCG.js} +4 -0
- package/chunks/{chunk-ZLJQIGCH.js → chunk-XZCMQUOF.js} +8 -0
- package/chunks/{chunk-PQEIKQXN.js → chunk-YJMFRTLV.js} +24 -6
- package/chunks/{chunk-QZQ72YF6.js → chunk-Z26UXKZE.js} +1 -1
- package/chunks/{chunk-VA5NLVPT.js → chunk-Z7JILXGX.js} +1 -1
- package/chunks/{chunk-UEJESCS7.js → chunk-ZPPP6VCL.js} +1 -1
- package/chunks/{computer-use-MDOMIVTL.js → computer-use-ENYMKQAI.js} +17 -16
- package/chunks/{config-utils-E3ZQTHGM.js → config-utils-LIRO7NSU.js} +2 -2
- package/chunks/{contextCommand-FCK3CB37.js → contextCommand-E7XMHU6M.js} +19 -18
- package/chunks/{core-runtime-UHRHHU2O.js → core-runtime-KDIRQ63A.js} +17 -16
- package/chunks/{create-sub-session-J32WC64U.js → create-sub-session-6EWLAZD5.js} +1 -1
- package/chunks/{create-sub-session-MIXUVLWW.js → create-sub-session-VVEL77UF.js} +17 -16
- package/chunks/{cron-create-HMFSHIAR.js → cron-create-CCRIULJE.js} +1 -1
- package/chunks/{cron-delete-ZJFHOX57.js → cron-delete-FCFW6BGP.js} +1 -1
- package/chunks/{cron-list-ZEX2NBMN.js → cron-list-QDBVCHRF.js} +1 -1
- package/chunks/{daemon-status-provider-6LC7LUNR.js → daemon-status-provider-4LMCSLZ4.js} +25 -23
- package/chunks/{daemon-trust-policy-Y36HGRAM.js → daemon-trust-policy-XLONWB2C.js} +22 -21
- package/chunks/{daemon-trust-policy-monitor-ROTBBDOH.js → daemon-trust-policy-monitor-FHFZ3NNG.js} +22 -21
- package/chunks/{deferred-core-runtime-ZQ4JIAJD.js → deferred-core-runtime-QNEBJ3DP.js} +17 -16
- package/chunks/{display-image-2WOG27DY.js → display-image-GUJA352B.js} +2 -2
- package/chunks/{earlyInputCapture-GPRUNXTP.js → earlyInputCapture-OG5IUF4R.js} +17 -16
- package/chunks/{edit-YK3UP6D2.js → edit-E2WNOITJ.js} +18 -17
- package/chunks/{enter-worktree-QMVQW7UG.js → enter-worktree-RMCBAAA2.js} +17 -16
- package/chunks/{enterPlanMode-TZAYQ5MP.js → enterPlanMode-GISFJA3O.js} +17 -16
- package/chunks/{environment-3UQURCZG.js → environment-JXTQGYDN.js} +19 -18
- package/chunks/{errors-VBIMTNNI.js → errors-2AYTYCQ3.js} +19 -18
- package/chunks/{exit-worktree-4EC7LBBC.js → exit-worktree-HORS3V7Z.js} +17 -16
- package/chunks/{exitPlanMode-K5Y3REU2.js → exitPlanMode-V75Y36HJ.js} +17 -16
- package/chunks/external-tool-guard-provider-5HTGOPGU.js +273 -0
- package/chunks/{fast-path-KS6IE7YR.js → fast-path-HURC6JUT.js} +5 -5
- package/chunks/{gemini-LTUCUOJH.js → gemini-WHMD4RGY.js} +70 -55
- package/chunks/{geminiContentGenerator-M3HJTHKR.js → geminiContentGenerator-DZB3GPNQ.js} +1 -1
- package/chunks/{glob-SKUYGTF2.js → glob-IGTV723M.js} +17 -16
- package/chunks/{goal-tools-SPQ5M6D3.js → goal-tools-3AZKX5WQ.js} +2 -18
- package/chunks/{grep-SQ7RD7SV.js → grep-SJ2NYUCD.js} +17 -16
- package/chunks/{handleAutoUpdate-OK7OX23A.js → handleAutoUpdate-NPBKROGA.js} +21 -20
- package/chunks/{i18n-P77YBKY4.js → i18n-CBSMJZ3Z.js} +18 -17
- package/chunks/{image-gen-2ZWPS42A.js → image-gen-KNKDTUEN.js} +2 -2
- package/chunks/{initializer-PIOYXVW7.js → initializer-JT5P3IQF.js} +22 -21
- package/chunks/{installationInfo-IWMM6DPV.js → installationInfo-CZVCKPPZ.js} +18 -17
- package/chunks/{list-3DCR4TRI.js → list-MT7T6JVH.js} +25 -24
- package/chunks/{list-agents-TWEGRJWO.js → list-agents-GC4BRET7.js} +1 -1
- package/chunks/{loadedSettingsAdapter-EJC6CU5N.js → loadedSettingsAdapter-D4JFGYYQ.js} +22 -21
- package/chunks/{loggingContentGenerator-2JEFU25T.js → loggingContentGenerator-SFT5CMPU.js} +9 -8
- package/chunks/{loop-wakeup-6LLEOQYV.js → loop-wakeup-SQQSBMEY.js} +2 -2
- package/chunks/{ls-H5WX22VK.js → ls-63CC3NNX.js} +1 -1
- package/chunks/{lsp-G6FXYEIS.js → lsp-P6NVJVNT.js} +1 -1
- package/chunks/{managed-npm-update-EGVQPSBR.js → managed-npm-update-YHJW6SGD.js} +18 -17
- package/chunks/{mcp-KFFH2MBV.js → mcp-53X2M7XL.js} +22 -21
- package/chunks/{monitor-6Y3NDMTI.js → monitor-I43P3MNV.js} +17 -16
- package/chunks/{nonInteractiveCli-426IQDPE.js → nonInteractiveCli-UADCDERF.js} +50 -48
- package/chunks/{notebook-edit-373IQQLE.js → notebook-edit-WKZUONWV.js} +18 -17
- package/chunks/{openaiContentGenerator-PGFSOMIQ.js → openaiContentGenerator-YHF3FIYI.js} +9 -8
- package/chunks/{pidfile-Y4INDMHG.js → pidfile-VU37FJS4.js} +17 -16
- package/chunks/{processUtils-6BCPCJZW.js → processUtils-VIQVTDWH.js} +2 -2
- package/chunks/{qwenContentGenerator-QC3KSHSX.js → qwenContentGenerator-46476NL4.js} +18 -17
- package/chunks/{qwenOAuth2-IOAXKJ3L.js → qwenOAuth2-D62OJZFU.js} +1 -1
- package/chunks/{read-file-2T54FYZV.js → read-file-6PSNROKB.js} +7 -6
- package/chunks/{read-mcp-resource-DRZSI3HE.js → read-mcp-resource-RTSSEER5.js} +1 -1
- package/chunks/{record-artifact-IPIRWMFY.js → record-artifact-E6AWQU2Z.js} +2 -2
- package/chunks/{resumeHistoryUtils-O62RDCZ3.js → resumeHistoryUtils-QFD6LB7N.js} +20 -19
- package/chunks/{ripGrep-3H72KY7S.js → ripGrep-4WZJEOGB.js} +17 -16
- package/chunks/{run-qwen-serve-3AIDNNHO.js → run-qwen-serve-SEL3TISE.js} +72 -36
- package/chunks/{runtime-AZ4EHHFV.js → runtime-T6JAS7GL.js} +25 -24
- package/chunks/{scheduler-L4UUCU4Z.js → scheduler-ZCTDMJJV.js} +17 -16
- package/chunks/{sdk-exporters-http-IKNWQJNV.js → sdk-exporters-http-IL2346MJ.js} +6 -2
- package/chunks/{sdk-impl-7CUUMQDB.js → sdk-impl-SYKGVWOZ.js} +2 -2
- package/chunks/{send-message-LHJLVWFD.js → send-message-TL6FIMMN.js} +3 -3
- package/chunks/{serve-CLXGSYOE.js → serve-A7B6VWK7.js} +23 -21
- package/chunks/{server-MEAE3WMM.js → server-6CCTTLO4.js} +170 -63
- package/chunks/{session-OSLD2LT5.js → session-3YYXW6MZ.js} +51 -49
- package/chunks/{settings-ILWAOKA4.js → settings-KWYWA3BS.js} +21 -20
- package/chunks/{shell-RT5DBH6B.js → shell-6SUYJURL.js} +17 -16
- package/chunks/{skill-LVGA3ATZ.js → skill-ZIQFS6YD.js} +8 -7
- package/chunks/{skill-settings-WTZE7EPE.js → skill-settings-23IFV7S3.js} +21 -20
- package/chunks/{spawnChannel-BOBS7DVM.js → spawnChannel-AI7QA35U.js} +20 -18
- package/chunks/{standalone-update-Y5JB4S2K.js → standalone-update-WNXRFLEA.js} +19 -18
- package/chunks/{startInteractiveUI-ZV25CD2S.js → startInteractiveUI-NPZU6YXV.js} +76 -71
- package/chunks/{syntheticOutput-EYL7DWO7.js → syntheticOutput-BN7E626U.js} +2 -2
- package/chunks/{task-create-4ALZMGP5.js → task-create-2X4UP4F3.js} +4 -4
- package/chunks/{task-list-6CVQPORX.js → task-list-WOLJPZ64.js} +1 -1
- package/chunks/{task-stop-Y5ZTFVRX.js → task-stop-TNXRNAL2.js} +1 -1
- package/chunks/{task-update-IKCEEWJ6.js → task-update-VDUSN36E.js} +4 -4
- package/chunks/{team-create-ZVPQIXCP.js → team-create-CMF2RRF2.js} +17 -16
- package/chunks/{team-delete-CE7DC53R.js → team-delete-D2VMSDOT.js} +1 -1
- package/chunks/{team-plan-approval-5UHUBY3W.js → team-plan-approval-5EET4S3I.js} +17 -16
- package/chunks/{terminal-image-renderer-NWC2RALG.js → terminal-image-renderer-TCEAHDFE.js} +18 -17
- package/chunks/{theme-manager-5KICSBOB.js → theme-manager-RPYRQJLX.js} +17 -16
- package/chunks/{todoWrite-FTZWQRZH.js → todoWrite-MHWHO5UO.js} +1 -1
- package/chunks/{tool-search-2AOU77H4.js → tool-search-HJN53LCN.js} +9 -8
- package/chunks/{total-session-admission-FR7RMHVL.js → total-session-admission-4FZK4PCR.js} +21 -19
- package/chunks/{trustedFolders-V7UUPQXO.js → trustedFolders-RIYUQQJC.js} +18 -17
- package/chunks/{update-relaunch-TBWRMQD6.js → update-relaunch-3HVSJU2T.js} +5 -5
- package/chunks/{updateCheck-42SPCLH7.js → updateCheck-EE2XXQNJ.js} +20 -19
- package/chunks/{useAutoAcceptIndicator-4C2KM345.js → useAutoAcceptIndicator-RRV7MW47.js} +23 -22
- package/chunks/{validateNonInterActiveAuth-UVFRXV3Z.js → validateNonInterActiveAuth-3QRII2BS.js} +47 -45
- package/chunks/{version-HKTV6TPN.js → version-4KUHPDAC.js} +1 -1
- package/chunks/{web-fetch-ZRXSV5AN.js → web-fetch-MXA6HQ42.js} +7 -6
- package/chunks/{web-search-WOLV3L6T.js → web-search-YENHOBMC.js} +5 -4
- package/chunks/{workflow-F63ES3OB.js → workflow-RYEVBM4L.js} +18 -17
- package/chunks/{workspace-providers-status-PJMGMYMC.js → workspace-providers-status-SBTU5TWO.js} +25 -24
- package/chunks/{workspace-registration-store-LNBOX5TJ.js → workspace-registration-store-VUMOTODR.js} +1 -1
- package/chunks/{workspace-registry-4PR7VDQ3.js → workspace-registry-OZ5ZUBJ6.js} +21 -19
- package/chunks/{workspace-service-PVI3VUNQ.js → workspace-service-Y3IGAN4K.js} +26 -25
- package/chunks/{workspace-skills-status-2Q5ZISO6.js → workspace-skills-status-FXOIDGOS.js} +23 -22
- package/chunks/{workspace-trust-reconciler-NOILUH3C.js → workspace-trust-reconciler-DQI7MYJS.js} +26 -24
- package/chunks/{write-file-MOM4JDHG.js → write-file-NK4C3GFC.js} +17 -16
- package/chunks/{zoom-image-E3VHRCFU.js → zoom-image-4Y6Y6DAX.js} +7 -6
- package/cli-entry.js +14 -0
- package/cli.js +16 -12
- package/package.json +3 -3
- package/web-shell/assets/{arc-GpdmhIxr.js → arc-DtI1rZcQ.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-C-LhCgH_.js → architectureDiagram-3BPJPVTR-BPZwSVct.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CzNdTCm-.js → blockDiagram-GPEHLZMM-BIQ03j4C.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Ce7hbrRM.js → c4Diagram-AAUBKEIU-CB0RyFGm.js} +1 -1
- package/web-shell/assets/channel-vfbVFuM1.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BBSEn1PK.js → chunk-2J33WTMH-B3WoS-4H.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-_llgjfe5.js → chunk-4BX2VUAB-C98xYZ1X.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-9fJZ_oZE.js → chunk-55IACEB6-CbTIWRwQ.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DgEzQWOu.js → chunk-727SXJPM-DWGnKTPu.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-B4RthUTc.js → chunk-AQP2D5EJ-4__QyCEX.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CDI-emMW.js → chunk-FMBD7UC4-DFtG1YCW.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-jM2-yOd8.js → chunk-ND2GUHAM-rvAhW51N.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-XGZHlKPF.js → chunk-QZHKN3VN-DfiU9pwZ.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-Cvr8atq3.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Cvr8atq3.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-90nbW1xQ.js → cose-bilkent-S5V4N54A-Cc4EIdxu.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-BtzlyqZ9.js → dagre-BM42HDAG-CZNj4dGW.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-DAaqGWaH.js → diagram-2AECGRRQ-D5tiqQCr.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-CxlzSIFa.js → diagram-5GNKFQAL-pwzw0jVO.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-8kj-1H6u.js → diagram-KO2AKTUF-4CWiM00x.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-6NhjFwRF.js → diagram-LMA3HP47-Dd7rc7Qf.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Bn9kvInz.js → diagram-OG6HWLK6-_vzV52ml.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CaRoGsAt.js → erDiagram-TEJ5UH35-CqbE2bx_.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-TkLweHdf.js → flowDiagram-I6XJVG4X-CaxNr7w4.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-ruwhCKBl.js → ganttDiagram-6RSMTGT7-AGjrtfUA.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-DNI_PxoU.js → gitGraphDiagram-PVQCEYII-ADG2zSkc.js} +1 -1
- package/web-shell/assets/{index-p1gz-sxE.js → index-BOryKCqt.js} +1 -1
- package/web-shell/assets/index-Cb1LjsCv.css +5 -0
- package/web-shell/assets/{index-T4KluHvu.js → index-CvJDaIy8.js} +329 -329
- package/web-shell/assets/{infoDiagram-5YYISTIA-DarXq1-A.js → infoDiagram-5YYISTIA-CE3B_IoZ.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-GxDaDlT0.js → ishikawaDiagram-YF4QCWOH-CN-Frhoi.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-mDEoGBzY.js → journeyDiagram-JHISSGLW-CGgezS93.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-Ds0t-Mup.js → kanban-definition-UN3LZRKU-BqWijky5.js} +1 -1
- package/web-shell/assets/{linear-05nJ0xZ7.js → linear-D8sfpZf6.js} +1 -1
- package/web-shell/assets/{mermaid.core-Bua24ThM.js → mermaid.core-3PA4QrzM.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-D_zRdvUS.js → mindmap-definition-RKZ34NQL-D9QxwiCY.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DZHr1x16.js → pieDiagram-4H26LBE5-Bioaf6uE.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-HA06Wf0h.js → quadrantDiagram-W4KKPZXB-DBb2AS73.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DH3urmJf.js → requirementDiagram-4Y6WPE33-DXOvZ3KB.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-C4xgz0TT.js → sankeyDiagram-5OEKKPKP-D9qg09Dm.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DAUoZWgv.js → sequenceDiagram-3UESZ5HK-DSAUIfpw.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-v7NzXy4l.js → stateDiagram-AJRCARHV-BPZkzfQ3.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DInOqnhZ.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-B3GTYR2W.js → timeline-definition-PNZ67QCA-UDaQp9sP.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BWHjSPAq.js → vennDiagram-CIIHVFJN-2ouhAnHO.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-m9r6IUBC.js → wardley-L42UT6IY-Cq_WEvTK.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-kT0FkVfK.js → wardleyDiagram-YWT4CUSO-Dt24aXOM.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-CYRm10z5.js → xychartDiagram-2RQKCTM6-A5Xk2WCH.js} +1 -1
- package/web-shell/index.html +2 -2
- package/bundled/review/DESIGN.md +0 -724
- package/web-shell/assets/channel-95y6Rcp3.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-pfzVkmjQ.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-pfzVkmjQ.js +0 -1
- package/web-shell/assets/index-WxSvj2tI.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CtdFexEf.js +0 -1
- package/chunks/{channel-management-service-UHX56NBO.js → channel-management-service-5XPPTWUQ.js} +3 -3
- package/chunks/{chunk-LEZFUYPM.js → chunk-7GYP5COR.js} +3 -3
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
serveCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FV2JYSWS.js";
|
|
6
6
|
import {
|
|
7
7
|
listCommand
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XIDYVC4P.js";
|
|
9
9
|
import {
|
|
10
10
|
getErrorMessage as getErrorMessage2
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PWFDZA5A.js";
|
|
12
12
|
import {
|
|
13
13
|
ObservedChannelContactStore
|
|
14
14
|
} from "./chunk-DYA25Y7U.js";
|
|
@@ -46,22 +46,22 @@ import {
|
|
|
46
46
|
registerToolCallDispatch,
|
|
47
47
|
selectFirstModel,
|
|
48
48
|
sessionsPath
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-JEVHOCCA.js";
|
|
50
50
|
import {
|
|
51
51
|
getExtensionManager,
|
|
52
52
|
requestChoicePluginNonInteractive,
|
|
53
53
|
requestConsentNonInteractive,
|
|
54
54
|
requestConsentOrFail,
|
|
55
55
|
resolveExtensionCommandScope
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-VY4TEQQ6.js";
|
|
57
57
|
import {
|
|
58
58
|
collectProviderModelsForProtocol,
|
|
59
59
|
getAuthTypeFromEnv,
|
|
60
60
|
resolveCliGenerationConfig
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-PQ2J56BJ.js";
|
|
62
62
|
import {
|
|
63
63
|
parseChannelConfig
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-7GYP5COR.js";
|
|
65
65
|
import {
|
|
66
66
|
findCliEntryPath
|
|
67
67
|
} from "./chunk-V6WHFGST.js";
|
|
@@ -96,6 +96,9 @@ import {
|
|
|
96
96
|
import {
|
|
97
97
|
normalizeServeChannelSelection
|
|
98
98
|
} from "./chunk-ALMR3E6Q.js";
|
|
99
|
+
import {
|
|
100
|
+
EXTERNAL_TOOL_GUARD_TOKEN_ENV
|
|
101
|
+
} from "./chunk-BKHCW2BI.js";
|
|
99
102
|
import {
|
|
100
103
|
redactLogCredentials
|
|
101
104
|
} from "./chunk-M5GB774H.js";
|
|
@@ -128,29 +131,29 @@ import {
|
|
|
128
131
|
assembleMcpServers,
|
|
129
132
|
getPendingGatedMcpServers,
|
|
130
133
|
mcpCommand
|
|
131
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-JNFWMBG6.js";
|
|
132
135
|
import {
|
|
133
136
|
loadSettings
|
|
134
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-GXP44JOS.js";
|
|
135
138
|
import {
|
|
136
139
|
detectSystemLanguage,
|
|
137
140
|
getCurrentLanguage,
|
|
138
141
|
initializeI18n,
|
|
139
142
|
resolveLanguageSetting,
|
|
140
143
|
t
|
|
141
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-O4WOWHMZ.js";
|
|
142
145
|
import {
|
|
143
146
|
loadEnvironment
|
|
144
|
-
} from "./chunk-
|
|
147
|
+
} from "./chunk-7FKLLD4X.js";
|
|
145
148
|
import {
|
|
146
149
|
getCliVersion
|
|
147
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-7EW7CYLA.js";
|
|
148
151
|
import {
|
|
149
152
|
getPackageJson
|
|
150
153
|
} from "./chunk-VJNBRRZG.js";
|
|
151
154
|
import {
|
|
152
155
|
isWorkspaceTrusted
|
|
153
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-MKMUBBEX.js";
|
|
154
157
|
import {
|
|
155
158
|
require_strip_json_comments
|
|
156
159
|
} from "./chunk-ALGGS7UH.js";
|
|
@@ -191,7 +194,7 @@ import {
|
|
|
191
194
|
unquoteCStylePath,
|
|
192
195
|
updateChannelMemoryEntry,
|
|
193
196
|
updateSetting
|
|
194
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-5OAMVWFL.js";
|
|
195
198
|
import {
|
|
196
199
|
nextFireTime,
|
|
197
200
|
parseCron
|
|
@@ -202,18 +205,18 @@ import {
|
|
|
202
205
|
import {
|
|
203
206
|
parseBooleanEnvFlag,
|
|
204
207
|
resolveTelemetrySettings
|
|
205
|
-
} from "./chunk-
|
|
208
|
+
} from "./chunk-MGSSJT27.js";
|
|
206
209
|
import {
|
|
207
210
|
getAllGeminiMdFilenames,
|
|
208
211
|
setGeminiMdFilename
|
|
209
|
-
} from "./chunk-
|
|
212
|
+
} from "./chunk-NMBDPO63.js";
|
|
210
213
|
import {
|
|
211
214
|
SchemaValidator,
|
|
212
215
|
ToolNames
|
|
213
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-D7D7RXIJ.js";
|
|
214
217
|
import {
|
|
215
218
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
216
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-LCCBAGRT.js";
|
|
217
220
|
import {
|
|
218
221
|
isTlsVerificationDisabled
|
|
219
222
|
} from "./chunk-BFHXDAR7.js";
|
|
@@ -222,7 +225,7 @@ import {
|
|
|
222
225
|
} from "./chunk-UH7Z7Y45.js";
|
|
223
226
|
import {
|
|
224
227
|
recordChannelMemoryRecallMetrics
|
|
225
|
-
} from "./chunk-
|
|
228
|
+
} from "./chunk-5L6CQ4ZU.js";
|
|
226
229
|
import {
|
|
227
230
|
FatalConfigError,
|
|
228
231
|
FatalSandboxError,
|
|
@@ -358,9 +361,9 @@ var require_command_exists = __commonJS({
|
|
|
358
361
|
cleanInput = /* @__PURE__ */ __name(function(s) {
|
|
359
362
|
var isPathName = /[\\]/.test(s);
|
|
360
363
|
if (isPathName) {
|
|
361
|
-
var
|
|
364
|
+
var dirname24 = '"' + path3.dirname(s) + '"';
|
|
362
365
|
var basename6 = '"' + path3.basename(s) + '"';
|
|
363
|
-
return
|
|
366
|
+
return dirname24 + ":" + basename6;
|
|
364
367
|
}
|
|
365
368
|
return '"' + s + '"';
|
|
366
369
|
}, "cleanInput");
|
|
@@ -368,10 +371,10 @@ var require_command_exists = __commonJS({
|
|
|
368
371
|
module.exports = /* @__PURE__ */ __name(function commandExists2(commandName, callback) {
|
|
369
372
|
var cleanedCommandName = cleanInput(commandName);
|
|
370
373
|
if (!callback && typeof Promise !== "undefined") {
|
|
371
|
-
return new Promise(function(
|
|
374
|
+
return new Promise(function(resolve24, reject) {
|
|
372
375
|
commandExists2(commandName, function(error, output) {
|
|
373
376
|
if (output) {
|
|
374
|
-
|
|
377
|
+
resolve24(commandName);
|
|
375
378
|
} else {
|
|
376
379
|
reject(error);
|
|
377
380
|
}
|
|
@@ -2255,8 +2258,8 @@ function createBridgeReadinessGate() {
|
|
|
2255
2258
|
current: /* @__PURE__ */ __name(() => pending, "current"),
|
|
2256
2259
|
block: /* @__PURE__ */ __name(() => {
|
|
2257
2260
|
if (pending) return;
|
|
2258
|
-
pending = new Promise((
|
|
2259
|
-
releasePending =
|
|
2261
|
+
pending = new Promise((resolve24) => {
|
|
2262
|
+
releasePending = resolve24;
|
|
2260
2263
|
});
|
|
2261
2264
|
}, "block"),
|
|
2262
2265
|
release: /* @__PURE__ */ __name(() => {
|
|
@@ -2338,7 +2341,7 @@ function createBridgeRecovery(options) {
|
|
|
2338
2341
|
writeStderrLine(
|
|
2339
2342
|
`[Channel] Bridge crashed (${recentCrashCount}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2340
2343
|
);
|
|
2341
|
-
await new Promise((
|
|
2344
|
+
await new Promise((resolve24) => setTimeout(resolve24, RESTART_DELAY_MS));
|
|
2342
2345
|
const bridge = new AcpBridge(bridgeOpts);
|
|
2343
2346
|
setBridge(bridge);
|
|
2344
2347
|
attachDisconnectHandler(bridge);
|
|
@@ -3206,12 +3209,12 @@ async function abortableStartup(value, signal) {
|
|
|
3206
3209
|
const promise = Promise.resolve(value);
|
|
3207
3210
|
if (!signal) return await promise;
|
|
3208
3211
|
if (signal.aborted) throw startupAbortError();
|
|
3209
|
-
return await new Promise((
|
|
3212
|
+
return await new Promise((resolve24, reject) => {
|
|
3210
3213
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3211
3214
|
reject(startupAbortError());
|
|
3212
3215
|
}, "onAbort");
|
|
3213
3216
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3214
|
-
promise.then(
|
|
3217
|
+
promise.then(resolve24, reject).finally(() => {
|
|
3215
3218
|
signal.removeEventListener("abort", onAbort);
|
|
3216
3219
|
});
|
|
3217
3220
|
});
|
|
@@ -3585,6 +3588,7 @@ function scrubDaemonWorkerEnv() {
|
|
|
3585
3588
|
delete process.env[QWEN_DAEMON_URL_ENV];
|
|
3586
3589
|
delete process.env[QWEN_DAEMON_WORKSPACE_ENV];
|
|
3587
3590
|
delete process.env[QWEN_SERVER_TOKEN_ENV];
|
|
3591
|
+
delete process.env[EXTERNAL_TOOL_GUARD_TOKEN_ENV];
|
|
3588
3592
|
}
|
|
3589
3593
|
__name(scrubDaemonWorkerEnv, "scrubDaemonWorkerEnv");
|
|
3590
3594
|
function readDaemonWorkerEnv() {
|
|
@@ -3619,7 +3623,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3619
3623
|
if (!send) {
|
|
3620
3624
|
return Promise.reject(new Error("Channel worker IPC is unavailable."));
|
|
3621
3625
|
}
|
|
3622
|
-
return new Promise((
|
|
3626
|
+
return new Promise((resolve24, reject) => {
|
|
3623
3627
|
let settled = false;
|
|
3624
3628
|
let unsubscribeMessage = /* @__PURE__ */ __name(() => {
|
|
3625
3629
|
}, "unsubscribeMessage");
|
|
@@ -3633,7 +3637,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3633
3637
|
settled = true;
|
|
3634
3638
|
cleanup();
|
|
3635
3639
|
if (error) reject(error);
|
|
3636
|
-
else
|
|
3640
|
+
else resolve24();
|
|
3637
3641
|
}, "finish");
|
|
3638
3642
|
const onMessage = /* @__PURE__ */ __name((value) => {
|
|
3639
3643
|
if (isChannelStartupReportAckMessage(value)) {
|
|
@@ -3881,8 +3885,8 @@ var daemonWorkerCommand = {
|
|
|
3881
3885
|
let shuttingDown = false;
|
|
3882
3886
|
let exitCode = 0;
|
|
3883
3887
|
let finish;
|
|
3884
|
-
const finished = new Promise((
|
|
3885
|
-
finish =
|
|
3888
|
+
const finished = new Promise((resolve24) => {
|
|
3889
|
+
finish = resolve24;
|
|
3886
3890
|
});
|
|
3887
3891
|
const shutdown = /* @__PURE__ */ __name(async (reason) => {
|
|
3888
3892
|
if (shuttingDown) {
|
|
@@ -3910,8 +3914,8 @@ var daemonWorkerCommand = {
|
|
|
3910
3914
|
...activeChannelDeliveries.values(),
|
|
3911
3915
|
...activeWebhookTasks.values()
|
|
3912
3916
|
]),
|
|
3913
|
-
new Promise((
|
|
3914
|
-
const timer = setTimeout(
|
|
3917
|
+
new Promise((resolve24) => {
|
|
3918
|
+
const timer = setTimeout(resolve24, WORKER_SHUTDOWN_DRAIN_MS);
|
|
3915
3919
|
timer.unref();
|
|
3916
3920
|
})
|
|
3917
3921
|
]);
|
|
@@ -4547,12 +4551,12 @@ var parseArgsCommand = {
|
|
|
4547
4551
|
|
|
4548
4552
|
// packages/cli/src/commands/review/compose-review.ts
|
|
4549
4553
|
init_esbuild_shims();
|
|
4550
|
-
import { mkdirSync as
|
|
4551
|
-
import { dirname as dirname4, join as
|
|
4554
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
4555
|
+
import { dirname as dirname4, join as join9 } from "node:path";
|
|
4552
4556
|
|
|
4553
4557
|
// packages/cli/src/commands/review/lib/coverage.ts
|
|
4554
4558
|
init_esbuild_shims();
|
|
4555
|
-
import { readFileSync as
|
|
4559
|
+
import { readFileSync as readFileSync8, statSync as statSync3 } from "node:fs";
|
|
4556
4560
|
|
|
4557
4561
|
// packages/cli/src/commands/review/lib/transcripts.ts
|
|
4558
4562
|
init_esbuild_shims();
|
|
@@ -6186,6 +6190,150 @@ If you find no new gap in your scope, say so **and name what you re-examined** \
|
|
|
6186
6190
|
}
|
|
6187
6191
|
};
|
|
6188
6192
|
|
|
6193
|
+
// packages/cli/src/commands/review/lib/deadline.ts
|
|
6194
|
+
init_esbuild_shims();
|
|
6195
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
6196
|
+
import { join as join8 } from "node:path";
|
|
6197
|
+
var DEADLINE_ENV = "QWEN_REVIEW_DEADLINE_EPOCH";
|
|
6198
|
+
var RESERVE_ENV = "QWEN_REVIEW_DEADLINE_RESERVE_SECONDS";
|
|
6199
|
+
var DEFAULT_RESERVE_SECONDS = 3600;
|
|
6200
|
+
var DEFAULT_ROUND_SECONDS = 1800;
|
|
6201
|
+
var MIN_OBSERVED_ROUND_SECONDS = 600;
|
|
6202
|
+
var STAMPS_FILE = "budget-rounds.json";
|
|
6203
|
+
var STOP_FILE = "budget-stop.json";
|
|
6204
|
+
var RUN_EPOCH_SLACK_MS = 2e3;
|
|
6205
|
+
function runEpochMs(planPath) {
|
|
6206
|
+
try {
|
|
6207
|
+
return statSync2(planPath).mtimeMs - RUN_EPOCH_SLACK_MS;
|
|
6208
|
+
} catch {
|
|
6209
|
+
return Number.NEGATIVE_INFINITY;
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
__name(runEpochMs, "runEpochMs");
|
|
6213
|
+
function readRoundStamps(planPath) {
|
|
6214
|
+
try {
|
|
6215
|
+
const raw = readFileSync7(
|
|
6216
|
+
join8(promptRecordDir(planPath), STAMPS_FILE),
|
|
6217
|
+
"utf8"
|
|
6218
|
+
);
|
|
6219
|
+
const parsed = JSON.parse(raw);
|
|
6220
|
+
if (!Array.isArray(parsed)) return [];
|
|
6221
|
+
const epoch = runEpochMs(planPath);
|
|
6222
|
+
return parsed.filter(
|
|
6223
|
+
(e) => typeof e === "object" && e !== null && typeof e.atMs === "number" && e.atMs >= epoch
|
|
6224
|
+
);
|
|
6225
|
+
} catch {
|
|
6226
|
+
return [];
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
__name(readRoundStamps, "readRoundStamps");
|
|
6230
|
+
function stampRound(planPath, round, nowMs = Date.now()) {
|
|
6231
|
+
try {
|
|
6232
|
+
const stamps = readRoundStamps(planPath);
|
|
6233
|
+
if (round !== void 0 && stamps.some((s) => s.round === round)) return;
|
|
6234
|
+
stamps.push({ round: round ?? null, atMs: nowMs });
|
|
6235
|
+
const dir = promptRecordDir(planPath);
|
|
6236
|
+
mkdirSync5(dir, { recursive: true });
|
|
6237
|
+
writeFileSync5(join8(dir, STAMPS_FILE), JSON.stringify(stamps));
|
|
6238
|
+
} catch {
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
__name(stampRound, "stampRound");
|
|
6242
|
+
function expectedRoundSeconds(planPath, round, nowMs = Date.now()) {
|
|
6243
|
+
const stamps = readRoundStamps(planPath);
|
|
6244
|
+
for (let i = stamps.length - 1; i >= 0; i--) {
|
|
6245
|
+
const s = stamps[i];
|
|
6246
|
+
if (round !== void 0 && s.round === round) continue;
|
|
6247
|
+
const observed = Math.round((nowMs - s.atMs) / 1e3);
|
|
6248
|
+
return Math.max(MIN_OBSERVED_ROUND_SECONDS, observed);
|
|
6249
|
+
}
|
|
6250
|
+
return DEFAULT_ROUND_SECONDS;
|
|
6251
|
+
}
|
|
6252
|
+
__name(expectedRoundSeconds, "expectedRoundSeconds");
|
|
6253
|
+
function reverseAuditBudgetExhausted(env, roundCostSeconds, nowMs = Date.now()) {
|
|
6254
|
+
const raw = env[DEADLINE_ENV];
|
|
6255
|
+
if (raw === void 0 || raw.trim() === "") return null;
|
|
6256
|
+
const deadline = Number(raw);
|
|
6257
|
+
if (!Number.isFinite(deadline) || deadline <= 0) return null;
|
|
6258
|
+
let reserve = DEFAULT_RESERVE_SECONDS;
|
|
6259
|
+
const reserveRaw = env[RESERVE_ENV];
|
|
6260
|
+
if (reserveRaw !== void 0 && reserveRaw.trim() !== "") {
|
|
6261
|
+
const r = Number(reserveRaw);
|
|
6262
|
+
if (Number.isFinite(r) && r >= 0) reserve = r;
|
|
6263
|
+
}
|
|
6264
|
+
const remainingSeconds = Math.floor(deadline - nowMs / 1e3);
|
|
6265
|
+
if (remainingSeconds >= reserve + roundCostSeconds) return null;
|
|
6266
|
+
return {
|
|
6267
|
+
remainingSeconds,
|
|
6268
|
+
reserveSeconds: reserve,
|
|
6269
|
+
expectedRoundSeconds: roundCostSeconds
|
|
6270
|
+
};
|
|
6271
|
+
}
|
|
6272
|
+
__name(reverseAuditBudgetExhausted, "reverseAuditBudgetExhausted");
|
|
6273
|
+
var BUDGET_STOP_PHRASE = "review time budget";
|
|
6274
|
+
function budgetStopDisclosure(round) {
|
|
6275
|
+
const which = round !== void 0 ? `round ${round}` : "the next round";
|
|
6276
|
+
const whichZh = round !== void 0 ? `\u7B2C ${round} \u8F6E` : "\u4E0B\u4E00\u8F6E";
|
|
6277
|
+
return {
|
|
6278
|
+
subject: "reverse audit",
|
|
6279
|
+
reason: `stopped before ${which} by the ${BUDGET_STOP_PHRASE}`,
|
|
6280
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
6281
|
+
reasonZh: `\u8BC4\u5BA1\u65F6\u95F4\u9884\u7B97\u4E0D\u8DB3\uFF0C\u672A\u80FD\u5F00\u59CB${whichZh}`
|
|
6282
|
+
};
|
|
6283
|
+
}
|
|
6284
|
+
__name(budgetStopDisclosure, "budgetStopDisclosure");
|
|
6285
|
+
function budgetStopEntry(round) {
|
|
6286
|
+
const d = budgetStopDisclosure(round);
|
|
6287
|
+
return `${d.subject} \u2014 ${d.reason}`;
|
|
6288
|
+
}
|
|
6289
|
+
__name(budgetStopEntry, "budgetStopEntry");
|
|
6290
|
+
function budgetStopEntryZh(round) {
|
|
6291
|
+
const d = budgetStopDisclosure(round);
|
|
6292
|
+
return `${d.subjectZh}\u2014\u2014${d.reasonZh}`;
|
|
6293
|
+
}
|
|
6294
|
+
__name(budgetStopEntryZh, "budgetStopEntryZh");
|
|
6295
|
+
function writeBudgetStop(planPath, spent, round, nowMs = Date.now()) {
|
|
6296
|
+
try {
|
|
6297
|
+
const dir = promptRecordDir(planPath);
|
|
6298
|
+
mkdirSync5(dir, { recursive: true });
|
|
6299
|
+
const stop = {
|
|
6300
|
+
entry: budgetStopEntry(round),
|
|
6301
|
+
entryZh: budgetStopEntryZh(round),
|
|
6302
|
+
round: round ?? null,
|
|
6303
|
+
remainingSeconds: spent.remainingSeconds,
|
|
6304
|
+
reserveSeconds: spent.reserveSeconds,
|
|
6305
|
+
atMs: nowMs
|
|
6306
|
+
};
|
|
6307
|
+
writeFileSync5(join8(dir, STOP_FILE), JSON.stringify(stop, null, 2));
|
|
6308
|
+
} catch {
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6311
|
+
__name(writeBudgetStop, "writeBudgetStop");
|
|
6312
|
+
function readBudgetStop(planPath) {
|
|
6313
|
+
try {
|
|
6314
|
+
const raw = readFileSync7(
|
|
6315
|
+
join8(promptRecordDir(planPath), STOP_FILE),
|
|
6316
|
+
"utf8"
|
|
6317
|
+
);
|
|
6318
|
+
const parsed = JSON.parse(raw);
|
|
6319
|
+
if (typeof parsed !== "object" || parsed === null || typeof parsed.entry !== "string" || typeof parsed.atMs !== "number" || parsed.atMs < runEpochMs(planPath)) {
|
|
6320
|
+
return null;
|
|
6321
|
+
}
|
|
6322
|
+
return parsed;
|
|
6323
|
+
} catch {
|
|
6324
|
+
return null;
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
__name(readBudgetStop, "readBudgetStop");
|
|
6328
|
+
function reverseAuditBudgetMessage(spent, round) {
|
|
6329
|
+
const minutesLeft = Math.max(0, Math.floor(spent.remainingSeconds / 60));
|
|
6330
|
+
const reserveMinutes = Math.round(spent.reserveSeconds / 60);
|
|
6331
|
+
const roundMinutes = Math.round(spent.expectedRoundSeconds / 60);
|
|
6332
|
+
const which = round !== void 0 ? `round ${round}` : "the next round";
|
|
6333
|
+
return `BUDGET: ${minutesLeft} minute(s) remain before this review's deadline \u2014 not enough for the ~${roundMinutes}-minute round being asked for plus the ${reserveMinutes}-minute reserve kept for its verification, compose-review and submission \u2014 so no further reverse-audit round will be built. This is the loop's termination rule, not an error: do not rebuild ${which} and do not relaunch auditors. A budget-stop marker has been recorded and compose-review will disclose it and cap the verdict itself; also add exactly this entry to unreviewedDimensions so the terminal report says it too \u2014 \`${budgetStopEntry(round)}\` \u2014 and proceed to Step 6 with the findings already confirmed. Spend what time remains only on verifying findings already in hand, composing, and submitting. A review that stops here still reports everything it proved; a review that runs past its deadline is killed holding all of it.`;
|
|
6334
|
+
}
|
|
6335
|
+
__name(reverseAuditBudgetMessage, "reverseAuditBudgetMessage");
|
|
6336
|
+
|
|
6189
6337
|
// packages/cli/src/commands/review/lib/shell-quote.ts
|
|
6190
6338
|
init_esbuild_shims();
|
|
6191
6339
|
function shellQuotePath(p) {
|
|
@@ -6195,7 +6343,7 @@ __name(shellQuotePath, "shellQuotePath");
|
|
|
6195
6343
|
|
|
6196
6344
|
// packages/cli/src/commands/review/lib/coverage.ts
|
|
6197
6345
|
function readPlan(path3) {
|
|
6198
|
-
const plan = JSON.parse(
|
|
6346
|
+
const plan = JSON.parse(readFileSync8(path3, "utf8"));
|
|
6199
6347
|
if (typeof plan?.diffPathAbsolute !== "string" || !plan.diffPathAbsolute) {
|
|
6200
6348
|
throw new Error(`coverage: ${path3} has no diffPathAbsolute`);
|
|
6201
6349
|
}
|
|
@@ -6206,7 +6354,7 @@ function readPlan(path3) {
|
|
|
6206
6354
|
if (problem) {
|
|
6207
6355
|
throw new Error(`coverage: ${path3} has ${problem}`);
|
|
6208
6356
|
}
|
|
6209
|
-
return { plan, mtimeMs:
|
|
6357
|
+
return { plan, mtimeMs: statSync3(path3).mtimeMs };
|
|
6210
6358
|
}
|
|
6211
6359
|
__name(readPlan, "readPlan");
|
|
6212
6360
|
var CHUNK_RE = /\bchunk\s+(\d+)\s+of\s+\d+\b/i;
|
|
@@ -6283,6 +6431,11 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6283
6431
|
const idleAgents = [];
|
|
6284
6432
|
const unopenedAgents = [];
|
|
6285
6433
|
const rewrittenPrompts = [];
|
|
6434
|
+
const driftedLaunches = [];
|
|
6435
|
+
const openedBriefOf = /* @__PURE__ */ __name((rec, key) => {
|
|
6436
|
+
const needle = JSON.stringify(briefPath(planPath, key));
|
|
6437
|
+
return rec.successfulCallArgs.some((a) => a.includes(needle));
|
|
6438
|
+
}, "openedBriefOf");
|
|
6286
6439
|
const disclosures = [];
|
|
6287
6440
|
const disclose = /* @__PURE__ */ __name((subject, reason, pub) => {
|
|
6288
6441
|
disclosures.push({
|
|
@@ -6355,15 +6508,23 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6355
6508
|
);
|
|
6356
6509
|
}
|
|
6357
6510
|
} else if (!wasDeliveredVerbatim(rec.launchPrompt, b)) {
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
)
|
|
6511
|
+
if (openedBriefOf(rec, `chunk-${chunk2}`) && rec.diffToolCalls > 0) {
|
|
6512
|
+
if (!superseded(rec, chunk2)) {
|
|
6513
|
+
driftedLaunches.push(
|
|
6514
|
+
`${name} \u2014 launched with a near-verbatim prompt; its brief was opened and the diff was read, so the delivery stands`
|
|
6515
|
+
);
|
|
6516
|
+
}
|
|
6517
|
+
} else {
|
|
6518
|
+
rewrittenThisRecord = true;
|
|
6519
|
+
if (!superseded(rec, chunk2)) {
|
|
6520
|
+
rewrittenPrompts.push(
|
|
6521
|
+
disclose(
|
|
6522
|
+
name,
|
|
6523
|
+
"launched with a prompt that is not the one the CLI built",
|
|
6524
|
+
{ reasonZh: "\u542F\u52A8\u65F6\u4F7F\u7528\u7684 prompt \u4E0D\u662F CLI \u6784\u5EFA\u7684\u90A3\u4E00\u4EFD" }
|
|
6525
|
+
)
|
|
6526
|
+
);
|
|
6527
|
+
}
|
|
6367
6528
|
}
|
|
6368
6529
|
}
|
|
6369
6530
|
}
|
|
@@ -6407,16 +6568,12 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6407
6568
|
);
|
|
6408
6569
|
}
|
|
6409
6570
|
const buildable = roster.filter((r) => builtOf(r.key) !== void 0);
|
|
6410
|
-
const openedBrief = /* @__PURE__ */ __name((rec, key) => {
|
|
6411
|
-
const needle = JSON.stringify(briefPath(planPath, key));
|
|
6412
|
-
return rec.successfulCallArgs.some((a) => a.includes(needle));
|
|
6413
|
-
}, "openedBrief");
|
|
6414
6571
|
const candidatesOf = buildable.map((req) => {
|
|
6415
6572
|
const b = builtOf(req.key);
|
|
6416
6573
|
return records.filter((r) => wasDeliveredVerbatim(r.launchPrompt, b));
|
|
6417
6574
|
});
|
|
6418
6575
|
const openedOfReq = buildable.map(
|
|
6419
|
-
(req, i) => candidatesOf[i].filter((r) =>
|
|
6576
|
+
(req, i) => candidatesOf[i].filter((r) => openedBriefOf(r, req.key))
|
|
6420
6577
|
);
|
|
6421
6578
|
const matchedRec = /* @__PURE__ */ new Map();
|
|
6422
6579
|
const augment = /* @__PURE__ */ __name((i, edges, seen) => {
|
|
@@ -6441,6 +6598,7 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6441
6598
|
}
|
|
6442
6599
|
const assignment = /* @__PURE__ */ new Map();
|
|
6443
6600
|
for (const [rec, i] of matchedRec) assignment.set(i, rec);
|
|
6601
|
+
const rescued = /* @__PURE__ */ new Set();
|
|
6444
6602
|
let buildableIdx = -1;
|
|
6445
6603
|
for (const req of roster) {
|
|
6446
6604
|
const b = builtOf(req.key);
|
|
@@ -6465,6 +6623,21 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6465
6623
|
const pick2 = assignment.get(buildableIdx);
|
|
6466
6624
|
if (pick2 === void 0) {
|
|
6467
6625
|
const anyMatch = candidatesOf[buildableIdx].length > 0;
|
|
6626
|
+
if (!anyMatch) {
|
|
6627
|
+
const needsDiff = req.role === "chunk" || BRIEFS[req.role].readsDiff;
|
|
6628
|
+
const rescue = records.find(
|
|
6629
|
+
(r) => !matchedRec.has(r) && !rescued.has(r) && r.successfulToolCalls > 0 && (!needsDiff || r.diffToolCalls > 0) && openedBriefOf(r, req.key)
|
|
6630
|
+
);
|
|
6631
|
+
if (rescue !== void 0) {
|
|
6632
|
+
rescued.add(rescue);
|
|
6633
|
+
if (req.role !== "chunk") {
|
|
6634
|
+
driftedLaunches.push(
|
|
6635
|
+
`${roleLabel(req)} \u2014 no launch matched its block verbatim, but an agent opened this role's brief and did the work, so the delivery stands`
|
|
6636
|
+
);
|
|
6637
|
+
}
|
|
6638
|
+
continue;
|
|
6639
|
+
}
|
|
6640
|
+
}
|
|
6468
6641
|
missingRoles.push(
|
|
6469
6642
|
disclose(
|
|
6470
6643
|
roleLabel(req),
|
|
@@ -6512,6 +6685,7 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6512
6685
|
idleAgents,
|
|
6513
6686
|
unopenedAgents,
|
|
6514
6687
|
rewrittenPrompts,
|
|
6688
|
+
driftedLaunches,
|
|
6515
6689
|
missingRoles,
|
|
6516
6690
|
missingRoleSelectors,
|
|
6517
6691
|
disclosures,
|
|
@@ -6526,7 +6700,13 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
6526
6700
|
};
|
|
6527
6701
|
}
|
|
6528
6702
|
__name(coverageFromTranscripts, "coverageFromTranscripts");
|
|
6529
|
-
var rebuildFix = /* @__PURE__ */ __name((role, noun) => `build the prompt with \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt --plan <plan> --role ${role} --findings <file> [--rules <rules file>]
|
|
6703
|
+
var rebuildFix = /* @__PURE__ */ __name((role, noun) => `build the prompt with \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt --plan <plan> --role ${role} --findings <file> [--rules <rules file>] ` + // --round is MANDATORY for a reverse-audit build (`agent-prompt` refuses a
|
|
6704
|
+
// round-less call — the label keys the record and the budget gate's
|
|
6705
|
+
// accounting), so the paste-and-run repair must not bracket it as optional:
|
|
6706
|
+
// an orchestrator honouring the bracket convention would have its first
|
|
6707
|
+
// repair attempt rejected. Verify genuinely takes it or not (only a repeat
|
|
6708
|
+
// verification round passes one), so its brackets stay.
|
|
6709
|
+
(role === "reverse-audit" ? `--round <k>\` ` : `[--round <k>]\` `) + (role === "reverse-audit" ? `(an early round with nothing confirmed passes an empty file; ` : `(pass the shard's findings, never an empty file \u2014 a verifier that sees no findings verifies nothing; `) + `pass --rules whenever the review loaded any, or the rebuilt brief silently drops the project rules) and launch an agent with EXACTLY what it prints \u2014 no hand-added ${noun} number` + // --round bakes in a ROUND number. Verify's noun is "shard", and a
|
|
6530
6710
|
// parenthetical claiming --round bakes it in would send the reader to the
|
|
6531
6711
|
// wrong flag — shards are already told apart by their findings digest.
|
|
6532
6712
|
(role === "reverse-audit" ? ` (--round bakes it in)` : ``) + `, no summary of your own, no rewording`, "rebuildFix");
|
|
@@ -6641,7 +6821,9 @@ function verificationGaps(planPath, opts, env = process.env) {
|
|
|
6641
6821
|
(k) => k === "reverse-audit" || k.startsWith("reverse-audit--")
|
|
6642
6822
|
);
|
|
6643
6823
|
const reverse = bestDelivery(reverseKeys);
|
|
6644
|
-
const
|
|
6824
|
+
const budgetStopped = readBudgetStop(planPath) !== null;
|
|
6825
|
+
const reverseByDesign = budgetStopped && reverse === "not-built";
|
|
6826
|
+
const reverseGap = !balancedMedium && !reverseByDesign && reverse !== "ok";
|
|
6645
6827
|
if (reverseGap) {
|
|
6646
6828
|
remediation.push(
|
|
6647
6829
|
`reverse audit: ${REVERSE_AUDIT_GAP[reverse].fix.replace(
|
|
@@ -6944,6 +7126,24 @@ function unmarkedComments(comments) {
|
|
|
6944
7126
|
}
|
|
6945
7127
|
__name(unmarkedComments, "unmarkedComments");
|
|
6946
7128
|
|
|
7129
|
+
// packages/cli/src/commands/review/lib/review-footer.ts
|
|
7130
|
+
init_esbuild_shims();
|
|
7131
|
+
var FOOTER_MARKER = "via Qwen Code /review";
|
|
7132
|
+
function reviewFooter(modelId, cliVersion) {
|
|
7133
|
+
return `_\u2014 ${modelId} ${FOOTER_MARKER} (v${cliVersion})_`;
|
|
7134
|
+
}
|
|
7135
|
+
__name(reviewFooter, "reviewFooter");
|
|
7136
|
+
var REVIEW_FOOTER_RE = /\s*(?:_— (?:(?! via Qwen Code \/review)[^\n])* via Qwen Code \/review(?: \(v[^\n)]*\))?_?\s*)+$/;
|
|
7137
|
+
function isFooterSafeModelId(modelId) {
|
|
7138
|
+
return !/[\n\r]/.test(modelId) && !modelId.includes(FOOTER_MARKER);
|
|
7139
|
+
}
|
|
7140
|
+
__name(isFooterSafeModelId, "isFooterSafeModelId");
|
|
7141
|
+
var FOOTER_VERSION_RE = /^[A-Za-z0-9._+-]+$/;
|
|
7142
|
+
function footerVersion(stamp) {
|
|
7143
|
+
return stamp !== void 0 && FOOTER_VERSION_RE.test(stamp) ? stamp : void 0;
|
|
7144
|
+
}
|
|
7145
|
+
__name(footerVersion, "footerVersion");
|
|
7146
|
+
|
|
6947
7147
|
// packages/cli/src/commands/review/compose-review.ts
|
|
6948
7148
|
var LOW_SIGNAL_SRC_DIFF_LINES = 100;
|
|
6949
7149
|
function withMarker(line) {
|
|
@@ -6970,6 +7170,10 @@ function toStringList(value, field) {
|
|
|
6970
7170
|
return [...value];
|
|
6971
7171
|
}
|
|
6972
7172
|
__name(toStringList, "toStringList");
|
|
7173
|
+
function stripReviewFooter(entry) {
|
|
7174
|
+
return entry.replace(REVIEW_FOOTER_RE, "");
|
|
7175
|
+
}
|
|
7176
|
+
__name(stripReviewFooter, "stripReviewFooter");
|
|
6973
7177
|
function toBool(value, field) {
|
|
6974
7178
|
if (value === void 0 || value === null) return false;
|
|
6975
7179
|
if (typeof value !== "boolean") {
|
|
@@ -6991,15 +7195,15 @@ __name(composeReview, "composeReview");
|
|
|
6991
7195
|
function ledgerMarkerFor(input) {
|
|
6992
7196
|
try {
|
|
6993
7197
|
if (!input.planPath) return null;
|
|
6994
|
-
const plan = JSON.parse(
|
|
7198
|
+
const plan = JSON.parse(readFileSync9(input.planPath, "utf8"));
|
|
6995
7199
|
const pr = plan?.prNumber;
|
|
6996
7200
|
const isPr = typeof pr === "number" && Number.isInteger(pr) && pr > 0 || typeof pr === "string" && /^\d+$/.test(pr);
|
|
6997
7201
|
if (!isPr) return null;
|
|
6998
7202
|
let prevRound = 0;
|
|
6999
7203
|
try {
|
|
7000
7204
|
const prev = JSON.parse(
|
|
7001
|
-
|
|
7002
|
-
|
|
7205
|
+
readFileSync9(
|
|
7206
|
+
join9(
|
|
7003
7207
|
dirname4(input.planPath),
|
|
7004
7208
|
`qwen-review-pr-${pr}-prev-ledger.json`
|
|
7005
7209
|
),
|
|
@@ -7014,7 +7218,7 @@ function ledgerMarkerFor(input) {
|
|
|
7014
7218
|
buildLedger(
|
|
7015
7219
|
prevRound + 1,
|
|
7016
7220
|
input.draftedComments ?? [],
|
|
7017
|
-
toStringList(input.bodyCriticals, "bodyCriticals")
|
|
7221
|
+
toStringList(input.bodyCriticals, "bodyCriticals").map(stripReviewFooter).filter((entry) => entry.trim() !== "")
|
|
7018
7222
|
)
|
|
7019
7223
|
);
|
|
7020
7224
|
} catch {
|
|
@@ -7028,7 +7232,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7028
7232
|
input.suggestionsInline,
|
|
7029
7233
|
"suggestionsInline"
|
|
7030
7234
|
);
|
|
7031
|
-
const bodyCriticals = toStringList(input.bodyCriticals, "bodyCriticals");
|
|
7235
|
+
const bodyCriticals = toStringList(input.bodyCriticals, "bodyCriticals").map(stripReviewFooter).filter((entry) => entry.trim() !== "");
|
|
7032
7236
|
const suggestionsDiscarded = toCount(
|
|
7033
7237
|
input.suggestionsDiscarded,
|
|
7034
7238
|
"suggestionsDiscarded"
|
|
@@ -7036,7 +7240,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7036
7240
|
const cannotTell = toStringList(
|
|
7037
7241
|
input.cannotTellCriticals,
|
|
7038
7242
|
"cannotTellCriticals"
|
|
7039
|
-
);
|
|
7243
|
+
).map(stripReviewFooter).filter((entry) => entry.trim() !== "");
|
|
7040
7244
|
const uncoverable = toStringList(
|
|
7041
7245
|
input.uncoverableChunks,
|
|
7042
7246
|
"uncoverableChunks"
|
|
@@ -7046,6 +7250,19 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7046
7250
|
"unreviewedDimensions"
|
|
7047
7251
|
);
|
|
7048
7252
|
const coverageEntries = [];
|
|
7253
|
+
let budgetEntry;
|
|
7254
|
+
if (input.planPath) {
|
|
7255
|
+
const stop = readBudgetStop(input.planPath);
|
|
7256
|
+
if (stop !== null) {
|
|
7257
|
+
for (let i = unreviewed.length - 1; i >= 0; i--) {
|
|
7258
|
+
if (unreviewed[i].includes(BUDGET_STOP_PHRASE)) {
|
|
7259
|
+
unreviewed.splice(i, 1);
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
7262
|
+
budgetEntry = budgetStopDisclosure(stop.round ?? void 0);
|
|
7263
|
+
coverageEntries.push(budgetEntry);
|
|
7264
|
+
}
|
|
7265
|
+
}
|
|
7049
7266
|
const remediation = [];
|
|
7050
7267
|
const planRef = input.planPath ? shellQuotePath(input.planPath) : "<plan>";
|
|
7051
7268
|
const missingReceipts = [];
|
|
@@ -7205,6 +7422,11 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7205
7422
|
"compose-review: modelId is required (the public footer names the reviewing model)"
|
|
7206
7423
|
);
|
|
7207
7424
|
}
|
|
7425
|
+
if (!isFooterSafeModelId(modelId)) {
|
|
7426
|
+
throw new TypeError(
|
|
7427
|
+
"compose-review: modelId is interpolated into the public footer verbatim \u2014 it must be a single line that does not contain the footer marker"
|
|
7428
|
+
);
|
|
7429
|
+
}
|
|
7208
7430
|
const c = criticalsInline + bodyCriticals.length;
|
|
7209
7431
|
const s = suggestionsInline + suggestionsDiscarded;
|
|
7210
7432
|
const baseEvent = c >= 1 ? "REQUEST_CHANGES" : s >= 1 ? "COMMENT" : "APPROVE";
|
|
@@ -7217,28 +7439,28 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7217
7439
|
}
|
|
7218
7440
|
if (contextUnavailable) cappedBy.push("context-unavailable");
|
|
7219
7441
|
if (criticalsUnverified) cappedBy.push("criticals-unverified");
|
|
7220
|
-
let
|
|
7221
|
-
if (
|
|
7442
|
+
let event2 = baseEvent;
|
|
7443
|
+
if (event2 === "APPROVE" && cappedBy.length > 0) event2 = "COMMENT";
|
|
7222
7444
|
const deterministicBodyCriticals = bodyCriticals.length - nonDeterministicBodyCriticals;
|
|
7223
|
-
if (
|
|
7224
|
-
|
|
7445
|
+
if (event2 === "REQUEST_CHANGES" && criticalsUnverified && deterministicBodyCriticals === 0) {
|
|
7446
|
+
event2 = "COMMENT";
|
|
7225
7447
|
}
|
|
7226
7448
|
let downgraded = false;
|
|
7227
7449
|
let downgradedFrom = null;
|
|
7228
|
-
if (
|
|
7229
|
-
|
|
7450
|
+
if (event2 === "APPROVE" && downgradeApprove) {
|
|
7451
|
+
event2 = "COMMENT";
|
|
7230
7452
|
downgraded = true;
|
|
7231
7453
|
downgradedFrom = "Approve";
|
|
7232
|
-
} else if ((
|
|
7233
|
-
|
|
7454
|
+
} else if ((event2 === "REQUEST_CHANGES" || baseEvent === "REQUEST_CHANGES" && criticalsUnverified) && downgradeRequestChanges) {
|
|
7455
|
+
event2 = "COMMENT";
|
|
7234
7456
|
downgraded = true;
|
|
7235
7457
|
downgradedFrom = "Request changes";
|
|
7236
7458
|
}
|
|
7237
7459
|
let lowSignal = null;
|
|
7238
|
-
if (
|
|
7460
|
+
if (event2 === "APPROVE" && input.planPath) {
|
|
7239
7461
|
try {
|
|
7240
7462
|
const plan = JSON.parse(
|
|
7241
|
-
|
|
7463
|
+
readFileSync9(input.planPath, "utf8")
|
|
7242
7464
|
);
|
|
7243
7465
|
const src = Number(plan.srcDiffLines ?? 0);
|
|
7244
7466
|
if (src > LOW_SIGNAL_SRC_DIFF_LINES) {
|
|
@@ -7247,12 +7469,12 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7247
7469
|
} catch {
|
|
7248
7470
|
}
|
|
7249
7471
|
}
|
|
7250
|
-
const footer =
|
|
7472
|
+
const footer = reviewFooter(modelId, cliVersion);
|
|
7251
7473
|
const bilingual = bilingualFromPlan(input.planPath, input.prBodyFetcher);
|
|
7252
|
-
const render = /* @__PURE__ */ __name((parts,
|
|
7253
|
-
const en = parts.map((p) => p.en).join(
|
|
7474
|
+
const render = /* @__PURE__ */ __name((parts, sep5) => {
|
|
7475
|
+
const en = parts.map((p) => p.en).join(sep5);
|
|
7254
7476
|
if (en === "") return "";
|
|
7255
|
-
const zh = parts.map((p) => p.zh).join(
|
|
7477
|
+
const zh = parts.map((p) => p.zh).join(sep5);
|
|
7256
7478
|
const text = bilingual && zh !== en ? `${en}
|
|
7257
7479
|
|
|
7258
7480
|
<details>
|
|
@@ -7306,7 +7528,7 @@ ${footer}`;
|
|
|
7306
7528
|
if (seenCaller.has(d)) continue;
|
|
7307
7529
|
seenCaller.add(d);
|
|
7308
7530
|
const echoesCoverage = covEntries.some(
|
|
7309
|
-
(e) => d === e.subject || d.startsWith(`${e.subject} \u2014 `)
|
|
7531
|
+
(e) => d === e.subject || e !== budgetEntry && d.startsWith(`${e.subject} \u2014 `)
|
|
7310
7532
|
);
|
|
7311
7533
|
if (!echoesCoverage) callerLeft.push(d);
|
|
7312
7534
|
}
|
|
@@ -7386,7 +7608,7 @@ ${footer}`;
|
|
|
7386
7608
|
zh: `Test Plan\uFF08\u975E\u963B\u65AD\uFF09\uFF1A${testPlanNotes.join("; ")}\u3002`
|
|
7387
7609
|
}
|
|
7388
7610
|
] : [];
|
|
7389
|
-
if (
|
|
7611
|
+
if (event2 === "REQUEST_CHANGES") {
|
|
7390
7612
|
const parts = [
|
|
7391
7613
|
...contextUnavailable ? [contextUnavailableClause] : [],
|
|
7392
7614
|
...cannotTellBlock,
|
|
@@ -7396,7 +7618,7 @@ ${footer}`;
|
|
|
7396
7618
|
...bodyCriticalBlock
|
|
7397
7619
|
];
|
|
7398
7620
|
return {
|
|
7399
|
-
event,
|
|
7621
|
+
event: event2,
|
|
7400
7622
|
body: render(parts, "\n\n"),
|
|
7401
7623
|
baseEvent,
|
|
7402
7624
|
cappedBy,
|
|
@@ -7406,9 +7628,9 @@ ${footer}`;
|
|
|
7406
7628
|
lowSignal
|
|
7407
7629
|
};
|
|
7408
7630
|
}
|
|
7409
|
-
if (
|
|
7631
|
+
if (event2 === "APPROVE") {
|
|
7410
7632
|
return {
|
|
7411
|
-
event,
|
|
7633
|
+
event: event2,
|
|
7412
7634
|
body: render(
|
|
7413
7635
|
[
|
|
7414
7636
|
{ en: "No issues found. LGTM! \u2705", zh: "\u672A\u53D1\u73B0\u95EE\u9898\u3002LGTM\uFF01\u2705" },
|
|
@@ -7471,7 +7693,7 @@ ${footer}`;
|
|
|
7471
7693
|
clauses.push(...bodyCriticalBlock);
|
|
7472
7694
|
}
|
|
7473
7695
|
return {
|
|
7474
|
-
event,
|
|
7696
|
+
event: event2,
|
|
7475
7697
|
body: render(clauses, " "),
|
|
7476
7698
|
baseEvent,
|
|
7477
7699
|
cappedBy,
|
|
@@ -7530,7 +7752,7 @@ function scriptLintGate(planPath) {
|
|
|
7530
7752
|
const disclosed = [];
|
|
7531
7753
|
let plan;
|
|
7532
7754
|
try {
|
|
7533
|
-
plan = JSON.parse(
|
|
7755
|
+
plan = JSON.parse(readFileSync9(planPath, "utf8"));
|
|
7534
7756
|
} catch {
|
|
7535
7757
|
unreviewed.push(
|
|
7536
7758
|
"the executable-script lint \u2014 could not read the plan to check the gate"
|
|
@@ -7541,13 +7763,13 @@ function scriptLintGate(planPath) {
|
|
|
7541
7763
|
return { criticals, unreviewed, disclosed };
|
|
7542
7764
|
}
|
|
7543
7765
|
const owed = hasExecutableScript(plan);
|
|
7544
|
-
const reportPath =
|
|
7766
|
+
const reportPath = join9(
|
|
7545
7767
|
dirname4(planPath),
|
|
7546
7768
|
scriptLintReportName(plan.prNumber)
|
|
7547
7769
|
);
|
|
7548
7770
|
let report;
|
|
7549
7771
|
try {
|
|
7550
|
-
report = JSON.parse(
|
|
7772
|
+
report = JSON.parse(readFileSync9(reportPath, "utf8"));
|
|
7551
7773
|
} catch {
|
|
7552
7774
|
if (owed) {
|
|
7553
7775
|
unreviewed.push(
|
|
@@ -7603,7 +7825,7 @@ function testPlanGate(planPath) {
|
|
|
7603
7825
|
const notes = [];
|
|
7604
7826
|
let plan;
|
|
7605
7827
|
try {
|
|
7606
|
-
plan = JSON.parse(
|
|
7828
|
+
plan = JSON.parse(readFileSync9(planPath, "utf8"));
|
|
7607
7829
|
} catch {
|
|
7608
7830
|
return { notes };
|
|
7609
7831
|
}
|
|
@@ -7613,8 +7835,8 @@ function testPlanGate(planPath) {
|
|
|
7613
7835
|
let report;
|
|
7614
7836
|
try {
|
|
7615
7837
|
report = JSON.parse(
|
|
7616
|
-
|
|
7617
|
-
|
|
7838
|
+
readFileSync9(
|
|
7839
|
+
join9(dirname4(planPath), `qwen-review-pr-${pr}-test-plan.json`),
|
|
7618
7840
|
"utf8"
|
|
7619
7841
|
)
|
|
7620
7842
|
);
|
|
@@ -7647,7 +7869,7 @@ function bilingualFromPlan(planPath, fetchPrBody2 = fetchPrBodyViaGh) {
|
|
|
7647
7869
|
if (!planPath) return false;
|
|
7648
7870
|
let plan;
|
|
7649
7871
|
try {
|
|
7650
|
-
plan = JSON.parse(
|
|
7872
|
+
plan = JSON.parse(readFileSync9(planPath, "utf8"));
|
|
7651
7873
|
} catch {
|
|
7652
7874
|
return false;
|
|
7653
7875
|
}
|
|
@@ -7667,7 +7889,7 @@ __name(bilingualFromPlan, "bilingualFromPlan");
|
|
|
7667
7889
|
function readDraftedComments(path3) {
|
|
7668
7890
|
let raw;
|
|
7669
7891
|
try {
|
|
7670
|
-
raw =
|
|
7892
|
+
raw = readFileSync9(path3, "utf8");
|
|
7671
7893
|
} catch (err) {
|
|
7672
7894
|
throw new Error(
|
|
7673
7895
|
`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.`
|
|
@@ -7721,7 +7943,7 @@ var composeReviewCommand = {
|
|
|
7721
7943
|
"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."
|
|
7722
7944
|
);
|
|
7723
7945
|
}
|
|
7724
|
-
const raw =
|
|
7946
|
+
const raw = readFileSync9(input ?? 0, "utf8");
|
|
7725
7947
|
const parsed = JSON.parse(raw);
|
|
7726
7948
|
delete parsed.env;
|
|
7727
7949
|
delete parsed.prBodyFetcher;
|
|
@@ -7738,7 +7960,9 @@ var composeReviewCommand = {
|
|
|
7738
7960
|
...countInlineFindings(drafted),
|
|
7739
7961
|
draftedComments: drafted
|
|
7740
7962
|
},
|
|
7741
|
-
|
|
7963
|
+
// Same pin as `submit`: the startup stamp, not a version resolved at
|
|
7964
|
+
// compose time — a shared runner can rewrite the install mid-session.
|
|
7965
|
+
footerVersion(process.env["QWEN_CODE_STARTUP_VERSION"]) ?? await getCliVersion()
|
|
7742
7966
|
);
|
|
7743
7967
|
const json = JSON.stringify(
|
|
7744
7968
|
{ ...result, verdictLine: verdictLine(result) },
|
|
@@ -7746,8 +7970,8 @@ var composeReviewCommand = {
|
|
|
7746
7970
|
2
|
|
7747
7971
|
);
|
|
7748
7972
|
if (out) {
|
|
7749
|
-
|
|
7750
|
-
|
|
7973
|
+
mkdirSync6(dirname4(out), { recursive: true });
|
|
7974
|
+
writeFileSync6(out, json, "utf8");
|
|
7751
7975
|
}
|
|
7752
7976
|
writeStdoutLine(json);
|
|
7753
7977
|
for (const fix of result.remediation) {
|
|
@@ -7848,7 +8072,7 @@ __name(verdictLine, "verdictLine");
|
|
|
7848
8072
|
|
|
7849
8073
|
// packages/cli/src/commands/review/findings.ts
|
|
7850
8074
|
init_esbuild_shims();
|
|
7851
|
-
import { existsSync as existsSync3, readFileSync as
|
|
8075
|
+
import { existsSync as existsSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
7852
8076
|
import { dirname as dirname5, resolve as resolve5 } from "node:path";
|
|
7853
8077
|
var SEVERITIES = ["Critical", "Suggestion", "Nice to have"];
|
|
7854
8078
|
var CONFIDENCES = ["high", "low"];
|
|
@@ -7901,8 +8125,8 @@ function parseLocations(o, index) {
|
|
|
7901
8125
|
const lo = l;
|
|
7902
8126
|
const file2 = asString(lo, "file");
|
|
7903
8127
|
if (!file2) fail(index, `location ${j} is missing a non-empty "file".`);
|
|
7904
|
-
if (lo["line"] !== void 0 && typeof lo["line"] !== "number") {
|
|
7905
|
-
fail(index, `location ${j} has
|
|
8128
|
+
if (lo["line"] !== void 0 && (typeof lo["line"] !== "number" || !Number.isSafeInteger(lo["line"]) || lo["line"] <= 0)) {
|
|
8129
|
+
fail(index, `location ${j} has an invalid "line".`);
|
|
7906
8130
|
}
|
|
7907
8131
|
return {
|
|
7908
8132
|
file: file2,
|
|
@@ -7918,8 +8142,8 @@ function parseLocations(o, index) {
|
|
|
7918
8142
|
'needs a non-empty "file" (or a "locations" array for a pattern aggregate).'
|
|
7919
8143
|
);
|
|
7920
8144
|
}
|
|
7921
|
-
if (o["line"] !== void 0 && typeof o["line"] !== "number") {
|
|
7922
|
-
fail(index, 'has
|
|
8145
|
+
if (o["line"] !== void 0 && (typeof o["line"] !== "number" || !Number.isSafeInteger(o["line"]) || o["line"] <= 0)) {
|
|
8146
|
+
fail(index, 'has an invalid "line".');
|
|
7923
8147
|
}
|
|
7924
8148
|
return [
|
|
7925
8149
|
{
|
|
@@ -8222,7 +8446,7 @@ __name(renderFindings, "renderFindings");
|
|
|
8222
8446
|
function readJson(path3, what) {
|
|
8223
8447
|
let text;
|
|
8224
8448
|
try {
|
|
8225
|
-
text =
|
|
8449
|
+
text = readFileSync10(resolve5(path3), "utf8");
|
|
8226
8450
|
} catch (err) {
|
|
8227
8451
|
throw new Error(
|
|
8228
8452
|
`Could not read the ${what} file at ${JSON.stringify(path3)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -8293,8 +8517,8 @@ var findingsCommand = {
|
|
|
8293
8517
|
}
|
|
8294
8518
|
const report = buildReport(findings);
|
|
8295
8519
|
const target = resolve5(out);
|
|
8296
|
-
|
|
8297
|
-
|
|
8520
|
+
mkdirSync7(dirname5(target), { recursive: true });
|
|
8521
|
+
writeFileSync7(target, `${JSON.stringify(report, null, 2)}
|
|
8298
8522
|
`, "utf8");
|
|
8299
8523
|
const { bySeverity, byConfidence } = report.counts;
|
|
8300
8524
|
writeStderrLine(
|
|
@@ -8325,7 +8549,7 @@ var findingsCommand = {
|
|
|
8325
8549
|
// packages/cli/src/commands/review/fetch-pr.ts
|
|
8326
8550
|
init_esbuild_shims();
|
|
8327
8551
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
8328
|
-
import { mkdirSync as
|
|
8552
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
8329
8553
|
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
8330
8554
|
|
|
8331
8555
|
// packages/cli/src/commands/review/lib/git.ts
|
|
@@ -8433,11 +8657,11 @@ var LITERAL_PATHSPECS = "--literal-pathspecs";
|
|
|
8433
8657
|
|
|
8434
8658
|
// packages/cli/src/commands/review/lib/effort.ts
|
|
8435
8659
|
init_esbuild_shims();
|
|
8436
|
-
import { readFileSync as
|
|
8660
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
8437
8661
|
function resolveEffort(explicit) {
|
|
8438
8662
|
if (explicit && EFFORT_LEVELS.has(explicit)) return explicit;
|
|
8439
8663
|
try {
|
|
8440
|
-
const parsed = JSON.parse(
|
|
8664
|
+
const parsed = JSON.parse(readFileSync11(PARSE_ARGS_REPORT, "utf8"));
|
|
8441
8665
|
if (typeof parsed.effort === "string" && EFFORT_LEVELS.has(parsed.effort)) {
|
|
8442
8666
|
return parsed.effort;
|
|
8443
8667
|
}
|
|
@@ -8458,7 +8682,7 @@ __name(planEffortField, "planEffortField");
|
|
|
8458
8682
|
|
|
8459
8683
|
// packages/cli/src/commands/review/lib/report.ts
|
|
8460
8684
|
init_esbuild_shims();
|
|
8461
|
-
import { statSync as
|
|
8685
|
+
import { statSync as statSync4 } from "node:fs";
|
|
8462
8686
|
|
|
8463
8687
|
// packages/cli/src/commands/review/lib/heavy.ts
|
|
8464
8688
|
init_esbuild_shims();
|
|
@@ -8561,7 +8785,7 @@ __name(buildPlanReport, "buildPlanReport");
|
|
|
8561
8785
|
function warnOnReportSize(path3, cap) {
|
|
8562
8786
|
let size = 0;
|
|
8563
8787
|
try {
|
|
8564
|
-
size =
|
|
8788
|
+
size = statSync4(path3).size;
|
|
8565
8789
|
} catch {
|
|
8566
8790
|
return;
|
|
8567
8791
|
}
|
|
@@ -8684,7 +8908,7 @@ async function runFetchPr(args) {
|
|
|
8684
8908
|
);
|
|
8685
8909
|
}
|
|
8686
8910
|
try {
|
|
8687
|
-
|
|
8911
|
+
mkdirSync8(dirname6(wt), { recursive: true });
|
|
8688
8912
|
git("worktree", "add", wt, ref);
|
|
8689
8913
|
} catch (err) {
|
|
8690
8914
|
tryRemove(
|
|
@@ -8694,7 +8918,7 @@ async function runFetchPr(args) {
|
|
|
8694
8918
|
`Failed to create worktree at ${wt}: ${err.message}`
|
|
8695
8919
|
);
|
|
8696
8920
|
}
|
|
8697
|
-
|
|
8921
|
+
mkdirSync8(REVIEW_TMP_DIR, { recursive: true });
|
|
8698
8922
|
const { sha: mergeBaseSha, baseFetchFailed } = resolveMergeBase(
|
|
8699
8923
|
remote,
|
|
8700
8924
|
meta.baseRefName,
|
|
@@ -8718,7 +8942,7 @@ async function runFetchPr(args) {
|
|
|
8718
8942
|
...PINNED_DIFF_FLAGS,
|
|
8719
8943
|
`${mergeBaseSha}..${fetchedSha}`
|
|
8720
8944
|
);
|
|
8721
|
-
|
|
8945
|
+
writeFileSync8(diffRel, buf);
|
|
8722
8946
|
diffText = buf.toString("utf8");
|
|
8723
8947
|
diffPath = diffRel;
|
|
8724
8948
|
diffPathAbsolute = resolve6(diffRel);
|
|
@@ -8745,7 +8969,7 @@ async function runFetchPr(args) {
|
|
|
8745
8969
|
let auditSince = fetchedAt;
|
|
8746
8970
|
let prevRaw = null;
|
|
8747
8971
|
try {
|
|
8748
|
-
prevRaw =
|
|
8972
|
+
prevRaw = readFileSync12(out, "utf8");
|
|
8749
8973
|
} catch (err) {
|
|
8750
8974
|
const code = err.code;
|
|
8751
8975
|
if (code !== "ENOENT") {
|
|
@@ -8828,7 +9052,7 @@ async function runFetchPr(args) {
|
|
|
8828
9052
|
...buildPlanReport(plan, (path3) => fileLineCount(fetchedSha, path3)),
|
|
8829
9053
|
...planEffortField(args.effort)
|
|
8830
9054
|
};
|
|
8831
|
-
|
|
9055
|
+
writeFileSync8(out, stringifyPlanReport(result), "utf8");
|
|
8832
9056
|
writeStdoutLine(`Wrote fetch-pr report to ${out}`);
|
|
8833
9057
|
if (diffPath) writeStdoutLine(`Wrote review diff to ${diffPath}`);
|
|
8834
9058
|
writeStderrLine(
|
|
@@ -8912,13 +9136,13 @@ var fetchPrCommand = {
|
|
|
8912
9136
|
|
|
8913
9137
|
// packages/cli/src/commands/review/capture-local.ts
|
|
8914
9138
|
init_esbuild_shims();
|
|
8915
|
-
import { mkdirSync as
|
|
9139
|
+
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
8916
9140
|
import { dirname as dirname7, resolve as resolve8 } from "node:path";
|
|
8917
9141
|
|
|
8918
9142
|
// packages/cli/src/commands/review/lib/local-diff.ts
|
|
8919
9143
|
init_esbuild_shims();
|
|
8920
|
-
import { lstatSync as lstatSync2, statSync as
|
|
8921
|
-
import { join as
|
|
9144
|
+
import { lstatSync as lstatSync2, statSync as statSync5, realpathSync as realpathSync2 } from "node:fs";
|
|
9145
|
+
import { join as join10, relative as relative2, resolve as resolve7, isAbsolute as isAbsolute2, sep as sep2 } from "node:path";
|
|
8922
9146
|
var MAX_UNTRACKED_BYTES = 1e6;
|
|
8923
9147
|
var MAX_UNTRACKED_FILES = 500;
|
|
8924
9148
|
var MAX_UNTRACKED_TOTAL_BYTES = 1e7;
|
|
@@ -8939,7 +9163,7 @@ function describeUndiffable(abs, st) {
|
|
|
8939
9163
|
}
|
|
8940
9164
|
if (st.isSymbolicLink()) {
|
|
8941
9165
|
try {
|
|
8942
|
-
return
|
|
9166
|
+
return statSync5(abs).isDirectory() ? "is a symlink to a directory \u2014 git cannot diff it as a file" : null;
|
|
8943
9167
|
} catch {
|
|
8944
9168
|
return null;
|
|
8945
9169
|
}
|
|
@@ -9044,7 +9268,7 @@ function captureLocalDiff(opts) {
|
|
|
9044
9268
|
for (const path3 of candidates) {
|
|
9045
9269
|
let bytes;
|
|
9046
9270
|
try {
|
|
9047
|
-
const abs =
|
|
9271
|
+
const abs = join10(repoRoot, path3);
|
|
9048
9272
|
const st = lstatSync2(abs);
|
|
9049
9273
|
const kind = describeUndiffable(abs, st);
|
|
9050
9274
|
if (kind) {
|
|
@@ -9136,10 +9360,10 @@ function runCaptureLocal(args) {
|
|
|
9136
9360
|
includeUntracked: args.untracked
|
|
9137
9361
|
});
|
|
9138
9362
|
const diffText = capture.diff.toString("utf8");
|
|
9139
|
-
|
|
9140
|
-
|
|
9363
|
+
mkdirSync9(REVIEW_TMP_DIR, { recursive: true });
|
|
9364
|
+
mkdirSync9(dirname7(resolve8(out)), { recursive: true });
|
|
9141
9365
|
const diffPath = tmpFile(target, "diff.txt");
|
|
9142
|
-
|
|
9366
|
+
writeFileSync9(diffPath, capture.diff);
|
|
9143
9367
|
const plan = buildDiffPlan(diffText);
|
|
9144
9368
|
const result = {
|
|
9145
9369
|
diffPath,
|
|
@@ -9152,7 +9376,7 @@ function runCaptureLocal(args) {
|
|
|
9152
9376
|
skippedFiles: capture.skipped,
|
|
9153
9377
|
...planEffortField(args.effort)
|
|
9154
9378
|
};
|
|
9155
|
-
|
|
9379
|
+
writeFileSync9(out, stringifyPlanReport(result), "utf8");
|
|
9156
9380
|
writeStdoutLine(`Wrote diff to ${diffPath} and plan to ${out}`);
|
|
9157
9381
|
if (capture.unbornHead) {
|
|
9158
9382
|
writeStderrLine(
|
|
@@ -9210,13 +9434,13 @@ var captureLocalCommand = {
|
|
|
9210
9434
|
|
|
9211
9435
|
// packages/cli/src/commands/review/plan-diff.ts
|
|
9212
9436
|
init_esbuild_shims();
|
|
9213
|
-
import { readFileSync as
|
|
9437
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
9214
9438
|
import { resolve as resolve9 } from "node:path";
|
|
9215
9439
|
function runPlanDiff(args) {
|
|
9216
9440
|
const { diff_path: diffPath, out } = args;
|
|
9217
9441
|
let diffText;
|
|
9218
9442
|
try {
|
|
9219
|
-
diffText =
|
|
9443
|
+
diffText = readFileSync13(diffPath, "utf8");
|
|
9220
9444
|
} catch (err) {
|
|
9221
9445
|
throw new Error(
|
|
9222
9446
|
`Cannot read diff file ${diffPath}: ${err.message}`
|
|
@@ -9243,8 +9467,8 @@ function runPlanDiff(args) {
|
|
|
9243
9467
|
...buildPlanReport(plan, null),
|
|
9244
9468
|
...planEffortField(args.effort)
|
|
9245
9469
|
};
|
|
9246
|
-
|
|
9247
|
-
|
|
9470
|
+
mkdirSync10(REVIEW_TMP_DIR, { recursive: true });
|
|
9471
|
+
writeFileSync10(out, stringifyPlanReport(result), "utf8");
|
|
9248
9472
|
writeStdoutLine(`Wrote diff plan to ${out}`);
|
|
9249
9473
|
if (plan.diffLines === 0) {
|
|
9250
9474
|
writeStderrLine(
|
|
@@ -9290,8 +9514,8 @@ var planDiffCommand = {
|
|
|
9290
9514
|
|
|
9291
9515
|
// packages/cli/src/commands/review/pr-context.ts
|
|
9292
9516
|
init_esbuild_shims();
|
|
9293
|
-
import { mkdirSync as
|
|
9294
|
-
import { dirname as dirname8, join as
|
|
9517
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
9518
|
+
import { dirname as dirname8, join as join11 } from "node:path";
|
|
9295
9519
|
var SUMMARY_MARKER = "<!-- qwen-review-suggestion-summary -->";
|
|
9296
9520
|
function isLegacySuggestionSummary(body) {
|
|
9297
9521
|
return (body ?? "").includes(SUMMARY_MARKER);
|
|
@@ -9769,9 +9993,9 @@ async function runPrContext(args) {
|
|
|
9769
9993
|
}
|
|
9770
9994
|
if (prevLedger) {
|
|
9771
9995
|
try {
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9996
|
+
mkdirSync11(dirname8(out), { recursive: true });
|
|
9997
|
+
writeFileSync11(
|
|
9998
|
+
join11(dirname8(out), `qwen-review-pr-${prNumber}-prev-ledger.json`),
|
|
9775
9999
|
JSON.stringify(prevLedger, null, 2)
|
|
9776
10000
|
);
|
|
9777
10001
|
} catch {
|
|
@@ -9786,8 +10010,8 @@ async function runPrContext(args) {
|
|
|
9786
10010
|
reviews,
|
|
9787
10011
|
prevLedger
|
|
9788
10012
|
);
|
|
9789
|
-
|
|
9790
|
-
|
|
10013
|
+
mkdirSync11(dirname8(out), { recursive: true });
|
|
10014
|
+
writeFileSync11(out, md, "utf8");
|
|
9791
10015
|
const meaningfulReviewCount = reviews.filter(
|
|
9792
10016
|
(r) => isReviewWorthShowing(stripLedgerMarker(r.body ?? ""))
|
|
9793
10017
|
).length;
|
|
@@ -9841,7 +10065,7 @@ var prContextCommand = {
|
|
|
9841
10065
|
|
|
9842
10066
|
// packages/cli/src/commands/review/comment-status.ts
|
|
9843
10067
|
init_esbuild_shims();
|
|
9844
|
-
import { mkdirSync as
|
|
10068
|
+
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "node:fs";
|
|
9845
10069
|
import { dirname as dirname9 } from "node:path";
|
|
9846
10070
|
var TOUCHED_BY_CAP = 10;
|
|
9847
10071
|
function buildThreadStatuses(comments, prAuthor, probe) {
|
|
@@ -10047,9 +10271,9 @@ async function runCommentStatus(args) {
|
|
|
10047
10271
|
summary,
|
|
10048
10272
|
threads
|
|
10049
10273
|
};
|
|
10050
|
-
|
|
10274
|
+
mkdirSync12(dirname9(out), { recursive: true });
|
|
10051
10275
|
const json = JSON.stringify(report, null, 2) + "\n";
|
|
10052
|
-
|
|
10276
|
+
writeFileSync12(out, json, "utf8");
|
|
10053
10277
|
writeStdoutLine(
|
|
10054
10278
|
`Wrote comment-status report to ${out} (${comments.length} inline comments in ${summary.threads} threads: ${summary.outdated} outdated, ${summary.blockers} blocker(s), ${summary.changedSinceComment} on files changed since their comment, ${summary.withReplies} with replies, ${summary.authorReplied} answered by the PR author)`
|
|
10055
10279
|
);
|
|
@@ -10077,8 +10301,8 @@ async function runCommentStatus(args) {
|
|
|
10077
10301
|
writeStdoutLine(
|
|
10078
10302
|
`warning: comment-status failed: ${msg}. It is an index, not the evidence \u2014 re-derive thread statuses per-comment if needed.`
|
|
10079
10303
|
);
|
|
10080
|
-
|
|
10081
|
-
|
|
10304
|
+
mkdirSync12(dirname9(out), { recursive: true });
|
|
10305
|
+
writeFileSync12(
|
|
10082
10306
|
out,
|
|
10083
10307
|
JSON.stringify(
|
|
10084
10308
|
{
|
|
@@ -10140,7 +10364,7 @@ var commentStatusCommand = {
|
|
|
10140
10364
|
|
|
10141
10365
|
// packages/cli/src/commands/review/load-rules.ts
|
|
10142
10366
|
init_esbuild_shims();
|
|
10143
|
-
import { mkdirSync as
|
|
10367
|
+
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
10144
10368
|
import { dirname as dirname10 } from "node:path";
|
|
10145
10369
|
function showFile(baseRef, path3) {
|
|
10146
10370
|
return gitOpt("show", `${baseRef}:${path3}`);
|
|
@@ -10221,8 +10445,8 @@ __name(loadCombined, "loadCombined");
|
|
|
10221
10445
|
async function runLoadRules(args) {
|
|
10222
10446
|
const { base_ref: baseRef, out } = args;
|
|
10223
10447
|
const { combined, loaded } = loadCombined(baseRef);
|
|
10224
|
-
|
|
10225
|
-
|
|
10448
|
+
mkdirSync13(dirname10(out), { recursive: true });
|
|
10449
|
+
writeFileSync13(out, combined, "utf8");
|
|
10226
10450
|
if (loaded.length === 0) {
|
|
10227
10451
|
writeStdoutLine(
|
|
10228
10452
|
`No review rules found on ${baseRef}; wrote empty file to ${out}`
|
|
@@ -10253,7 +10477,7 @@ var loadRulesCommand = {
|
|
|
10253
10477
|
|
|
10254
10478
|
// packages/cli/src/commands/review/presubmit.ts
|
|
10255
10479
|
init_esbuild_shims();
|
|
10256
|
-
import { writeFileSync as
|
|
10480
|
+
import { writeFileSync as writeFileSync14, readFileSync as readFileSync14 } from "node:fs";
|
|
10257
10481
|
function verdictStamp(run4) {
|
|
10258
10482
|
return run4.completed_at ?? run4.started_at ?? "";
|
|
10259
10483
|
}
|
|
@@ -10289,7 +10513,7 @@ __name(isCurrentActionsRunCheck, "isCurrentActionsRunCheck");
|
|
|
10289
10513
|
function parseFindingsFile(path3) {
|
|
10290
10514
|
let parsed;
|
|
10291
10515
|
try {
|
|
10292
|
-
parsed = JSON.parse(
|
|
10516
|
+
parsed = JSON.parse(readFileSync14(path3, "utf8"));
|
|
10293
10517
|
} catch {
|
|
10294
10518
|
return null;
|
|
10295
10519
|
}
|
|
@@ -10592,7 +10816,7 @@ async function runPresubmit(args) {
|
|
|
10592
10816
|
findingsFileInvalid,
|
|
10593
10817
|
headDrift
|
|
10594
10818
|
};
|
|
10595
|
-
|
|
10819
|
+
writeFileSync14(outPath, JSON.stringify(result, null, 2) + "\n", "utf8");
|
|
10596
10820
|
writeStdoutLine(`Wrote presubmit report to ${outPath}`);
|
|
10597
10821
|
}
|
|
10598
10822
|
__name(runPresubmit, "runPresubmit");
|
|
@@ -10631,17 +10855,17 @@ var presubmitCommand = {
|
|
|
10631
10855
|
// packages/cli/src/commands/review/publish-assets.ts
|
|
10632
10856
|
init_esbuild_shims();
|
|
10633
10857
|
import { createHash as createHash2 } from "node:crypto";
|
|
10634
|
-
import { readFileSync as
|
|
10858
|
+
import { readFileSync as readFileSync16, statSync as statSync6, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "node:fs";
|
|
10635
10859
|
import { basename as basename5, dirname as dirname11, resolve as resolve10 } from "node:path";
|
|
10636
10860
|
|
|
10637
10861
|
// packages/cli/src/commands/review/lib/authorization.ts
|
|
10638
10862
|
init_esbuild_shims();
|
|
10639
|
-
import { readFileSync as
|
|
10863
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
10640
10864
|
|
|
10641
10865
|
// packages/cli/src/services/skill-args-file.ts
|
|
10642
10866
|
init_esbuild_shims();
|
|
10643
10867
|
import {
|
|
10644
|
-
mkdirSync as
|
|
10868
|
+
mkdirSync as mkdirSync14,
|
|
10645
10869
|
openSync as openSync2,
|
|
10646
10870
|
writeSync,
|
|
10647
10871
|
closeSync as closeSync2,
|
|
@@ -10650,9 +10874,9 @@ import {
|
|
|
10650
10874
|
existsSync as existsSync5,
|
|
10651
10875
|
constants
|
|
10652
10876
|
} from "node:fs";
|
|
10653
|
-
import { join as
|
|
10877
|
+
import { join as join12 } from "node:path";
|
|
10654
10878
|
var debugLogger3 = createDebugLogger("SKILL_ARGS_FILE");
|
|
10655
|
-
var SKILL_ARGS_DIR =
|
|
10879
|
+
var SKILL_ARGS_DIR = join12(".qwen", "tmp");
|
|
10656
10880
|
function safe(s) {
|
|
10657
10881
|
return s.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
10658
10882
|
}
|
|
@@ -10662,11 +10886,11 @@ function currentSessionId() {
|
|
|
10662
10886
|
}
|
|
10663
10887
|
__name(currentSessionId, "currentSessionId");
|
|
10664
10888
|
function skillArgsDir(sessionId = currentSessionId()) {
|
|
10665
|
-
return sessionId ?
|
|
10889
|
+
return sessionId ? join12(SKILL_ARGS_DIR, `s-${safe(sessionId)}`) : SKILL_ARGS_DIR;
|
|
10666
10890
|
}
|
|
10667
10891
|
__name(skillArgsDir, "skillArgsDir");
|
|
10668
10892
|
function skillArgsPath(skillName, sessionId = currentSessionId()) {
|
|
10669
|
-
return
|
|
10893
|
+
return join12(
|
|
10670
10894
|
skillArgsDir(sessionId),
|
|
10671
10895
|
`qwen-skill-args-${safe(skillName)}.txt`
|
|
10672
10896
|
);
|
|
@@ -10676,7 +10900,7 @@ function writeSkillArgs(skillName, args) {
|
|
|
10676
10900
|
const path3 = skillArgsPath(skillName);
|
|
10677
10901
|
try {
|
|
10678
10902
|
const dir = skillArgsDir();
|
|
10679
|
-
|
|
10903
|
+
mkdirSync14(dir, { recursive: true });
|
|
10680
10904
|
if (lstatSync3(dir).isSymbolicLink()) {
|
|
10681
10905
|
debugLogger3.warn(
|
|
10682
10906
|
`Skill args directory ${dir} is a symlink; refusing to write through it.`
|
|
@@ -10759,7 +10983,7 @@ function reviewWriteAuthorization(req) {
|
|
|
10759
10983
|
const path3 = currentSessionId() === "" && req.skillArgs ? req.skillArgs : sessionScoped;
|
|
10760
10984
|
let raw;
|
|
10761
10985
|
try {
|
|
10762
|
-
raw =
|
|
10986
|
+
raw = readFileSync15(path3, "utf8");
|
|
10763
10987
|
} catch {
|
|
10764
10988
|
return {
|
|
10765
10989
|
ok: false,
|
|
@@ -11025,7 +11249,7 @@ function runPublishAssets(args) {
|
|
|
11025
11249
|
const fileList = [...args.files ?? []];
|
|
11026
11250
|
if (args.findings) {
|
|
11027
11251
|
try {
|
|
11028
|
-
const artifact = JSON.parse(
|
|
11252
|
+
const artifact = JSON.parse(readFileSync16(resolve10(args.findings), "utf8"));
|
|
11029
11253
|
findings = validateFindings(
|
|
11030
11254
|
Array.isArray(artifact) ? artifact : artifact.findings
|
|
11031
11255
|
);
|
|
@@ -11055,7 +11279,7 @@ function runPublishAssets(args) {
|
|
|
11055
11279
|
for (const file of unique) {
|
|
11056
11280
|
const abs = resolve10(file);
|
|
11057
11281
|
try {
|
|
11058
|
-
const st =
|
|
11282
|
+
const st = statSync6(abs);
|
|
11059
11283
|
if (!st.isFile()) throw new Error("not a regular file");
|
|
11060
11284
|
stats.push({ file, abs, basename: basename5(abs), bytes: st.size });
|
|
11061
11285
|
} catch (err) {
|
|
@@ -11074,7 +11298,7 @@ function runPublishAssets(args) {
|
|
|
11074
11298
|
for (const st of stats) {
|
|
11075
11299
|
let content;
|
|
11076
11300
|
try {
|
|
11077
|
-
content =
|
|
11301
|
+
content = readFileSync16(st.abs);
|
|
11078
11302
|
} catch (err) {
|
|
11079
11303
|
refuse(
|
|
11080
11304
|
`cannot read ${JSON.stringify(st.file)}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -11121,8 +11345,8 @@ function runPublishAssets(args) {
|
|
|
11121
11345
|
published
|
|
11122
11346
|
};
|
|
11123
11347
|
const outPath = resolve10(args.out);
|
|
11124
|
-
|
|
11125
|
-
|
|
11348
|
+
mkdirSync15(dirname11(outPath), { recursive: true });
|
|
11349
|
+
writeFileSync15(outPath, `${JSON.stringify(manifest, null, 2)}
|
|
11126
11350
|
`, "utf8");
|
|
11127
11351
|
if (findings && !args.findingsOut) {
|
|
11128
11352
|
writeStderrLine(
|
|
@@ -11137,8 +11361,8 @@ function runPublishAssets(args) {
|
|
|
11137
11361
|
});
|
|
11138
11362
|
const report = buildReport(updated);
|
|
11139
11363
|
const fOut = resolve10(args.findingsOut);
|
|
11140
|
-
|
|
11141
|
-
|
|
11364
|
+
mkdirSync15(dirname11(fOut), { recursive: true });
|
|
11365
|
+
writeFileSync15(fOut, `${JSON.stringify(report, null, 2)}
|
|
11142
11366
|
`, "utf8");
|
|
11143
11367
|
}
|
|
11144
11368
|
writeStderrLine(
|
|
@@ -11200,7 +11424,7 @@ var publishAssetsCommand = {
|
|
|
11200
11424
|
|
|
11201
11425
|
// packages/cli/src/commands/review/resolve-anchors.ts
|
|
11202
11426
|
init_esbuild_shims();
|
|
11203
|
-
import { readFileSync as
|
|
11427
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16 } from "node:fs";
|
|
11204
11428
|
import { dirname as dirname12, resolve as resolve11 } from "node:path";
|
|
11205
11429
|
|
|
11206
11430
|
// packages/cli/src/commands/review/lib/anchors.ts
|
|
@@ -11398,8 +11622,8 @@ function validateRequests(raw) {
|
|
|
11398
11622
|
);
|
|
11399
11623
|
}
|
|
11400
11624
|
}
|
|
11401
|
-
if (o["line"] !== void 0 && typeof o["line"] !== "number") {
|
|
11402
|
-
throw new Error(`Finding "${o["id"]}" has
|
|
11625
|
+
if (o["line"] !== void 0 && (typeof o["line"] !== "number" || !Number.isSafeInteger(o["line"]) || o["line"] <= 0)) {
|
|
11626
|
+
throw new Error(`Finding "${o["id"]}" has an invalid "line".`);
|
|
11403
11627
|
}
|
|
11404
11628
|
return {
|
|
11405
11629
|
id: o["id"],
|
|
@@ -11425,7 +11649,7 @@ __name(validateRequests, "validateRequests");
|
|
|
11425
11649
|
function runResolveAnchors(args) {
|
|
11426
11650
|
let diffText;
|
|
11427
11651
|
try {
|
|
11428
|
-
diffText =
|
|
11652
|
+
diffText = readFileSync17(args.diff, "utf8");
|
|
11429
11653
|
} catch (err) {
|
|
11430
11654
|
throw new Error(
|
|
11431
11655
|
`Cannot read diff file ${args.diff}: ${err.message}`
|
|
@@ -11433,7 +11657,7 @@ function runResolveAnchors(args) {
|
|
|
11433
11657
|
}
|
|
11434
11658
|
let rawText;
|
|
11435
11659
|
try {
|
|
11436
|
-
rawText =
|
|
11660
|
+
rawText = readFileSync17(args.input, "utf8");
|
|
11437
11661
|
} catch (err) {
|
|
11438
11662
|
throw new Error(
|
|
11439
11663
|
`Cannot read findings file ${args.input}: ${err.message}`
|
|
@@ -11464,8 +11688,8 @@ function runResolveAnchors(args) {
|
|
|
11464
11688
|
loose: resolved.filter((r) => r.tier?.startsWith("loose")).length
|
|
11465
11689
|
}
|
|
11466
11690
|
};
|
|
11467
|
-
|
|
11468
|
-
|
|
11691
|
+
mkdirSync16(dirname12(resolve11(args.out)), { recursive: true });
|
|
11692
|
+
writeFileSync16(args.out, JSON.stringify(report, null, 2), "utf8");
|
|
11469
11693
|
writeStdoutLine(`Wrote resolved anchors to ${args.out}`);
|
|
11470
11694
|
const s = report.stats;
|
|
11471
11695
|
writeStderrLine(
|
|
@@ -11512,7 +11736,7 @@ var resolveAnchorsCommand = {
|
|
|
11512
11736
|
|
|
11513
11737
|
// packages/cli/src/commands/review/check-coverage.ts
|
|
11514
11738
|
init_esbuild_shims();
|
|
11515
|
-
import { writeFileSync as
|
|
11739
|
+
import { writeFileSync as writeFileSync17, mkdirSync as mkdirSync17 } from "node:fs";
|
|
11516
11740
|
import { dirname as dirname13, resolve as resolve12 } from "node:path";
|
|
11517
11741
|
function runCheckCoverage(args) {
|
|
11518
11742
|
let report;
|
|
@@ -11529,8 +11753,8 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
11529
11753
|
}
|
|
11530
11754
|
throw err;
|
|
11531
11755
|
}
|
|
11532
|
-
|
|
11533
|
-
|
|
11756
|
+
mkdirSync17(dirname13(resolve12(args.out)), { recursive: true });
|
|
11757
|
+
writeFileSync17(args.out, JSON.stringify(report, null, 2));
|
|
11534
11758
|
writeStdoutLine(`Wrote coverage report to ${args.out}`);
|
|
11535
11759
|
const totalChunks = report.coveredChunks.length + report.missingChunks.length + report.uncoverableChunks.length;
|
|
11536
11760
|
const worked = report.agents - report.blindAgents.length - report.idleAgents.length;
|
|
@@ -11547,6 +11771,11 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
11547
11771
|
`ERROR: ${report.rewrittenPrompts.length} agent(s) were not launched with the prompt this CLI built for them \u2014 ${report.rewrittenPrompts.join("; ")}. \`agent-prompt\` prints a prompt to be passed VERBATIM; a summary of it is not it. The last run to paraphrase one dropped the rule against reciting a stock sentence and replaced the project's review rules with three sentences of its own. Re-run \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt\` and pass its output unedited \u2014 copy it, do not retype it.`
|
|
11548
11772
|
);
|
|
11549
11773
|
}
|
|
11774
|
+
if (report.driftedLaunches.length > 0) {
|
|
11775
|
+
writeStderrLine(
|
|
11776
|
+
`NOTE: ${report.driftedLaunches.length} agent(s) launched with a near-verbatim prompt \u2014 ${report.driftedLaunches.join("; ")}. Their briefs were opened and the work is on record, so the delivery stands and NO relaunch is owed. Copy future blocks exactly \u2014 one edited word is what turns a clean pass into this note.`
|
|
11777
|
+
);
|
|
11778
|
+
}
|
|
11550
11779
|
if (report.missingRoles.length > 0) {
|
|
11551
11780
|
writeStderrLine(
|
|
11552
11781
|
// No count: when no role was briefed at all, `missingRoles` collapses to one
|
|
@@ -11624,8 +11853,8 @@ var checkCoverageCommand = {
|
|
|
11624
11853
|
// packages/cli/src/commands/review/agent-prompt.ts
|
|
11625
11854
|
init_esbuild_shims();
|
|
11626
11855
|
import { createHash as createHash3 } from "node:crypto";
|
|
11627
|
-
import { readFileSync as
|
|
11628
|
-
import { dirname as dirname14, join as
|
|
11856
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
11857
|
+
import { dirname as dirname14, join as join13, resolve as resolve13 } from "node:path";
|
|
11629
11858
|
|
|
11630
11859
|
// packages/cli/src/commands/review/lib/path-rules.ts
|
|
11631
11860
|
init_esbuild_shims();
|
|
@@ -12077,7 +12306,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
12077
12306
|
"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."
|
|
12078
12307
|
);
|
|
12079
12308
|
}
|
|
12080
|
-
const ctx = opts.planPath ?
|
|
12309
|
+
const ctx = opts.planPath ? join13(dirname14(resolve13(opts.planPath)), `qwen-review-pr-${pr}-context.md`) : null;
|
|
12081
12310
|
parts.push(
|
|
12082
12311
|
"",
|
|
12083
12312
|
`**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.`
|
|
@@ -12336,7 +12565,7 @@ The \`description\` parameter of each Agent call is the task name the user watch
|
|
|
12336
12565
|
);
|
|
12337
12566
|
}
|
|
12338
12567
|
__name(runRoster, "runRoster");
|
|
12339
|
-
function
|
|
12568
|
+
function requireAuditableChunks(report) {
|
|
12340
12569
|
if (!Array.isArray(report.chunks) || report.chunks.length === 0) {
|
|
12341
12570
|
throw new Error("agent-prompt: the plan has no `chunks[]`.");
|
|
12342
12571
|
}
|
|
@@ -12347,6 +12576,11 @@ function runAllChunks(report, planPath, role, findingsContent, rules, round) {
|
|
|
12347
12576
|
`agent-prompt: the plan has ${problem} \u2014 a round built from what remains would look complete while a territory goes unaudited. Re-run the Step 1 capture; do not hand-edit the plan.`
|
|
12348
12577
|
);
|
|
12349
12578
|
}
|
|
12579
|
+
return chunks;
|
|
12580
|
+
}
|
|
12581
|
+
__name(requireAuditableChunks, "requireAuditableChunks");
|
|
12582
|
+
function runAllChunks(report, planPath, role, findingsContent, rules, round) {
|
|
12583
|
+
const chunks = requireAuditableChunks(report);
|
|
12350
12584
|
const digest = findingsDigest(findingsContent, rules);
|
|
12351
12585
|
const roundPart = round !== void 0 ? `--round-${round}` : "";
|
|
12352
12586
|
const blocks = chunks.map((c, i) => {
|
|
@@ -12452,6 +12686,11 @@ function runAgentPrompt(args) {
|
|
|
12452
12686
|
);
|
|
12453
12687
|
}
|
|
12454
12688
|
}
|
|
12689
|
+
if (role === "reverse-audit" && !hasRound) {
|
|
12690
|
+
bad(
|
|
12691
|
+
"--role reverse-audit builds one round of the Step 5 loop and requires --round <k>: the label keys the record and the budget gate's per-round accounting."
|
|
12692
|
+
);
|
|
12693
|
+
}
|
|
12455
12694
|
} else if (hasFindings) {
|
|
12456
12695
|
const findingRoles = Object.keys(BRIEFS).filter(
|
|
12457
12696
|
(r) => BRIEFS[r].acceptsFindings
|
|
@@ -12482,7 +12721,7 @@ function runAgentPrompt(args) {
|
|
|
12482
12721
|
}
|
|
12483
12722
|
let report;
|
|
12484
12723
|
try {
|
|
12485
|
-
report = JSON.parse(
|
|
12724
|
+
report = JSON.parse(readFileSync18(args.plan, "utf8"));
|
|
12486
12725
|
} catch (err) {
|
|
12487
12726
|
throw new Error(
|
|
12488
12727
|
`agent-prompt: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -12491,7 +12730,7 @@ function runAgentPrompt(args) {
|
|
|
12491
12730
|
let rules;
|
|
12492
12731
|
if (args.rules) {
|
|
12493
12732
|
try {
|
|
12494
|
-
rules =
|
|
12733
|
+
rules = readFileSync18(args.rules, "utf8");
|
|
12495
12734
|
} catch (err) {
|
|
12496
12735
|
throw new Error(
|
|
12497
12736
|
`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.`
|
|
@@ -12506,7 +12745,7 @@ function runAgentPrompt(args) {
|
|
|
12506
12745
|
if (hasFindings && args.role) {
|
|
12507
12746
|
const role = args.role;
|
|
12508
12747
|
try {
|
|
12509
|
-
findingsContent =
|
|
12748
|
+
findingsContent = readFileSync18(args.findings, "utf8");
|
|
12510
12749
|
} catch (err) {
|
|
12511
12750
|
throw new Error(
|
|
12512
12751
|
`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).`
|
|
@@ -12518,6 +12757,21 @@ function runAgentPrompt(args) {
|
|
|
12518
12757
|
);
|
|
12519
12758
|
}
|
|
12520
12759
|
}
|
|
12760
|
+
if (args.allChunks && args.role && findingsContent !== void 0) {
|
|
12761
|
+
requireAuditableChunks(report);
|
|
12762
|
+
}
|
|
12763
|
+
if (args.role === "reverse-audit") {
|
|
12764
|
+
const spent = reverseAuditBudgetExhausted(
|
|
12765
|
+
process.env,
|
|
12766
|
+
expectedRoundSeconds(args.plan, args.round)
|
|
12767
|
+
);
|
|
12768
|
+
if (spent !== null) {
|
|
12769
|
+
writeBudgetStop(args.plan, spent, args.round);
|
|
12770
|
+
writeStderrLine(reverseAuditBudgetMessage(spent, args.round));
|
|
12771
|
+
process.exitCode = 4;
|
|
12772
|
+
return;
|
|
12773
|
+
}
|
|
12774
|
+
}
|
|
12521
12775
|
if (args.allChunks && args.role && findingsContent !== void 0) {
|
|
12522
12776
|
runAllChunks(
|
|
12523
12777
|
report,
|
|
@@ -12527,6 +12781,9 @@ function runAgentPrompt(args) {
|
|
|
12527
12781
|
rules,
|
|
12528
12782
|
args.round
|
|
12529
12783
|
);
|
|
12784
|
+
if (args.role === "reverse-audit") {
|
|
12785
|
+
stampRound(args.plan, args.round);
|
|
12786
|
+
}
|
|
12530
12787
|
return;
|
|
12531
12788
|
}
|
|
12532
12789
|
let prompt;
|
|
@@ -12557,11 +12814,14 @@ function runAgentPrompt(args) {
|
|
|
12557
12814
|
const printed = findingsContent !== void 0 && args.role ? foldFindings(args.role, findingsContent, prompt) : prompt;
|
|
12558
12815
|
recordPrompt(args.plan, key, printed);
|
|
12559
12816
|
writeStdoutLine(printed);
|
|
12817
|
+
if (args.role === "reverse-audit") {
|
|
12818
|
+
stampRound(args.plan, args.round);
|
|
12819
|
+
}
|
|
12560
12820
|
}
|
|
12561
12821
|
__name(runAgentPrompt, "runAgentPrompt");
|
|
12562
12822
|
var agentPromptCommand = {
|
|
12563
12823
|
command: "agent-prompt",
|
|
12564
|
-
describe: "Build a review agent's launch prompt from the plan (the diff path, its line ranges and the agent's own brief are welded in, not left to the caller to remember)",
|
|
12824
|
+
describe: "Build a review agent's launch prompt from the plan (the diff path, its line ranges and the agent's own brief are welded in, not left to the caller to remember). Exit codes: 0 built; 4 the review time budget refused another reverse-audit round (a termination rule, not an error \u2014 see the BUDGET line on stderr); anything else is a bad call or a broken plan.",
|
|
12565
12825
|
builder: /* @__PURE__ */ __name((yargs) => yargs.option("plan", {
|
|
12566
12826
|
type: "string",
|
|
12567
12827
|
demandOption: true,
|
|
@@ -12616,17 +12876,17 @@ init_esbuild_shims();
|
|
|
12616
12876
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
12617
12877
|
import {
|
|
12618
12878
|
existsSync as existsSync7,
|
|
12619
|
-
readFileSync as
|
|
12879
|
+
readFileSync as readFileSync20,
|
|
12620
12880
|
rmSync as rmSync5,
|
|
12621
12881
|
statfsSync,
|
|
12622
|
-
writeFileSync as
|
|
12882
|
+
writeFileSync as writeFileSync18
|
|
12623
12883
|
} from "node:fs";
|
|
12624
|
-
import { join as
|
|
12884
|
+
import { join as join15, resolve as resolve14 } from "node:path";
|
|
12625
12885
|
|
|
12626
12886
|
// packages/cli/src/commands/review/lib/workspaces.ts
|
|
12627
12887
|
init_esbuild_shims();
|
|
12628
|
-
import { existsSync as existsSync6, readFileSync as
|
|
12629
|
-
import { join as
|
|
12888
|
+
import { existsSync as existsSync6, readFileSync as readFileSync19, readdirSync as readdirSync4 } from "node:fs";
|
|
12889
|
+
import { join as join14 } from "node:path";
|
|
12630
12890
|
function isWorkspaceMember(filePath, workspaceGlobs) {
|
|
12631
12891
|
return workspaceDirFor(filePath, workspaceGlobs) !== null;
|
|
12632
12892
|
}
|
|
@@ -12664,7 +12924,7 @@ __name(hasUnmodeledWorkspaceGlob, "hasUnmodeledWorkspaceGlob");
|
|
|
12664
12924
|
function readWorkspaceGlobs(root) {
|
|
12665
12925
|
try {
|
|
12666
12926
|
const pkg = JSON.parse(
|
|
12667
|
-
|
|
12927
|
+
readFileSync19(join14(root, "package.json"), "utf8")
|
|
12668
12928
|
);
|
|
12669
12929
|
const ws = pkg.workspaces;
|
|
12670
12930
|
const globs = Array.isArray(ws) ? ws : Array.isArray(ws?.packages) ? ws.packages : [];
|
|
@@ -12677,7 +12937,7 @@ __name(readWorkspaceGlobs, "readWorkspaceGlobs");
|
|
|
12677
12937
|
function readRootPackage(root) {
|
|
12678
12938
|
let pkg;
|
|
12679
12939
|
try {
|
|
12680
|
-
pkg = JSON.parse(
|
|
12940
|
+
pkg = JSON.parse(readFileSync19(join14(root, "package.json"), "utf8"));
|
|
12681
12941
|
} catch {
|
|
12682
12942
|
return null;
|
|
12683
12943
|
}
|
|
@@ -12701,7 +12961,7 @@ function readWorkspacePackages(root) {
|
|
|
12701
12961
|
const base = g.slice(0, -2);
|
|
12702
12962
|
let entries;
|
|
12703
12963
|
try {
|
|
12704
|
-
entries = readdirSync4(
|
|
12964
|
+
entries = readdirSync4(join14(root, base), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
12705
12965
|
} catch {
|
|
12706
12966
|
continue;
|
|
12707
12967
|
}
|
|
@@ -12713,11 +12973,11 @@ function readWorkspacePackages(root) {
|
|
|
12713
12973
|
const pkgs = [];
|
|
12714
12974
|
for (const dir of dirs) {
|
|
12715
12975
|
if (workspaceDirFor(`${dir}/package.json`, globs) !== dir) continue;
|
|
12716
|
-
const manifest =
|
|
12976
|
+
const manifest = join14(root, dir, "package.json");
|
|
12717
12977
|
if (!existsSync6(manifest)) continue;
|
|
12718
12978
|
let pkg;
|
|
12719
12979
|
try {
|
|
12720
|
-
pkg = JSON.parse(
|
|
12980
|
+
pkg = JSON.parse(readFileSync19(manifest, "utf8"));
|
|
12721
12981
|
} catch {
|
|
12722
12982
|
continue;
|
|
12723
12983
|
}
|
|
@@ -12890,7 +13150,7 @@ __name(unresolvedWorkspaceDeps, "unresolvedWorkspaceDeps");
|
|
|
12890
13150
|
function changedFilesFrom(planPath) {
|
|
12891
13151
|
let parsed;
|
|
12892
13152
|
try {
|
|
12893
|
-
parsed = JSON.parse(
|
|
13153
|
+
parsed = JSON.parse(readFileSync20(planPath, "utf8"));
|
|
12894
13154
|
} catch (err) {
|
|
12895
13155
|
throw new Error(
|
|
12896
13156
|
`build-test: cannot read the plan ${planPath}: ${err.message}`
|
|
@@ -12973,15 +13233,15 @@ function runBuildTest(args) {
|
|
|
12973
13233
|
timedOut: [],
|
|
12974
13234
|
note: ""
|
|
12975
13235
|
};
|
|
12976
|
-
const npmLock = existsSync7(
|
|
12977
|
-
const installComplete = /* @__PURE__ */ __name(() => existsSync7(
|
|
12978
|
-
if (args.install && !npmLock && !existsSync7(
|
|
13236
|
+
const npmLock = existsSync7(join15(root, "package-lock.json"));
|
|
13237
|
+
const installComplete = /* @__PURE__ */ __name(() => existsSync7(join15(root, "node_modules", ".package-lock.json")), "installComplete");
|
|
13238
|
+
if (args.install && !npmLock && !existsSync7(join15(root, "node_modules"))) {
|
|
12979
13239
|
const altLock = [
|
|
12980
13240
|
["yarn.lock", "yarn install --frozen-lockfile"],
|
|
12981
13241
|
["pnpm-lock.yaml", "pnpm install --frozen-lockfile"],
|
|
12982
13242
|
["bun.lockb", "bun install --frozen-lockfile"],
|
|
12983
13243
|
["bun.lock", "bun install --frozen-lockfile"]
|
|
12984
|
-
].find(([f]) => existsSync7(
|
|
13244
|
+
].find(([f]) => existsSync7(join15(root, f)));
|
|
12985
13245
|
return unsupportedReport(
|
|
12986
13246
|
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."
|
|
12987
13247
|
);
|
|
@@ -12999,7 +13259,7 @@ function runBuildTest(args) {
|
|
|
12999
13259
|
if (install.timedOut) results.timedOut.push(install.command);
|
|
13000
13260
|
if (install.timedOut) {
|
|
13001
13261
|
try {
|
|
13002
|
-
rmSync5(
|
|
13262
|
+
rmSync5(join15(root, "node_modules"), {
|
|
13003
13263
|
recursive: true,
|
|
13004
13264
|
force: true,
|
|
13005
13265
|
maxRetries: 3
|
|
@@ -13122,7 +13382,7 @@ var buildTestCommand = {
|
|
|
13122
13382
|
try {
|
|
13123
13383
|
const report = runBuildTest(args);
|
|
13124
13384
|
if (args.out) {
|
|
13125
|
-
|
|
13385
|
+
writeFileSync18(args.out, JSON.stringify(report, null, 2));
|
|
13126
13386
|
}
|
|
13127
13387
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
13128
13388
|
} catch (err) {
|
|
@@ -13137,13 +13397,13 @@ init_esbuild_shims();
|
|
|
13137
13397
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
13138
13398
|
import {
|
|
13139
13399
|
existsSync as existsSync8,
|
|
13140
|
-
mkdirSync as
|
|
13141
|
-
readFileSync as
|
|
13400
|
+
mkdirSync as mkdirSync18,
|
|
13401
|
+
readFileSync as readFileSync21,
|
|
13142
13402
|
rmSync as rmSync7,
|
|
13143
|
-
statSync as
|
|
13144
|
-
writeFileSync as
|
|
13403
|
+
statSync as statSync7,
|
|
13404
|
+
writeFileSync as writeFileSync19
|
|
13145
13405
|
} from "node:fs";
|
|
13146
|
-
import { dirname as dirname15, join as
|
|
13406
|
+
import { dirname as dirname15, join as join16, resolve as resolve15 } from "node:path";
|
|
13147
13407
|
|
|
13148
13408
|
// packages/cli/src/commands/review/lib/worktree.ts
|
|
13149
13409
|
init_esbuild_shims();
|
|
@@ -13190,7 +13450,7 @@ function runBaseTree(args) {
|
|
|
13190
13450
|
}), "unavailable");
|
|
13191
13451
|
let plan;
|
|
13192
13452
|
try {
|
|
13193
|
-
plan = JSON.parse(
|
|
13453
|
+
plan = JSON.parse(readFileSync21(args.plan, "utf8"));
|
|
13194
13454
|
} catch (err) {
|
|
13195
13455
|
return unavailable(
|
|
13196
13456
|
`cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -13212,10 +13472,10 @@ function runBaseTree(args) {
|
|
|
13212
13472
|
return unavailable(`the review worktree ${worktree} does not exist`);
|
|
13213
13473
|
}
|
|
13214
13474
|
const tree = baseWorktreePath(worktree);
|
|
13215
|
-
const marker = /* @__PURE__ */ __name(() =>
|
|
13216
|
-
const failedMarker = /* @__PURE__ */ __name(() =>
|
|
13475
|
+
const marker = /* @__PURE__ */ __name(() => join16(tree, ".qwen-review-base-ok"), "marker");
|
|
13476
|
+
const failedMarker = /* @__PURE__ */ __name(() => join16(tree, ".qwen-review-base-failed"), "failedMarker");
|
|
13217
13477
|
try {
|
|
13218
|
-
if (existsSync8(tree) &&
|
|
13478
|
+
if (existsSync8(tree) && readFileSync21(marker(), "utf8").trim() === baseSha && gitOut(tree, "rev-parse", "HEAD") === baseSha) {
|
|
13219
13479
|
return {
|
|
13220
13480
|
available: true,
|
|
13221
13481
|
path: tree,
|
|
@@ -13227,7 +13487,7 @@ function runBaseTree(args) {
|
|
|
13227
13487
|
} catch {
|
|
13228
13488
|
}
|
|
13229
13489
|
try {
|
|
13230
|
-
if (existsSync8(tree) &&
|
|
13490
|
+
if (existsSync8(tree) && readFileSync21(failedMarker(), "utf8").trim() === baseSha) {
|
|
13231
13491
|
return {
|
|
13232
13492
|
available: false,
|
|
13233
13493
|
path: tree,
|
|
@@ -13240,14 +13500,14 @@ function runBaseTree(args) {
|
|
|
13240
13500
|
}
|
|
13241
13501
|
const lock = `${tree}.lock`;
|
|
13242
13502
|
try {
|
|
13243
|
-
const age = Date.now() -
|
|
13503
|
+
const age = Date.now() - statSync7(lock).mtimeMs;
|
|
13244
13504
|
if (age > 30 * 60 * 1e3) {
|
|
13245
13505
|
rmSync7(lock, { recursive: true, force: true });
|
|
13246
13506
|
}
|
|
13247
13507
|
} catch {
|
|
13248
13508
|
}
|
|
13249
13509
|
try {
|
|
13250
|
-
|
|
13510
|
+
mkdirSync18(lock);
|
|
13251
13511
|
} catch (err) {
|
|
13252
13512
|
if (err.code !== "EEXIST") {
|
|
13253
13513
|
return unavailable(
|
|
@@ -13285,7 +13545,7 @@ function runBaseTree(args) {
|
|
|
13285
13545
|
});
|
|
13286
13546
|
if (!build.ok || build.toolchain !== "npm" || build.build.length === 0) {
|
|
13287
13547
|
try {
|
|
13288
|
-
|
|
13548
|
+
writeFileSync19(failedMarker(), `${baseSha2}
|
|
13289
13549
|
`);
|
|
13290
13550
|
} catch {
|
|
13291
13551
|
}
|
|
@@ -13298,7 +13558,7 @@ function runBaseTree(args) {
|
|
|
13298
13558
|
};
|
|
13299
13559
|
}
|
|
13300
13560
|
try {
|
|
13301
|
-
|
|
13561
|
+
writeFileSync19(marker(), `${baseSha2}
|
|
13302
13562
|
`);
|
|
13303
13563
|
} catch {
|
|
13304
13564
|
}
|
|
@@ -13338,8 +13598,8 @@ var baseTreeCommand = {
|
|
|
13338
13598
|
try {
|
|
13339
13599
|
const report = runBaseTree(args);
|
|
13340
13600
|
if (args.out) {
|
|
13341
|
-
|
|
13342
|
-
|
|
13601
|
+
mkdirSync18(dirname15(resolve15(args.out)), { recursive: true });
|
|
13602
|
+
writeFileSync19(resolve15(args.out), JSON.stringify(report, null, 2));
|
|
13343
13603
|
}
|
|
13344
13604
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
13345
13605
|
writeStderrLine(`base-tree: ${report.note}`);
|
|
@@ -13353,7 +13613,7 @@ var baseTreeCommand = {
|
|
|
13353
13613
|
// packages/cli/src/commands/review/test-delta.ts
|
|
13354
13614
|
init_esbuild_shims();
|
|
13355
13615
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
13356
|
-
import { existsSync as existsSync9, mkdirSync as
|
|
13616
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync20 } from "node:fs";
|
|
13357
13617
|
import { dirname as dirname16, resolve as resolve16 } from "node:path";
|
|
13358
13618
|
var ANSI_SGR_RE2 = /\x1b\[[0-9;]*m/g;
|
|
13359
13619
|
var RERUNNABLE_COMMAND_RE = /^npm test(?: --workspace="[\w@./-]+")?$/;
|
|
@@ -13427,7 +13687,7 @@ function runTestDelta(args) {
|
|
|
13427
13687
|
}), "empty");
|
|
13428
13688
|
let report;
|
|
13429
13689
|
try {
|
|
13430
|
-
report = JSON.parse(
|
|
13690
|
+
report = JSON.parse(readFileSync22(args.report, "utf8"));
|
|
13431
13691
|
} catch (err) {
|
|
13432
13692
|
return empty(
|
|
13433
13693
|
`cannot read the build-test report ${args.report}: ${err.message}`
|
|
@@ -13569,8 +13829,8 @@ var testDeltaCommand = {
|
|
|
13569
13829
|
const args = argv;
|
|
13570
13830
|
const report = runTestDelta(args);
|
|
13571
13831
|
if (args.out) {
|
|
13572
|
-
|
|
13573
|
-
|
|
13832
|
+
mkdirSync19(dirname16(resolve16(args.out)), { recursive: true });
|
|
13833
|
+
writeFileSync20(resolve16(args.out), JSON.stringify(report, null, 2));
|
|
13574
13834
|
}
|
|
13575
13835
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
13576
13836
|
writeStderrLine(`test-delta: ${report.note}`);
|
|
@@ -13581,14 +13841,14 @@ var testDeltaCommand = {
|
|
|
13581
13841
|
init_esbuild_shims();
|
|
13582
13842
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
13583
13843
|
import {
|
|
13584
|
-
mkdirSync as
|
|
13585
|
-
writeFileSync as
|
|
13586
|
-
readFileSync as
|
|
13844
|
+
mkdirSync as mkdirSync20,
|
|
13845
|
+
writeFileSync as writeFileSync21,
|
|
13846
|
+
readFileSync as readFileSync23,
|
|
13587
13847
|
existsSync as existsSync10,
|
|
13588
13848
|
rmSync as rmSync8,
|
|
13589
|
-
statSync as
|
|
13849
|
+
statSync as statSync8
|
|
13590
13850
|
} from "node:fs";
|
|
13591
|
-
import { dirname as dirname17, join as
|
|
13851
|
+
import { dirname as dirname17, join as join17, resolve as resolve17 } from "node:path";
|
|
13592
13852
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
13593
13853
|
var SERVER_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
13594
13854
|
function shellQuote(v) {
|
|
@@ -13600,7 +13860,7 @@ var LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
|
13600
13860
|
var POLL_MS = 250;
|
|
13601
13861
|
function logBytes(p) {
|
|
13602
13862
|
try {
|
|
13603
|
-
return
|
|
13863
|
+
return statSync8(p).size;
|
|
13604
13864
|
} catch {
|
|
13605
13865
|
return 0;
|
|
13606
13866
|
}
|
|
@@ -13706,13 +13966,13 @@ function runDrive(args) {
|
|
|
13706
13966
|
waitMs(POLL_MS);
|
|
13707
13967
|
}
|
|
13708
13968
|
}
|
|
13709
|
-
const dir =
|
|
13710
|
-
|
|
13711
|
-
const scriptPath =
|
|
13712
|
-
const logPath = args.logPath ??
|
|
13713
|
-
const sentinelPath =
|
|
13969
|
+
const dir = join17(tmpdir2(), `qwen-review-drive-${server}`);
|
|
13970
|
+
mkdirSync20(dir, { recursive: true });
|
|
13971
|
+
const scriptPath = join17(dir, "drive.sh");
|
|
13972
|
+
const logPath = args.logPath ?? join17(dir, "drive.log");
|
|
13973
|
+
const sentinelPath = join17(dir, "drive.rc");
|
|
13714
13974
|
rmSync8(sentinelPath, { force: true });
|
|
13715
|
-
|
|
13975
|
+
writeFileSync21(scriptPath, wrapScript(args.script, sentinelPath), "utf8");
|
|
13716
13976
|
const droveFrom = Date.now();
|
|
13717
13977
|
let output = "";
|
|
13718
13978
|
let exitCode = null;
|
|
@@ -13742,8 +14002,8 @@ function runDrive(args) {
|
|
|
13742
14002
|
}
|
|
13743
14003
|
const deadline = droveFrom + args.timeout * 1e3;
|
|
13744
14004
|
for (; ; ) {
|
|
13745
|
-
output = existsSync10(logPath) ?
|
|
13746
|
-
exitCode = existsSync10(sentinelPath) ? sentinelExitCode(
|
|
14005
|
+
output = existsSync10(logPath) ? readFileSync23(logPath, "utf8") : "";
|
|
14006
|
+
exitCode = existsSync10(sentinelPath) ? sentinelExitCode(readFileSync23(sentinelPath, "utf8")) : null;
|
|
13747
14007
|
if (exitCode !== null) {
|
|
13748
14008
|
outcome = "completed";
|
|
13749
14009
|
break;
|
|
@@ -13810,8 +14070,8 @@ var driveCommand = {
|
|
|
13810
14070
|
const args = argv;
|
|
13811
14071
|
const report = runDrive(args);
|
|
13812
14072
|
if (args.out) {
|
|
13813
|
-
|
|
13814
|
-
|
|
14073
|
+
mkdirSync20(dirname17(resolve17(args.out)), { recursive: true });
|
|
14074
|
+
writeFileSync21(resolve17(args.out), JSON.stringify(report, null, 2));
|
|
13815
14075
|
}
|
|
13816
14076
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
13817
14077
|
writeStderrLine(`drive: ${report.note}`);
|
|
@@ -13828,7 +14088,7 @@ init_esbuild_shims();
|
|
|
13828
14088
|
import {
|
|
13829
14089
|
createServer
|
|
13830
14090
|
} from "node:http";
|
|
13831
|
-
import { appendFileSync, mkdirSync as
|
|
14091
|
+
import { appendFileSync, mkdirSync as mkdirSync21, writeFileSync as writeFileSync22 } from "node:fs";
|
|
13832
14092
|
import { dirname as dirname18, resolve as resolve18 } from "node:path";
|
|
13833
14093
|
import { pathToFileURL } from "node:url";
|
|
13834
14094
|
function messagesText(body) {
|
|
@@ -14085,8 +14345,8 @@ async function startMockProvider(args, respondOverride) {
|
|
|
14085
14345
|
respond = fn;
|
|
14086
14346
|
}
|
|
14087
14347
|
const logPath = resolve18(args.log);
|
|
14088
|
-
|
|
14089
|
-
|
|
14348
|
+
mkdirSync21(dirname18(logPath), { recursive: true });
|
|
14349
|
+
writeFileSync22(logPath, "");
|
|
14090
14350
|
let n = 0;
|
|
14091
14351
|
const record = /* @__PURE__ */ __name((entry) => appendFileSync(logPath, `${JSON.stringify(entry)}
|
|
14092
14352
|
`), "record");
|
|
@@ -14248,8 +14508,8 @@ var mockProviderCommand = {
|
|
|
14248
14508
|
const args = argv;
|
|
14249
14509
|
const { report, close } = await startMockProvider(args);
|
|
14250
14510
|
if (args.out) {
|
|
14251
|
-
|
|
14252
|
-
|
|
14511
|
+
mkdirSync21(dirname18(resolve18(args.out)), { recursive: true });
|
|
14512
|
+
writeFileSync22(resolve18(args.out), JSON.stringify(report, null, 2));
|
|
14253
14513
|
}
|
|
14254
14514
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
14255
14515
|
writeStderrLine(`mock-provider: ${report.note}`);
|
|
@@ -14267,7 +14527,7 @@ var mockProviderCommand = {
|
|
|
14267
14527
|
// packages/cli/src/commands/review/extract-step.ts
|
|
14268
14528
|
init_esbuild_shims();
|
|
14269
14529
|
var import_yaml = __toESM(require_dist(), 1);
|
|
14270
|
-
import { mkdirSync as
|
|
14530
|
+
import { mkdirSync as mkdirSync22, readFileSync as readFileSync24, writeFileSync as writeFileSync23, chmodSync } from "node:fs";
|
|
14271
14531
|
import { dirname as dirname19, resolve as resolve19 } from "node:path";
|
|
14272
14532
|
function expressionsOf(...texts) {
|
|
14273
14533
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14515,7 +14775,7 @@ function runExtractStep(args) {
|
|
|
14515
14775
|
const wfPath = resolve19(args.workflow);
|
|
14516
14776
|
let text;
|
|
14517
14777
|
try {
|
|
14518
|
-
text =
|
|
14778
|
+
text = readFileSync24(wfPath, "utf8");
|
|
14519
14779
|
} catch (err) {
|
|
14520
14780
|
throw new Error(
|
|
14521
14781
|
`extract-step: cannot read ${args.workflow}: ${err.message}`
|
|
@@ -14582,7 +14842,7 @@ function runExtractStep(args) {
|
|
|
14582
14842
|
const script = step.run;
|
|
14583
14843
|
const stepLabel = String(step.name ?? step.id ?? index);
|
|
14584
14844
|
const outPath = resolve19(args.out);
|
|
14585
|
-
|
|
14845
|
+
mkdirSync22(dirname19(outPath), { recursive: true });
|
|
14586
14846
|
const header = [
|
|
14587
14847
|
`#!/usr/bin/env ${shellCommand}`,
|
|
14588
14848
|
...commentLines(
|
|
@@ -14606,7 +14866,7 @@ function runExtractStep(args) {
|
|
|
14606
14866
|
),
|
|
14607
14867
|
""
|
|
14608
14868
|
].join("\n");
|
|
14609
|
-
|
|
14869
|
+
writeFileSync23(outPath, header + script + (script.endsWith("\n") ? "" : "\n"));
|
|
14610
14870
|
chmodSync(outPath, 493);
|
|
14611
14871
|
return {
|
|
14612
14872
|
workflow: args.workflow,
|
|
@@ -14667,7 +14927,7 @@ var extractStepCommand = {
|
|
|
14667
14927
|
|
|
14668
14928
|
// packages/cli/src/commands/review/submit.ts
|
|
14669
14929
|
init_esbuild_shims();
|
|
14670
|
-
import { mkdirSync as
|
|
14930
|
+
import { mkdirSync as mkdirSync23, readFileSync as readFileSync25 } from "node:fs";
|
|
14671
14931
|
|
|
14672
14932
|
// packages/cli/src/commands/review/lib/receipt.ts
|
|
14673
14933
|
init_esbuild_shims();
|
|
@@ -14689,7 +14949,7 @@ __name(parseReceiptIds, "parseReceiptIds");
|
|
|
14689
14949
|
var EVENTS = /* @__PURE__ */ new Set(["APPROVE", "REQUEST_CHANGES", "COMMENT"]);
|
|
14690
14950
|
function readReceiptIds(receiptPath) {
|
|
14691
14951
|
try {
|
|
14692
|
-
return parseReceiptIds(
|
|
14952
|
+
return parseReceiptIds(readFileSync25(receiptPath, "utf8"));
|
|
14693
14953
|
} catch {
|
|
14694
14954
|
return [];
|
|
14695
14955
|
}
|
|
@@ -14699,6 +14959,24 @@ function isDiffLine(n) {
|
|
|
14699
14959
|
return typeof n === "number" && Number.isSafeInteger(n) && n > 0;
|
|
14700
14960
|
}
|
|
14701
14961
|
__name(isDiffLine, "isDiffLine");
|
|
14962
|
+
function normalizeInlineComments(comments, modelId, cliVersion) {
|
|
14963
|
+
if (typeof modelId !== "string" || modelId.trim() === "") return comments;
|
|
14964
|
+
const footer = reviewFooter(modelId, cliVersion);
|
|
14965
|
+
return comments.map(
|
|
14966
|
+
(comment) => (
|
|
14967
|
+
// An empty body stays empty: this runs BEFORE the consistency check, and
|
|
14968
|
+
// a footer pasted onto '' would hide the emptiness from the refusal that
|
|
14969
|
+
// names it ('has no body — an empty comment').
|
|
14970
|
+
typeof comment.body === "string" && comment.body.trim() !== "" ? {
|
|
14971
|
+
...comment,
|
|
14972
|
+
body: `${comment.body.replace(REVIEW_FOOTER_RE, "")}
|
|
14973
|
+
|
|
14974
|
+
${footer}`
|
|
14975
|
+
} : comment
|
|
14976
|
+
)
|
|
14977
|
+
);
|
|
14978
|
+
}
|
|
14979
|
+
__name(normalizeInlineComments, "normalizeInlineComments");
|
|
14702
14980
|
function authorization(args) {
|
|
14703
14981
|
return reviewWriteAuthorization({
|
|
14704
14982
|
userAuthorized: args.userAuthorized,
|
|
@@ -14744,6 +15022,18 @@ __name(compose, "compose");
|
|
|
14744
15022
|
function structuralProblems(payload) {
|
|
14745
15023
|
const problems = [];
|
|
14746
15024
|
if (!payload.commit_id) problems.push("`commit_id` is missing");
|
|
15025
|
+
if (payload.comments !== void 0 && !Array.isArray(payload.comments)) {
|
|
15026
|
+
problems.push(
|
|
15027
|
+
"`comments` is not an array \u2014 it is the list of findings this post carries; any other shape is not a list of findings."
|
|
15028
|
+
);
|
|
15029
|
+
}
|
|
15030
|
+
if (Array.isArray(payload.comments) && payload.comments.some(
|
|
15031
|
+
(c) => c === null || typeof c !== "object"
|
|
15032
|
+
)) {
|
|
15033
|
+
problems.push(
|
|
15034
|
+
"`comments` entries must each be an object \u2014 a finding is a path, a line and a body; any other shape is not a finding."
|
|
15035
|
+
);
|
|
15036
|
+
}
|
|
14747
15037
|
if (payload.event !== void 0 || payload.body !== void 0) {
|
|
14748
15038
|
problems.push(
|
|
14749
15039
|
"the payload carries `event`/`body`. Those are computed here, from `state` and from the comments you attached \u2014 they are not inputs. Remove them. (A run that skipped `compose-review` and typed its own Approve is exactly what this refuses.)"
|
|
@@ -14762,12 +15052,12 @@ function structuralProblems(payload) {
|
|
|
14762
15052
|
return problems;
|
|
14763
15053
|
}
|
|
14764
15054
|
__name(structuralProblems, "structuralProblems");
|
|
14765
|
-
function inconsistencies(payload,
|
|
15055
|
+
function inconsistencies(payload, event2) {
|
|
14766
15056
|
const problems = [];
|
|
14767
15057
|
const comments = payload.comments ?? [];
|
|
14768
|
-
if (!EVENTS.has(
|
|
15058
|
+
if (!EVENTS.has(event2)) {
|
|
14769
15059
|
problems.push(
|
|
14770
|
-
`computed \`event\` is ${JSON.stringify(
|
|
15060
|
+
`computed \`event\` is ${JSON.stringify(event2)}; GitHub accepts only ${[...EVENTS].join(", ")}`
|
|
14771
15061
|
);
|
|
14772
15062
|
}
|
|
14773
15063
|
comments.forEach((c, i) => {
|
|
@@ -14824,7 +15114,7 @@ function runSubmit(args, cliVersion = "unknown") {
|
|
|
14824
15114
|
}
|
|
14825
15115
|
let payload;
|
|
14826
15116
|
try {
|
|
14827
|
-
payload = JSON.parse(
|
|
15117
|
+
payload = JSON.parse(readFileSync25(args.review, "utf8"));
|
|
14828
15118
|
} catch (err) {
|
|
14829
15119
|
throw new Error(
|
|
14830
15120
|
`Cannot read review JSON ${args.review}: ${err.message}`
|
|
@@ -14849,18 +15139,26 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
14849
15139
|
` + structural.map((p) => ` - ${p}`).join("\n")
|
|
14850
15140
|
);
|
|
14851
15141
|
}
|
|
14852
|
-
|
|
15142
|
+
payload = {
|
|
15143
|
+
...payload,
|
|
15144
|
+
comments: normalizeInlineComments(
|
|
15145
|
+
payload.comments ?? [],
|
|
15146
|
+
payload.state?.modelId,
|
|
15147
|
+
cliVersion
|
|
15148
|
+
)
|
|
15149
|
+
};
|
|
15150
|
+
let event2;
|
|
14853
15151
|
let body;
|
|
14854
15152
|
let cappedBy;
|
|
14855
15153
|
try {
|
|
14856
|
-
({ event, body, cappedBy } = compose(payload, cliVersion));
|
|
15154
|
+
({ event: event2, body, cappedBy } = compose(payload, cliVersion));
|
|
14857
15155
|
} catch (err) {
|
|
14858
15156
|
throw new Error(
|
|
14859
15157
|
`The review state does not compose into a verdict; refusing to post:
|
|
14860
15158
|
- ${err.message}`
|
|
14861
15159
|
);
|
|
14862
15160
|
}
|
|
14863
|
-
const problems = inconsistencies(payload,
|
|
15161
|
+
const problems = inconsistencies(payload, event2);
|
|
14864
15162
|
if (problems.length > 0) {
|
|
14865
15163
|
throw new Error(
|
|
14866
15164
|
`The review payload contradicts itself; refusing to post it:
|
|
@@ -14869,7 +15167,7 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
14869
15167
|
}
|
|
14870
15168
|
const post = {
|
|
14871
15169
|
commit_id: payload.commit_id,
|
|
14872
|
-
event,
|
|
15170
|
+
event: event2,
|
|
14873
15171
|
body,
|
|
14874
15172
|
comments: payload.comments ?? []
|
|
14875
15173
|
};
|
|
@@ -14880,7 +15178,7 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
14880
15178
|
);
|
|
14881
15179
|
writeStdoutLine(
|
|
14882
15180
|
JSON.stringify(
|
|
14883
|
-
{ posted: false, wouldPost: true, target, event, cappedBy },
|
|
15181
|
+
{ posted: false, wouldPost: true, target, event: event2, cappedBy },
|
|
14884
15182
|
null,
|
|
14885
15183
|
2
|
|
14886
15184
|
)
|
|
@@ -14900,23 +15198,23 @@ Posting is a public, irreversible write, and this run has no authorisation for o
|
|
|
14900
15198
|
const receiptPath = tmpFile(`pr-${args.pr}`, "submit-receipt.json");
|
|
14901
15199
|
const priorIds = readReceiptIds(receiptPath);
|
|
14902
15200
|
const reviewIds = [.../* @__PURE__ */ new Set([...priorIds, reviewId])];
|
|
14903
|
-
|
|
15201
|
+
mkdirSync23(REVIEW_TMP_DIR, { recursive: true });
|
|
14904
15202
|
atomicWriteFileSync(
|
|
14905
15203
|
receiptPath,
|
|
14906
|
-
`${JSON.stringify({ reviewIds, event, postedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
15204
|
+
`${JSON.stringify({ reviewIds, event: event2, postedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
14907
15205
|
`
|
|
14908
15206
|
);
|
|
14909
15207
|
}
|
|
14910
15208
|
} catch {
|
|
14911
15209
|
}
|
|
14912
15210
|
writeStderrLine(
|
|
14913
|
-
`Posted ${
|
|
15211
|
+
`Posted ${event2} to ${args.repo}#${args.pr} \u2014 ${auth.why}` + (cappedBy.length ? ` (capped by ${cappedBy.join(", ")})` : "") + "."
|
|
14914
15212
|
);
|
|
14915
15213
|
writeStdoutLine(
|
|
14916
15214
|
JSON.stringify(
|
|
14917
15215
|
{
|
|
14918
15216
|
posted: true,
|
|
14919
|
-
event,
|
|
15217
|
+
event: event2,
|
|
14920
15218
|
cappedBy,
|
|
14921
15219
|
inlineComments: post.comments.length
|
|
14922
15220
|
},
|
|
@@ -14957,7 +15255,8 @@ var submitCommand = {
|
|
|
14957
15255
|
describe: "Check authorisation and payload consistency, then stop."
|
|
14958
15256
|
}), "builder"),
|
|
14959
15257
|
handler: /* @__PURE__ */ __name(async (argv) => {
|
|
14960
|
-
|
|
15258
|
+
const cliVersion = footerVersion(process.env["QWEN_CODE_STARTUP_VERSION"]) ?? await getCliVersion();
|
|
15259
|
+
runSubmit(argv, cliVersion);
|
|
14961
15260
|
}, "handler")
|
|
14962
15261
|
};
|
|
14963
15262
|
|
|
@@ -14965,18 +15264,18 @@ var submitCommand = {
|
|
|
14965
15264
|
init_esbuild_shims();
|
|
14966
15265
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
14967
15266
|
import {
|
|
14968
|
-
mkdirSync as
|
|
15267
|
+
mkdirSync as mkdirSync24,
|
|
14969
15268
|
readdirSync as readdirSync5,
|
|
14970
|
-
writeFileSync as
|
|
14971
|
-
readFileSync as
|
|
15269
|
+
writeFileSync as writeFileSync24,
|
|
15270
|
+
readFileSync as readFileSync26,
|
|
14972
15271
|
rmSync as rmSync9,
|
|
14973
15272
|
lstatSync as lstatSync4,
|
|
14974
15273
|
existsSync as existsSync11,
|
|
14975
|
-
statSync as
|
|
15274
|
+
statSync as statSync9,
|
|
14976
15275
|
symlinkSync
|
|
14977
15276
|
} from "node:fs";
|
|
14978
15277
|
import { createRequire } from "node:module";
|
|
14979
|
-
import { dirname as dirname20, join as
|
|
15278
|
+
import { dirname as dirname20, join as join18, isAbsolute as isAbsolute3, sep as sep3 } from "node:path";
|
|
14980
15279
|
var FIXTURE_DIR_RE = /(^|\/)(__fixtures__|__mocks__|__snapshots__|fixtures)\//;
|
|
14981
15280
|
function planTestEfficacy(files, workspaceGlobs) {
|
|
14982
15281
|
const tests = files.filter((f) => f.kind === "test").map((f) => f.path);
|
|
@@ -15499,23 +15798,24 @@ function gitOut2(cwd, ...args) {
|
|
|
15499
15798
|
return (r.stdout ?? "").trim();
|
|
15500
15799
|
}
|
|
15501
15800
|
__name(gitOut2, "gitOut");
|
|
15502
|
-
function findVitestBin(worktree
|
|
15503
|
-
|
|
15801
|
+
function findVitestBin(worktree, resolveModule = createRequire(
|
|
15802
|
+
join18(worktree, "noop.js")
|
|
15803
|
+
).resolve) {
|
|
15504
15804
|
let pkgPath;
|
|
15505
15805
|
try {
|
|
15506
|
-
pkgPath =
|
|
15806
|
+
pkgPath = resolveModule("vitest/package.json");
|
|
15507
15807
|
} catch (error) {
|
|
15508
15808
|
if (error.code === "MODULE_NOT_FOUND") {
|
|
15509
15809
|
throw new Error(`vitest not found searching up from ${worktree}`);
|
|
15510
15810
|
}
|
|
15511
15811
|
throw error;
|
|
15512
15812
|
}
|
|
15513
|
-
const pkg = JSON.parse(
|
|
15813
|
+
const pkg = JSON.parse(readFileSync26(pkgPath, "utf8"));
|
|
15514
15814
|
const bin = pkg.bin?.vitest;
|
|
15515
15815
|
if (!bin) {
|
|
15516
15816
|
throw new Error(`vitest package at ${pkgPath} declares no "vitest" bin`);
|
|
15517
15817
|
}
|
|
15518
|
-
return
|
|
15818
|
+
return join18(dirname20(pkgPath), bin);
|
|
15519
15819
|
}
|
|
15520
15820
|
__name(findVitestBin, "findVitestBin");
|
|
15521
15821
|
function gitCapture(cwd, ...args) {
|
|
@@ -15541,7 +15841,7 @@ function safeRmWithin(worktree, relPath) {
|
|
|
15541
15841
|
const parts = relPath.split(/[/\\]+/).filter((s) => s && s !== ".");
|
|
15542
15842
|
let cur = worktree;
|
|
15543
15843
|
for (let i = 0; i < parts.length; i++) {
|
|
15544
|
-
cur =
|
|
15844
|
+
cur = join18(cur, parts[i]);
|
|
15545
15845
|
let st;
|
|
15546
15846
|
try {
|
|
15547
15847
|
st = lstatSync4(cur);
|
|
@@ -15566,15 +15866,15 @@ __name(probeCleanupFailureDetail, "probeCleanupFailureDetail");
|
|
|
15566
15866
|
function exposeDependencies(probeTree, dependencyRoot) {
|
|
15567
15867
|
const done = { linked: 0, failed: 0 };
|
|
15568
15868
|
if (probeTree === dependencyRoot) return done;
|
|
15569
|
-
const source =
|
|
15570
|
-
const target =
|
|
15869
|
+
const source = join18(dependencyRoot, "node_modules");
|
|
15870
|
+
const target = join18(probeTree, "node_modules");
|
|
15571
15871
|
if (!existsSync11(source) || existsSync11(target)) return done;
|
|
15572
|
-
|
|
15872
|
+
mkdirSync24(target);
|
|
15573
15873
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
15574
15874
|
for (const entry of readdirSync5(source, { withFileTypes: true })) {
|
|
15575
15875
|
if (entry.name === ".vite" || entry.name === ".vite-temp") continue;
|
|
15576
|
-
const sourceEntry =
|
|
15577
|
-
const targetEntry =
|
|
15876
|
+
const sourceEntry = join18(source, entry.name);
|
|
15877
|
+
const targetEntry = join18(target, entry.name);
|
|
15578
15878
|
let sourceStats;
|
|
15579
15879
|
try {
|
|
15580
15880
|
sourceStats = lstatSync4(sourceEntry);
|
|
@@ -15584,7 +15884,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
15584
15884
|
}
|
|
15585
15885
|
if (sourceStats.isSymbolicLink()) {
|
|
15586
15886
|
try {
|
|
15587
|
-
if (!
|
|
15887
|
+
if (!statSync9(sourceEntry).isDirectory()) continue;
|
|
15588
15888
|
} catch {
|
|
15589
15889
|
continue;
|
|
15590
15890
|
}
|
|
@@ -15594,7 +15894,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
15594
15894
|
if (entry.name.startsWith("@")) {
|
|
15595
15895
|
let pkgs;
|
|
15596
15896
|
try {
|
|
15597
|
-
|
|
15897
|
+
mkdirSync24(targetEntry);
|
|
15598
15898
|
pkgs = readdirSync5(sourceEntry);
|
|
15599
15899
|
} catch {
|
|
15600
15900
|
done.failed++;
|
|
@@ -15602,7 +15902,7 @@ function exposeDependencies(probeTree, dependencyRoot) {
|
|
|
15602
15902
|
}
|
|
15603
15903
|
for (const pkg of pkgs) {
|
|
15604
15904
|
try {
|
|
15605
|
-
symlinkSync(
|
|
15905
|
+
symlinkSync(join18(sourceEntry, pkg), join18(targetEntry, pkg), linkType);
|
|
15606
15906
|
done.linked++;
|
|
15607
15907
|
} catch {
|
|
15608
15908
|
done.failed++;
|
|
@@ -15748,10 +16048,10 @@ function newSideLength(header) {
|
|
|
15748
16048
|
__name(newSideLength, "newSideLength");
|
|
15749
16049
|
function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
15750
16050
|
const { patch: _patch, ...meta } = hunk;
|
|
15751
|
-
const abs =
|
|
16051
|
+
const abs = join18(probeTree, hunk.file);
|
|
15752
16052
|
let original;
|
|
15753
16053
|
try {
|
|
15754
|
-
original =
|
|
16054
|
+
original = readFileSync26(abs, "utf8");
|
|
15755
16055
|
} catch (e) {
|
|
15756
16056
|
return {
|
|
15757
16057
|
...meta,
|
|
@@ -15777,21 +16077,21 @@ function runOneHunkProbe(probeTree, hunk, probes, deadlineAt, now = Date.now) {
|
|
|
15777
16077
|
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";
|
|
15778
16078
|
return { ...meta, verdict, detail };
|
|
15779
16079
|
} finally {
|
|
15780
|
-
|
|
15781
|
-
|
|
16080
|
+
mkdirSync24(dirname20(abs), { recursive: true });
|
|
16081
|
+
writeFileSync24(abs, original, "utf8");
|
|
15782
16082
|
}
|
|
15783
16083
|
}
|
|
15784
16084
|
__name(runOneHunkProbe, "runOneHunkProbe");
|
|
15785
16085
|
function runControlMutant(probeTree, probeFile, deadlineAt, now = Date.now) {
|
|
15786
|
-
const abs =
|
|
16086
|
+
const abs = join18(probeTree, probeFile);
|
|
15787
16087
|
let original;
|
|
15788
16088
|
try {
|
|
15789
|
-
original =
|
|
16089
|
+
original = readFileSync26(abs, "utf8");
|
|
15790
16090
|
} catch {
|
|
15791
16091
|
return null;
|
|
15792
16092
|
}
|
|
15793
16093
|
try {
|
|
15794
|
-
|
|
16094
|
+
writeFileSync24(
|
|
15795
16095
|
abs,
|
|
15796
16096
|
`${original}
|
|
15797
16097
|
;import { it as __qcIt, expect as __qcExpect } from 'vitest';
|
|
@@ -15804,13 +16104,13 @@ __qcIt('QWEN-REVIEW-POSITIVE-CONTROL', () => {
|
|
|
15804
16104
|
const { perFile } = runProbeSuite(probeTree, [probeFile], deadlineAt, now);
|
|
15805
16105
|
return perFile.some((r) => r.verdict === "gated");
|
|
15806
16106
|
} finally {
|
|
15807
|
-
|
|
16107
|
+
writeFileSync24(abs, original, "utf8");
|
|
15808
16108
|
}
|
|
15809
16109
|
}
|
|
15810
16110
|
__name(runControlMutant, "runControlMutant");
|
|
15811
16111
|
function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
15812
|
-
const abs =
|
|
15813
|
-
const original =
|
|
16112
|
+
const abs = join18(probeTree, mutant.file);
|
|
16113
|
+
const original = readFileSync26(abs, "utf8");
|
|
15814
16114
|
const lines2 = original.split("\n");
|
|
15815
16115
|
if ((lines2[mutant.line - 1] ?? "").trim() !== mutant.statement) {
|
|
15816
16116
|
return {
|
|
@@ -15826,7 +16126,7 @@ function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dep
|
|
|
15826
16126
|
lines2.splice(mutant.line - 1, 1);
|
|
15827
16127
|
}
|
|
15828
16128
|
try {
|
|
15829
|
-
|
|
16129
|
+
writeFileSync24(abs, lines2.join("\n"), "utf8");
|
|
15830
16130
|
const { perFile } = runProbeSuite(
|
|
15831
16131
|
probeTree,
|
|
15832
16132
|
probes,
|
|
@@ -15838,7 +16138,7 @@ function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dep
|
|
|
15838
16138
|
const detail = verdict === "killed" ? `the suite went red with this statement ${what} \u2014 a test catches it` : verdict === "survived" ? `every affected test still PASSED with this statement ${what} \u2014 no test fails ${mutant.mutated === void 0 ? "when it is removed" : "when it changes"}` : "the mutated tree produced no clean verdict (likely a compile or import error) \u2014 not evidence either way";
|
|
15839
16139
|
return { ...mutant, verdict, detail };
|
|
15840
16140
|
} finally {
|
|
15841
|
-
|
|
16141
|
+
writeFileSync24(abs, original, "utf8");
|
|
15842
16142
|
}
|
|
15843
16143
|
}
|
|
15844
16144
|
__name(runOneMutant, "runOneMutant");
|
|
@@ -15877,9 +16177,9 @@ async function runTestEfficacy(args) {
|
|
|
15877
16177
|
const now = args.now ?? Date.now;
|
|
15878
16178
|
const startedAt = now();
|
|
15879
16179
|
const { report, worktree, base, out } = args;
|
|
15880
|
-
const plan = JSON.parse(
|
|
16180
|
+
const plan = JSON.parse(readFileSync26(report, "utf8"));
|
|
15881
16181
|
const rootPkg = JSON.parse(
|
|
15882
|
-
|
|
16182
|
+
readFileSync26(`${worktree}/package.json`, "utf8")
|
|
15883
16183
|
);
|
|
15884
16184
|
const globs = rootPkg.workspaces ?? [];
|
|
15885
16185
|
const { unreachable, probes, revert } = planTestEfficacy(
|
|
@@ -15887,8 +16187,8 @@ async function runTestEfficacy(args) {
|
|
|
15887
16187
|
globs
|
|
15888
16188
|
);
|
|
15889
16189
|
for (const p of revert) {
|
|
15890
|
-
const norm =
|
|
15891
|
-
const root =
|
|
16190
|
+
const norm = join18(worktree, p);
|
|
16191
|
+
const root = join18(worktree, ".");
|
|
15892
16192
|
if (isAbsolute3(p) || norm !== root && !norm.startsWith(root + sep3)) {
|
|
15893
16193
|
throw new Error(
|
|
15894
16194
|
`refusing to run: revert path escapes the worktree: ${JSON.stringify(p)}`
|
|
@@ -16259,8 +16559,8 @@ async function runTestEfficacy(args) {
|
|
|
16259
16559
|
findings,
|
|
16260
16560
|
cleanupFailure
|
|
16261
16561
|
};
|
|
16262
|
-
|
|
16263
|
-
|
|
16562
|
+
mkdirSync24(dirname20(out), { recursive: true });
|
|
16563
|
+
writeFileSync24(out, JSON.stringify(result, null, 2), "utf8");
|
|
16264
16564
|
writeStdoutLine(
|
|
16265
16565
|
`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))`
|
|
16266
16566
|
);
|
|
@@ -16337,8 +16637,8 @@ var testEfficacyCommand = {
|
|
|
16337
16637
|
|
|
16338
16638
|
// packages/cli/src/commands/review/test-plan.ts
|
|
16339
16639
|
init_esbuild_shims();
|
|
16340
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
16341
|
-
import { dirname as dirname21, join as
|
|
16640
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync25, readFileSync as readFileSync27, writeFileSync as writeFileSync25 } from "node:fs";
|
|
16641
|
+
import { dirname as dirname21, join as join19, normalize, resolve as resolve20 } from "node:path";
|
|
16342
16642
|
var PLAN_NAME_RE = /(test\s*plan|\btesting\b|how\s+(?:has\s+this|to)\s+(?:been\s+)?test(?:ed)?|测试计划|测试方案|测试步骤)/i;
|
|
16343
16643
|
var HEADING_LINE_RE = /^(#{1,6})(?:[ \t](.*))?$/;
|
|
16344
16644
|
var BOLD_LINE_RE = /^\*\*([^*\n]+)\*\*:?\s*$/;
|
|
@@ -16541,7 +16841,7 @@ function rulePath(text, worktree, changed) {
|
|
|
16541
16841
|
};
|
|
16542
16842
|
}
|
|
16543
16843
|
const ignored = isGitIgnored(worktree, path3);
|
|
16544
|
-
if (existsSync12(
|
|
16844
|
+
if (existsSync12(join19(worktree, path3))) {
|
|
16545
16845
|
return {
|
|
16546
16846
|
kind: "path",
|
|
16547
16847
|
text,
|
|
@@ -16612,7 +16912,7 @@ function ruleCommand(text, worktree, buildTest) {
|
|
|
16612
16912
|
let rootScripts = [];
|
|
16613
16913
|
try {
|
|
16614
16914
|
const rootPkg = JSON.parse(
|
|
16615
|
-
|
|
16915
|
+
readFileSync27(join19(worktree, "package.json"), "utf8")
|
|
16616
16916
|
);
|
|
16617
16917
|
rootScripts = Object.keys(rootPkg.scripts ?? {});
|
|
16618
16918
|
} catch {
|
|
@@ -16690,7 +16990,7 @@ __name(fetchPrBody, "fetchPrBody");
|
|
|
16690
16990
|
function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
16691
16991
|
let plan;
|
|
16692
16992
|
try {
|
|
16693
|
-
plan = JSON.parse(
|
|
16993
|
+
plan = JSON.parse(readFileSync27(args.plan, "utf8"));
|
|
16694
16994
|
} catch (err) {
|
|
16695
16995
|
throw new Error(
|
|
16696
16996
|
`test-plan: cannot read the plan ${args.plan}: ${err.message}`
|
|
@@ -16725,7 +17025,7 @@ function runTestPlan(args, fetchBody = fetchPrBody) {
|
|
|
16725
17025
|
if (args.buildTest) {
|
|
16726
17026
|
try {
|
|
16727
17027
|
buildTest = JSON.parse(
|
|
16728
|
-
|
|
17028
|
+
readFileSync27(args.buildTest, "utf8")
|
|
16729
17029
|
);
|
|
16730
17030
|
} catch {
|
|
16731
17031
|
buildTest = null;
|
|
@@ -16782,8 +17082,8 @@ var testPlanCommand = {
|
|
|
16782
17082
|
try {
|
|
16783
17083
|
const report = runTestPlan(args);
|
|
16784
17084
|
if (args.out) {
|
|
16785
|
-
|
|
16786
|
-
|
|
17085
|
+
mkdirSync25(dirname21(resolve20(args.out)), { recursive: true });
|
|
17086
|
+
writeFileSync25(resolve20(args.out), JSON.stringify(report, null, 2));
|
|
16787
17087
|
}
|
|
16788
17088
|
writeStdoutLine(JSON.stringify(report, null, 2));
|
|
16789
17089
|
writeStderrLine(`test-plan: ${report.note}`);
|
|
@@ -16797,8 +17097,8 @@ var testPlanCommand = {
|
|
|
16797
17097
|
// packages/cli/src/commands/review/cleanup.ts
|
|
16798
17098
|
init_esbuild_shims();
|
|
16799
17099
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
16800
|
-
import { existsSync as existsSync13, readFileSync as
|
|
16801
|
-
import { join as
|
|
17100
|
+
import { existsSync as existsSync13, readFileSync as readFileSync28, readdirSync as readdirSync6, rmSync as rmSync10 } from "node:fs";
|
|
17101
|
+
import { join as join20 } from "node:path";
|
|
16802
17102
|
var AUTOMATION_MARKER = "<!-- qwen-";
|
|
16803
17103
|
function isAutomationComment(body) {
|
|
16804
17104
|
return (body ?? "").trimStart().startsWith(AUTOMATION_MARKER);
|
|
@@ -16829,7 +17129,7 @@ var OWNER_REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
|
16829
17129
|
function readAuditWindow(target, expectedPrNumber) {
|
|
16830
17130
|
let raw;
|
|
16831
17131
|
try {
|
|
16832
|
-
raw =
|
|
17132
|
+
raw = readFileSync28(tmpFile(target, "fetch.json"), "utf8");
|
|
16833
17133
|
} catch (err) {
|
|
16834
17134
|
const code = err.code;
|
|
16835
17135
|
return code === "ENOENT" ? { skip: "no fetch report" } : {
|
|
@@ -16876,7 +17176,7 @@ function readSubmitReceipt(target) {
|
|
|
16876
17176
|
try {
|
|
16877
17177
|
return new Set(
|
|
16878
17178
|
parseReceiptIds(
|
|
16879
|
-
|
|
17179
|
+
readFileSync28(tmpFile(target, "submit-receipt.json"), "utf8")
|
|
16880
17180
|
)
|
|
16881
17181
|
);
|
|
16882
17182
|
} catch {
|
|
@@ -17011,7 +17311,7 @@ function runCleanup(target) {
|
|
|
17011
17311
|
}
|
|
17012
17312
|
for (const file of tmpEntries) {
|
|
17013
17313
|
if (!file.startsWith(prefix)) continue;
|
|
17014
|
-
const full =
|
|
17314
|
+
const full = join20(REVIEW_TMP_DIR, file);
|
|
17015
17315
|
try {
|
|
17016
17316
|
rmSync10(full, { recursive: true, force: true });
|
|
17017
17317
|
writeStdoutLine(`Removed temp file: ${full}`);
|
|
@@ -17045,8 +17345,8 @@ var cleanupCommand = {
|
|
|
17045
17345
|
// packages/cli/src/commands/review/run.ts
|
|
17046
17346
|
init_esbuild_shims();
|
|
17047
17347
|
import { spawn, execFileSync as execFileSync6 } from "node:child_process";
|
|
17048
|
-
import { readdirSync as readdirSync7, readFileSync as
|
|
17049
|
-
import { dirname as dirname22, join as
|
|
17348
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync29, realpathSync as realpathSync3, statSync as statSync10 } from "node:fs";
|
|
17349
|
+
import { dirname as dirname22, join as join21, resolve as resolve21 } from "node:path";
|
|
17050
17350
|
var COMPOSED_PATTERN = /^qwen-review-.*composed\.json$/;
|
|
17051
17351
|
var COMPOSED_POLL_MS = 250;
|
|
17052
17352
|
var SIGNAL_EXIT_CODES = {
|
|
@@ -17080,10 +17380,10 @@ function newestArtifactSince(dir, pattern, startMs) {
|
|
|
17080
17380
|
}
|
|
17081
17381
|
for (const name of names) {
|
|
17082
17382
|
if (!pattern.test(name)) continue;
|
|
17083
|
-
const path3 =
|
|
17383
|
+
const path3 = join21(dir, name);
|
|
17084
17384
|
let mtime;
|
|
17085
17385
|
try {
|
|
17086
|
-
mtime =
|
|
17386
|
+
mtime = statSync10(path3).mtimeMs;
|
|
17087
17387
|
} catch {
|
|
17088
17388
|
continue;
|
|
17089
17389
|
}
|
|
@@ -17093,15 +17393,15 @@ function newestArtifactSince(dir, pattern, startMs) {
|
|
|
17093
17393
|
return best ? best.path : null;
|
|
17094
17394
|
}
|
|
17095
17395
|
__name(newestArtifactSince, "newestArtifactSince");
|
|
17096
|
-
function exitCodeFor(completed,
|
|
17396
|
+
function exitCodeFor(completed, event2, failOn) {
|
|
17097
17397
|
if (!completed) return 1;
|
|
17098
|
-
if (failOn === "request-changes" &&
|
|
17398
|
+
if (failOn === "request-changes" && event2 === "REQUEST_CHANGES") return 3;
|
|
17099
17399
|
return 0;
|
|
17100
17400
|
}
|
|
17101
17401
|
__name(exitCodeFor, "exitCodeFor");
|
|
17102
17402
|
function readComposed(path3) {
|
|
17103
17403
|
try {
|
|
17104
|
-
const parsed = JSON.parse(
|
|
17404
|
+
const parsed = JSON.parse(readFileSync29(path3, "utf8"));
|
|
17105
17405
|
return typeof parsed.event === "string" ? parsed : null;
|
|
17106
17406
|
} catch {
|
|
17107
17407
|
return null;
|
|
@@ -17332,13 +17632,308 @@ var runCommand = {
|
|
|
17332
17632
|
}, "handler")
|
|
17333
17633
|
};
|
|
17334
17634
|
|
|
17635
|
+
// packages/cli/src/commands/review/save-artifact.ts
|
|
17636
|
+
init_esbuild_shims();
|
|
17637
|
+
import {
|
|
17638
|
+
existsSync as existsSync14,
|
|
17639
|
+
lstatSync as lstatSync5,
|
|
17640
|
+
mkdirSync as mkdirSync26,
|
|
17641
|
+
readFileSync as readFileSync30,
|
|
17642
|
+
statSync as statSync11
|
|
17643
|
+
} from "node:fs";
|
|
17644
|
+
import {
|
|
17645
|
+
dirname as dirname23,
|
|
17646
|
+
isAbsolute as isAbsolute4,
|
|
17647
|
+
join as join22,
|
|
17648
|
+
relative as relative3,
|
|
17649
|
+
resolve as resolve22,
|
|
17650
|
+
sep as sep4,
|
|
17651
|
+
toNamespacedPath
|
|
17652
|
+
} from "node:path";
|
|
17653
|
+
import { isDeepStrictEqual } from "node:util";
|
|
17654
|
+
function workspaceRoot() {
|
|
17655
|
+
return resolve22(process.env["QWEN_CODE_PROJECT_DIR"] ?? process.cwd());
|
|
17656
|
+
}
|
|
17657
|
+
__name(workspaceRoot, "workspaceRoot");
|
|
17658
|
+
function isWithin(parent, child) {
|
|
17659
|
+
const rel = relative3(parent, child);
|
|
17660
|
+
return rel === "" || !isAbsolute4(rel) && rel !== ".." && !rel.startsWith(`..${sep4}`);
|
|
17661
|
+
}
|
|
17662
|
+
__name(isWithin, "isWithin");
|
|
17663
|
+
function workspacePath(root, value, label2) {
|
|
17664
|
+
const absolute = resolve22(root, value);
|
|
17665
|
+
if (!isWithin(root, absolute)) {
|
|
17666
|
+
throw new Error(
|
|
17667
|
+
`${label2} must be inside the workspace: ${JSON.stringify(value)}.`
|
|
17668
|
+
);
|
|
17669
|
+
}
|
|
17670
|
+
return absolute;
|
|
17671
|
+
}
|
|
17672
|
+
__name(workspacePath, "workspacePath");
|
|
17673
|
+
function rejectSymlinkPath(root, path3, label2) {
|
|
17674
|
+
const rel = relative3(root, path3);
|
|
17675
|
+
let current = root;
|
|
17676
|
+
for (const segment of rel.split(sep4)) {
|
|
17677
|
+
current = join22(current, segment);
|
|
17678
|
+
if (existsSync14(current) && lstatSync5(current).isSymbolicLink()) {
|
|
17679
|
+
throw new Error(`${label2} must not traverse a symbolic link.`);
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
}
|
|
17683
|
+
__name(rejectSymlinkPath, "rejectSymlinkPath");
|
|
17684
|
+
function sameFile(left, right) {
|
|
17685
|
+
if (left === right) return true;
|
|
17686
|
+
if (!existsSync14(left) || !existsSync14(right)) return false;
|
|
17687
|
+
const leftStat = statSync11(left);
|
|
17688
|
+
const rightStat = statSync11(right);
|
|
17689
|
+
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
17690
|
+
}
|
|
17691
|
+
__name(sameFile, "sameFile");
|
|
17692
|
+
function readText(path3, label2) {
|
|
17693
|
+
try {
|
|
17694
|
+
return readFileSync30(path3, "utf8");
|
|
17695
|
+
} catch (error) {
|
|
17696
|
+
throw new Error(
|
|
17697
|
+
`Could not read the ${label2} file at ${JSON.stringify(path3)}: ${error instanceof Error ? error.message : String(error)}`
|
|
17698
|
+
);
|
|
17699
|
+
}
|
|
17700
|
+
}
|
|
17701
|
+
__name(readText, "readText");
|
|
17702
|
+
function readJson2(path3, label2) {
|
|
17703
|
+
const text = readText(path3, label2);
|
|
17704
|
+
try {
|
|
17705
|
+
return JSON.parse(text);
|
|
17706
|
+
} catch (error) {
|
|
17707
|
+
throw new Error(
|
|
17708
|
+
`The ${label2} file at ${JSON.stringify(path3)} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
17709
|
+
);
|
|
17710
|
+
}
|
|
17711
|
+
}
|
|
17712
|
+
__name(readJson2, "readJson");
|
|
17713
|
+
function object(value, label2) {
|
|
17714
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
17715
|
+
throw new Error(`${label2} must be an object.`);
|
|
17716
|
+
}
|
|
17717
|
+
return value;
|
|
17718
|
+
}
|
|
17719
|
+
__name(object, "object");
|
|
17720
|
+
function string(value, label2) {
|
|
17721
|
+
if (typeof value !== "string") {
|
|
17722
|
+
throw new Error(`${label2} must be a string.`);
|
|
17723
|
+
}
|
|
17724
|
+
return value;
|
|
17725
|
+
}
|
|
17726
|
+
__name(string, "string");
|
|
17727
|
+
function nonEmptyString(value, label2) {
|
|
17728
|
+
const text = string(value, label2);
|
|
17729
|
+
if (text.trim() === "") {
|
|
17730
|
+
throw new Error(`${label2} must be a non-empty string.`);
|
|
17731
|
+
}
|
|
17732
|
+
return text;
|
|
17733
|
+
}
|
|
17734
|
+
__name(nonEmptyString, "nonEmptyString");
|
|
17735
|
+
function stringArray2(value, label2) {
|
|
17736
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
17737
|
+
throw new Error(`${label2} must be an array of strings.`);
|
|
17738
|
+
}
|
|
17739
|
+
return value;
|
|
17740
|
+
}
|
|
17741
|
+
__name(stringArray2, "stringArray");
|
|
17742
|
+
function event(value, label2) {
|
|
17743
|
+
if (value !== "APPROVE" && value !== "COMMENT" && value !== "REQUEST_CHANGES") {
|
|
17744
|
+
throw new Error(`${label2} has an unsupported value.`);
|
|
17745
|
+
}
|
|
17746
|
+
return value;
|
|
17747
|
+
}
|
|
17748
|
+
__name(event, "event");
|
|
17749
|
+
function validateVerdict(value) {
|
|
17750
|
+
const verdict = object(value, "Composed verdict");
|
|
17751
|
+
const downgradedFrom = verdict["downgradedFrom"];
|
|
17752
|
+
if (downgradedFrom !== null && downgradedFrom !== "Approve" && downgradedFrom !== "Request changes") {
|
|
17753
|
+
throw new Error(
|
|
17754
|
+
"Composed verdict.downgradedFrom has an unsupported value."
|
|
17755
|
+
);
|
|
17756
|
+
}
|
|
17757
|
+
if (typeof verdict["downgraded"] !== "boolean") {
|
|
17758
|
+
throw new Error("Composed verdict.downgraded must be a boolean.");
|
|
17759
|
+
}
|
|
17760
|
+
const lowSignal = verdict["lowSignal"];
|
|
17761
|
+
if (lowSignal !== null) {
|
|
17762
|
+
const signal = object(lowSignal, "Composed verdict.lowSignal");
|
|
17763
|
+
for (const key of ["agents", "srcDiffLines"]) {
|
|
17764
|
+
if (typeof signal[key] !== "number" || !Number.isInteger(signal[key]) || signal[key] < 0) {
|
|
17765
|
+
throw new Error(
|
|
17766
|
+
`Composed verdict.lowSignal.${key} must be a non-negative integer.`
|
|
17767
|
+
);
|
|
17768
|
+
}
|
|
17769
|
+
}
|
|
17770
|
+
}
|
|
17771
|
+
return {
|
|
17772
|
+
event: event(verdict["event"], "Composed verdict.event"),
|
|
17773
|
+
body: string(verdict["body"], "Composed verdict.body"),
|
|
17774
|
+
baseEvent: event(verdict["baseEvent"], "Composed verdict.baseEvent"),
|
|
17775
|
+
cappedBy: stringArray2(verdict["cappedBy"], "Composed verdict.cappedBy"),
|
|
17776
|
+
downgraded: verdict["downgraded"],
|
|
17777
|
+
downgradedFrom,
|
|
17778
|
+
remediation: stringArray2(
|
|
17779
|
+
verdict["remediation"],
|
|
17780
|
+
"Composed verdict.remediation"
|
|
17781
|
+
),
|
|
17782
|
+
lowSignal: lowSignal === null ? null : {
|
|
17783
|
+
agents: lowSignal["agents"],
|
|
17784
|
+
srcDiffLines: lowSignal["srcDiffLines"]
|
|
17785
|
+
},
|
|
17786
|
+
verdictLine: nonEmptyString(
|
|
17787
|
+
verdict["verdictLine"],
|
|
17788
|
+
"Composed verdict.verdictLine"
|
|
17789
|
+
)
|
|
17790
|
+
};
|
|
17791
|
+
}
|
|
17792
|
+
__name(validateVerdict, "validateVerdict");
|
|
17793
|
+
function validateFindingsReport(value) {
|
|
17794
|
+
const report = object(value, "Canonical findings report");
|
|
17795
|
+
if (typeof report["outcomesRecorded"] !== "boolean") {
|
|
17796
|
+
throw new Error(
|
|
17797
|
+
"Canonical findings report.outcomesRecorded must be a boolean."
|
|
17798
|
+
);
|
|
17799
|
+
}
|
|
17800
|
+
const canonical = buildReport(validateFindings(report["findings"]));
|
|
17801
|
+
const supplied = {
|
|
17802
|
+
findings: report["findings"],
|
|
17803
|
+
counts: report["counts"],
|
|
17804
|
+
outcomesRecorded: report["outcomesRecorded"]
|
|
17805
|
+
};
|
|
17806
|
+
if (!isDeepStrictEqual(supplied, canonical)) {
|
|
17807
|
+
throw new Error(
|
|
17808
|
+
"Canonical findings report is malformed or inconsistent with its findings."
|
|
17809
|
+
);
|
|
17810
|
+
}
|
|
17811
|
+
return supplied;
|
|
17812
|
+
}
|
|
17813
|
+
__name(validateFindingsReport, "validateFindingsReport");
|
|
17814
|
+
function saveReviewArtifact(args) {
|
|
17815
|
+
const root = workspaceRoot();
|
|
17816
|
+
const findingsPath = workspacePath(root, args.findings, "Findings input");
|
|
17817
|
+
const composedPath = workspacePath(root, args.composed, "Composed input");
|
|
17818
|
+
const reportPath = workspacePath(root, args.report, "Markdown report");
|
|
17819
|
+
const outputPath = workspacePath(root, args.out, "Output");
|
|
17820
|
+
const reviewsRoot = resolve22(root, REVIEWS_DIR);
|
|
17821
|
+
if (!isWithin(reviewsRoot, reportPath) || reportPath === reviewsRoot) {
|
|
17822
|
+
throw new Error(
|
|
17823
|
+
`Markdown report must be a file under ${JSON.stringify(REVIEWS_DIR)}: ${JSON.stringify(args.report)}.`
|
|
17824
|
+
);
|
|
17825
|
+
}
|
|
17826
|
+
if (!isWithin(reviewsRoot, outputPath) || outputPath === reviewsRoot) {
|
|
17827
|
+
throw new Error(
|
|
17828
|
+
`Output must be a file under ${JSON.stringify(REVIEWS_DIR)}: ${JSON.stringify(args.out)}.`
|
|
17829
|
+
);
|
|
17830
|
+
}
|
|
17831
|
+
for (const [label2, inputPath] of [
|
|
17832
|
+
["findings input", findingsPath],
|
|
17833
|
+
["composed input", composedPath],
|
|
17834
|
+
["Markdown report", reportPath]
|
|
17835
|
+
]) {
|
|
17836
|
+
if (sameFile(outputPath, inputPath)) {
|
|
17837
|
+
throw new Error(`Output must not overwrite the ${label2}.`);
|
|
17838
|
+
}
|
|
17839
|
+
}
|
|
17840
|
+
rejectSymlinkPath(root, findingsPath, "Findings input");
|
|
17841
|
+
rejectSymlinkPath(root, composedPath, "Composed input");
|
|
17842
|
+
rejectSymlinkPath(root, reportPath, "Markdown report");
|
|
17843
|
+
rejectSymlinkPath(root, outputPath, "Output");
|
|
17844
|
+
if (!EFFORT_LEVELS.has(args.effort)) {
|
|
17845
|
+
throw new Error(
|
|
17846
|
+
`Unsupported review effort: ${JSON.stringify(args.effort)}.`
|
|
17847
|
+
);
|
|
17848
|
+
}
|
|
17849
|
+
if (args.effort === "low") {
|
|
17850
|
+
throw new Error(
|
|
17851
|
+
"save-artifact does not support low-effort reviews: low has no canonical composed verdict to persist."
|
|
17852
|
+
);
|
|
17853
|
+
}
|
|
17854
|
+
nonEmptyString(args.target, "Target");
|
|
17855
|
+
const findings = validateFindingsReport(
|
|
17856
|
+
readJson2(findingsPath, "canonical findings")
|
|
17857
|
+
);
|
|
17858
|
+
const verdict = validateVerdict(readJson2(composedPath, "composed verdict"));
|
|
17859
|
+
let reportIsFile;
|
|
17860
|
+
try {
|
|
17861
|
+
reportIsFile = statSync11(reportPath).isFile();
|
|
17862
|
+
} catch {
|
|
17863
|
+
}
|
|
17864
|
+
if (reportIsFile === false) {
|
|
17865
|
+
throw new Error(
|
|
17866
|
+
`Markdown report is not a file: ${JSON.stringify(args.report)}.`
|
|
17867
|
+
);
|
|
17868
|
+
}
|
|
17869
|
+
readText(reportPath, "Markdown report");
|
|
17870
|
+
const markdownReportPath = relative3(root, reportPath).split(sep4).join("/");
|
|
17871
|
+
const document = {
|
|
17872
|
+
schemaVersion: 1,
|
|
17873
|
+
target: args.target,
|
|
17874
|
+
effort: args.effort,
|
|
17875
|
+
verdict,
|
|
17876
|
+
findings: findings.findings,
|
|
17877
|
+
counts: findings.counts,
|
|
17878
|
+
outcomesRecorded: findings.outcomesRecorded,
|
|
17879
|
+
markdownReportPath
|
|
17880
|
+
};
|
|
17881
|
+
mkdirSync26(dirname23(outputPath), { recursive: true });
|
|
17882
|
+
atomicWriteFileSync(
|
|
17883
|
+
toNamespacedPath(outputPath),
|
|
17884
|
+
`${JSON.stringify(document, null, 2)}
|
|
17885
|
+
`,
|
|
17886
|
+
{ encoding: "utf8", noFollow: true }
|
|
17887
|
+
);
|
|
17888
|
+
return {
|
|
17889
|
+
path: outputPath,
|
|
17890
|
+
workspacePath: relative3(root, outputPath).split(sep4).join("/")
|
|
17891
|
+
};
|
|
17892
|
+
}
|
|
17893
|
+
__name(saveReviewArtifact, "saveReviewArtifact");
|
|
17894
|
+
var saveArtifactCommand = {
|
|
17895
|
+
command: "save-artifact",
|
|
17896
|
+
describe: "Create a durable versioned code-review JSON document from canonical review artifacts",
|
|
17897
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.option("findings", {
|
|
17898
|
+
type: "string",
|
|
17899
|
+
demandOption: true,
|
|
17900
|
+
describe: "Canonical findings JSON"
|
|
17901
|
+
}).option("composed", {
|
|
17902
|
+
type: "string",
|
|
17903
|
+
demandOption: true,
|
|
17904
|
+
describe: "Composed verdict JSON"
|
|
17905
|
+
}).option("report", {
|
|
17906
|
+
type: "string",
|
|
17907
|
+
demandOption: true,
|
|
17908
|
+
describe: "Existing durable Markdown report"
|
|
17909
|
+
}).option("target", {
|
|
17910
|
+
type: "string",
|
|
17911
|
+
demandOption: true,
|
|
17912
|
+
describe: "Review target label"
|
|
17913
|
+
}).option("effort", {
|
|
17914
|
+
type: "string",
|
|
17915
|
+
choices: [...EFFORT_LEVELS].filter((effort) => effort !== "low"),
|
|
17916
|
+
demandOption: true,
|
|
17917
|
+
describe: "Resolved review effort"
|
|
17918
|
+
}).option("out", {
|
|
17919
|
+
type: "string",
|
|
17920
|
+
demandOption: true,
|
|
17921
|
+
describe: "Output path under .qwen/reviews/"
|
|
17922
|
+
}), "builder"),
|
|
17923
|
+
handler: /* @__PURE__ */ __name((argv) => {
|
|
17924
|
+
const saved = saveReviewArtifact(argv);
|
|
17925
|
+
writeStdoutLine(JSON.stringify(saved));
|
|
17926
|
+
writeStderrLine(`save-artifact: wrote ${saved.path}`);
|
|
17927
|
+
}, "handler")
|
|
17928
|
+
};
|
|
17929
|
+
|
|
17335
17930
|
// packages/cli/src/commands/review.ts
|
|
17336
17931
|
var reviewCommand = {
|
|
17337
17932
|
command: "review",
|
|
17338
17933
|
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)",
|
|
17339
|
-
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
17934
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(saveArtifactCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
17340
17935
|
1,
|
|
17341
|
-
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, submit, or cleanup."
|
|
17936
|
+
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, save-artifact, submit, or cleanup."
|
|
17342
17937
|
).version(false), "builder"),
|
|
17343
17938
|
handler: /* @__PURE__ */ __name(() => {
|
|
17344
17939
|
}, "handler")
|
|
@@ -17538,10 +18133,10 @@ var updateCommand3 = {
|
|
|
17538
18133
|
stdioHelpers,
|
|
17539
18134
|
{ updateEventEmitter }
|
|
17540
18135
|
] = await Promise.all([
|
|
17541
|
-
import("./settings-
|
|
17542
|
-
import("./updateCheck-
|
|
17543
|
-
import("./installationInfo-
|
|
17544
|
-
import("./standalone-update-
|
|
18136
|
+
import("./settings-KWYWA3BS.js"),
|
|
18137
|
+
import("./updateCheck-EE2XXQNJ.js"),
|
|
18138
|
+
import("./installationInfo-CZVCKPPZ.js"),
|
|
18139
|
+
import("./standalone-update-WNXRFLEA.js"),
|
|
17545
18140
|
import("./stdioHelpers-HGIYTWAY.js"),
|
|
17546
18141
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
17547
18142
|
]);
|
|
@@ -18387,7 +18982,7 @@ var SessionIdConflictError = class extends Error {
|
|
|
18387
18982
|
this.sessionId = sessionId;
|
|
18388
18983
|
}
|
|
18389
18984
|
};
|
|
18390
|
-
async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtensions, hooksConfig, disabledSkillNamesProvider, sessionMcpServers, settingsWatcher, throwOnSessionIdConflict = false) {
|
|
18985
|
+
async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtensions, hooksConfig, disabledSkillNamesProvider, sessionMcpServers, settingsWatcher, throwOnSessionIdConflict = false, hostPolicy) {
|
|
18391
18986
|
const debugMode = isDebugMode(argv);
|
|
18392
18987
|
if (debugMode && process.env["QWEN_DEBUG_LOG_FILE"] === void 0) {
|
|
18393
18988
|
process.env["QWEN_DEBUG_LOG_FILE"] = "1";
|
|
@@ -18708,7 +19303,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
18708
19303
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
18709
19304
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
18710
19305
|
terminalImageRenderSupportProvider: interactive ? async () => {
|
|
18711
|
-
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-
|
|
19306
|
+
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-TCEAHDFE.js");
|
|
18712
19307
|
return getTerminalImageRenderSupport();
|
|
18713
19308
|
} : void 0,
|
|
18714
19309
|
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|
|
@@ -18725,6 +19320,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
18725
19320
|
deny: mergedDeny.length > 0 ? mergedDeny : void 0,
|
|
18726
19321
|
autoMode: bareMode || safeMode ? void 0 : settings.permissions?.autoMode
|
|
18727
19322
|
},
|
|
19323
|
+
toolInvocationGuard: hostPolicy?.toolInvocationGuard,
|
|
18728
19324
|
// Permission rule persistence callback (writes to settings files).
|
|
18729
19325
|
onPersistPermissionRule: /* @__PURE__ */ __name(async (scope, ruleType, rule) => {
|
|
18730
19326
|
const currentSettings = loadSettings(cwd);
|
|
@@ -18984,11 +19580,11 @@ var ExtensionRefreshState = class {
|
|
|
18984
19580
|
contentChangedDuringReload = false;
|
|
18985
19581
|
suppressionDepth = 0;
|
|
18986
19582
|
suppressUntil = 0;
|
|
18987
|
-
on(
|
|
18988
|
-
this.events.on(
|
|
19583
|
+
on(event2, listener) {
|
|
19584
|
+
this.events.on(event2, listener);
|
|
18989
19585
|
}
|
|
18990
|
-
off(
|
|
18991
|
-
this.events.off(
|
|
19586
|
+
off(event2, listener) {
|
|
19587
|
+
this.events.off(event2, listener);
|
|
18992
19588
|
}
|
|
18993
19589
|
markExtensionsChanged(reason) {
|
|
18994
19590
|
if (this.isSuppressed()) {
|