@qwen-code/qwen-code 0.21.7-nightly.20260808.4ec0371e6 → 0.21.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bundled/qc-helper/docs/configuration/settings.md +12 -8
- package/bundled/qc-helper/docs/features/commands.md +1 -1
- package/bundled/qc-helper/docs/features/hooks.md +50 -0
- package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
- package/bundled/qc-helper/docs/qwen-serve.md +1 -1
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
- package/bundled/review/SKILL.md +24 -5
- package/chunks/{MaxSizedBox-COZBVNCI.js → MaxSizedBox-7PM6BGJ5.js} +13 -10
- package/chunks/{StandaloneSessionPicker-3OF2FS6S.js → StandaloneSessionPicker-3UQHM7GV.js} +29 -26
- package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
- package/chunks/{acpAgent-3JCJ6KWG.js → acpAgent-5UWLFV6V.js} +369 -148
- package/chunks/{agent-DBSC47CD.js → agent-624T2BLO.js} +13 -10
- package/chunks/{agent-headless-ZJHZ7I3S.js → agent-headless-2EE5J2KX.js} +13 -10
- package/chunks/{bridge-NFBYT4ZI.js → bridge-JENKGFFP.js} +15 -12
- package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
- package/chunks/{channel-management-service-LXSJXQGM.js → channel-management-service-DDWUPHMU.js} +1 -1
- package/chunks/{channel-settings-store-LABKDKSI.js → channel-settings-store-SA6JZSPH.js} +21 -18
- package/chunks/{channel-worker-group-MTW2AGT3.js → channel-worker-group-E67EN3RV.js} +2 -2
- package/chunks/{channel-worker-manager-UU6PTQSI.js → channel-worker-manager-SW4C45CF.js} +2 -2
- package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
- package/chunks/{chunk-HKCYGZZ4.js → chunk-2ILAOM2I.js} +30 -13
- package/chunks/{chunk-LDY4J4G6.js → chunk-2M4K4KYS.js} +176 -119
- package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
- package/chunks/{chunk-XCG76UE6.js → chunk-3PY4LPJF.js} +17 -129
- package/chunks/{chunk-26ISE5EG.js → chunk-3SE7J4DR.js} +3 -3
- package/chunks/{chunk-APMRLB2H.js → chunk-3WNQOYHQ.js} +12 -12
- package/chunks/{chunk-O7VQ3F22.js → chunk-4ALIARFY.js} +1 -1
- package/chunks/{chunk-FJ6YHWHZ.js → chunk-4DU3NCHG.js} +47 -54
- package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
- package/chunks/{chunk-3HS6Y4UA.js → chunk-4WU6NY7F.js} +2 -2
- package/chunks/{chunk-JRIJOZXO.js → chunk-5ZGR6RKJ.js} +3 -3
- package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
- package/chunks/{chunk-ZQGHESAS.js → chunk-6TR7CFXH.js} +1 -1
- package/chunks/{chunk-EZ53KMUN.js → chunk-757GB46F.js} +1 -1
- package/chunks/{chunk-5YT3Y33M.js → chunk-77QVBFCU.js} +3 -3
- package/chunks/{chunk-5PGKKSO6.js → chunk-7DVT4LVV.js} +35 -28
- package/chunks/{chunk-IMK3SJ43.js → chunk-7VUERJHS.js} +1066 -597
- package/chunks/{chunk-KPMB4JEZ.js → chunk-B52AWKBB.js} +64 -20
- package/chunks/{chunk-R2KZWK5Z.js → chunk-BF224XHL.js} +2 -2
- package/chunks/{chunk-TSYIQDG7.js → chunk-BF52U4XJ.js} +1 -1
- package/chunks/{chunk-LDUGDB5H.js → chunk-C5VWPTGT.js} +1 -1
- package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
- package/chunks/chunk-COBO5EBO.js +135 -0
- package/chunks/{chunk-ACHMWGC5.js → chunk-DQSDACD2.js} +1 -1
- package/chunks/{chunk-VT3VNFVW.js → chunk-DX5W5AON.js} +2 -2
- package/chunks/{chunk-JACAHYEN.js → chunk-E4ZBKMSF.js} +4 -4
- package/chunks/{chunk-MV7VUCIG.js → chunk-EIVICVHM.js} +4 -4
- package/chunks/{chunk-YHEEE624.js → chunk-EN2TKTFH.js} +1 -1
- package/chunks/chunk-F6WFNA7U.js +22 -0
- package/chunks/{chunk-Z6W3XDLN.js → chunk-FN6YXJOP.js} +1 -1
- package/chunks/{chunk-BJKFFPX2.js → chunk-FWBXMANW.js} +3 -3
- package/chunks/{chunk-764F335K.js → chunk-FYAXKJK7.js} +314 -63
- package/chunks/{chunk-XIDHBXUI.js → chunk-GBDINRIL.js} +3 -3
- package/chunks/{chunk-Z5ZAWED3.js → chunk-GOEVOFQI.js} +3 -3
- package/chunks/{chunk-ZKUJ4AO7.js → chunk-GQCEQPYQ.js} +3 -3
- package/chunks/{chunk-BFSQBXHV.js → chunk-GXSNGY5M.js} +399 -534
- package/chunks/{chunk-3ARO4N5G.js → chunk-HA3SAB64.js} +22 -69
- package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
- package/chunks/{chunk-LMEIS6WW.js → chunk-HWX5HPUG.js} +3 -3
- package/chunks/{chunk-VLFX3L3X.js → chunk-IBYULW65.js} +6 -6
- package/chunks/{chunk-SDUDZNF4.js → chunk-IUQ52YJK.js} +1 -1
- package/chunks/{chunk-H2352CX2.js → chunk-IYES5WOT.js} +2 -2
- package/chunks/{chunk-CE5UCTKO.js → chunk-KAQCJO6Y.js} +1 -1
- package/chunks/{chunk-DPH3MUAP.js → chunk-KKDVZLGL.js} +1 -1
- package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
- package/chunks/{chunk-P7HUJDBZ.js → chunk-M3STHEMM.js} +11 -16
- package/chunks/{chunk-VDS2WYM5.js → chunk-NGYI5EF5.js} +2 -2
- package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
- package/chunks/{chunk-GUFY6D3E.js → chunk-NPUXXRJI.js} +1 -1
- package/chunks/{chunk-4Q6N3SNL.js → chunk-NVRDQFCX.js} +1 -1
- package/chunks/{chunk-77WOUGCA.js → chunk-OHKJVAKG.js} +7 -7
- package/chunks/{chunk-TAOSTUHI.js → chunk-PG62DFWD.js} +10 -10
- package/chunks/{chunk-REHWPCG2.js → chunk-PLFATELK.js} +1 -1
- package/chunks/{chunk-APNNM3JC.js → chunk-QGHSP65Z.js} +2 -2
- package/chunks/{chunk-HY2INPTA.js → chunk-QQWD7LZV.js} +4 -4
- package/chunks/{chunk-P74TZRXD.js → chunk-QXVSWG66.js} +1 -1
- package/chunks/{chunk-TX3KSSDN.js → chunk-S3Y3GBFD.js} +1 -1
- package/chunks/{chunk-B23P3YWE.js → chunk-SNRT2TJJ.js} +6 -23
- package/chunks/chunk-SR7RZ4MS.js +202 -0
- package/chunks/{chunk-F3LPXDJP.js → chunk-TE3ZAJE7.js} +13 -3
- package/chunks/{chunk-AB4A73VL.js → chunk-TKSZJ5BV.js} +1 -1
- package/chunks/{chunk-RZMGG3HP.js → chunk-U5SLIG7E.js} +1 -1
- package/chunks/chunk-UA5H3DS2.js +203 -0
- package/chunks/{chunk-JSJTZ6GO.js → chunk-VWMUDKLC.js} +3 -3
- package/chunks/{chunk-RGTB44BO.js → chunk-VXZ5HAOV.js} +1 -1
- package/chunks/{chunk-BCMJPTXV.js → chunk-WG6542MA.js} +1 -1
- package/chunks/{chunk-AG3P2RES.js → chunk-WV5J6Q6N.js} +1 -1
- package/chunks/{chunk-MIA37QO3.js → chunk-XHD7CRP2.js} +2 -2
- package/chunks/{chunk-KKRGVSHC.js → chunk-XZKQT2B2.js} +4 -4
- package/chunks/{chunk-4QJJHIZ5.js → chunk-Y4TETC74.js} +5 -5
- package/chunks/{chunk-QKJT5K4Q.js → chunk-YEF7XEO2.js} +3 -3
- package/chunks/{chunk-UKAYEQDU.js → chunk-YHJFF7KH.js} +131 -38
- package/chunks/{chunk-64YLXLMY.js → chunk-YOM7DEGB.js} +2 -2
- package/chunks/{chunk-BN3OROB3.js → chunk-ZCLLJARV.js} +9 -9
- package/chunks/{chunk-RFA6VDCR.js → chunk-ZHA242R4.js} +2 -2
- package/chunks/{chunk-L4OW63GW.js → chunk-ZPLALRXZ.js} +17 -9
- package/chunks/{computer-use-QLJ27OCZ.js → computer-use-ESQYJ3JY.js} +13 -10
- package/chunks/{config-utils-KIEXWA4F.js → config-utils-XQHBJP7G.js} +2 -2
- package/chunks/{contextCommand-JDTOJRBO.js → contextCommand-CX3YF4ZE.js} +15 -12
- package/chunks/{core-runtime-MZIAVYQC.js → core-runtime-DIAU7JMG.js} +13 -10
- package/chunks/{create-sub-session-YBBCNSHE.js → create-sub-session-HDPD6HOA.js} +13 -10
- package/chunks/{daemon-SCTQMM7Z.js → daemon-VZBGJUNL.js} +30 -0
- package/chunks/{daemon-status-provider-BZ7RD4ZJ.js → daemon-status-provider-H6O4UQ4F.js} +19 -16
- package/chunks/{daemon-trust-policy-2E4C3M7S.js → daemon-trust-policy-BNUXG6MT.js} +20 -17
- package/chunks/{daemon-trust-policy-monitor-UYLFH6RW.js → daemon-trust-policy-monitor-E4EQ7GF4.js} +20 -17
- package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
- package/chunks/{deferred-core-runtime-6XZYMJZB.js → deferred-core-runtime-CBMSHPAU.js} +13 -10
- package/chunks/{dist-BATY7GI4.js → dist-EEEQGCZA.js} +731 -136
- package/chunks/{dist-26RK5XZO.js → dist-MKX5OSFF.js} +4 -3
- package/chunks/{earlyInputCapture-LATQCGDC.js → earlyInputCapture-UIOP7OIN.js} +13 -10
- package/chunks/{edit-72DP57CD.js → edit-ITMZYFKA.js} +13 -10
- package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
- package/chunks/{enter-worktree-B4FY2ZPP.js → enter-worktree-S4PL5UV6.js} +13 -10
- package/chunks/{enterPlanMode-TQBWGCPL.js → enterPlanMode-YV52NNJT.js} +13 -10
- package/chunks/{environment-MOGZGZDS.js → environment-NGOWPRZV.js} +17 -14
- package/chunks/{errors-PGON5GH7.js → errors-BU26DTDX.js} +15 -12
- package/chunks/{exit-worktree-EYUD4YP2.js → exit-worktree-XRM6LH5F.js} +13 -10
- package/chunks/{exitPlanMode-4Q7BSQXR.js → exitPlanMode-ZLI5F7KR.js} +13 -10
- package/chunks/{fast-path-WI7D5MER.js → fast-path-UJWORIED.js} +3 -3
- package/chunks/{fast-path-settings-YBRL24DB.js → fast-path-settings-37WQD5B2.js} +6 -3
- package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
- package/chunks/{gemini-ZXURGM6Y.js → gemini-ZSKNDUMU.js} +55 -48
- package/chunks/{geminiContentGenerator-EOODO75Y.js → geminiContentGenerator-YGEXOEKD.js} +1 -1
- package/chunks/{glob-QNRIUOS6.js → glob-7KZG44BR.js} +13 -10
- package/chunks/{goal-tools-QSYW65HV.js → goal-tools-PXWN5VK3.js} +3 -1
- package/chunks/{grep-56MTW67B.js → grep-6ZFC7RJ5.js} +13 -10
- package/chunks/{handleAutoUpdate-XGFIPVT4.js → handleAutoUpdate-KSEL3TQS.js} +17 -14
- package/chunks/{i18n-RZB35L4B.js → i18n-ZIUXBW5V.js} +14 -11
- package/chunks/{image-gen-OE2EEKN3.js → image-gen-AUIZJJNK.js} +6 -4
- package/chunks/{initializer-YPVMTMKD.js → initializer-7AHY3N6Q.js} +20 -17
- package/chunks/{installationInfo-ZTMTMYNW.js → installationInfo-VGBXMYLY.js} +14 -11
- package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
- package/chunks/{list-NIW3WID5.js → list-PSFKQHLB.js} +23 -20
- package/chunks/{loadedSettingsAdapter-VSLILTOZ.js → loadedSettingsAdapter-FTMRCTOF.js} +20 -17
- package/chunks/{loggingContentGenerator-KFZYVAGV.js → loggingContentGenerator-MZAN52UV.js} +5 -3
- package/chunks/{managed-npm-update-WHTA2K5V.js → managed-npm-update-O4NHK45X.js} +14 -11
- package/chunks/{mcp-7KGK3CS3.js → mcp-6CFP2AYQ.js} +20 -17
- package/chunks/{monitor-FDWEJQWP.js → monitor-DAKD6OU4.js} +13 -10
- package/chunks/{nonInteractiveCli-2MVJ6TCS.js → nonInteractiveCli-RC7VIUZL.js} +49 -44
- package/chunks/{notebook-edit-ZUVK2XWE.js → notebook-edit-474DPMRL.js} +13 -10
- package/chunks/{openaiContentGenerator-TNLWOPH5.js → openaiContentGenerator-2NFY2MWO.js} +6 -3
- package/chunks/{pidfile-BB6SKPH2.js → pidfile-KBFVDNQP.js} +13 -10
- package/chunks/{processUtils-WKHJOPDH.js → processUtils-6GRYH4Y3.js} +2 -2
- package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
- package/chunks/{qwenContentGenerator-FZS2DYF7.js → qwenContentGenerator-KAHU6IZY.js} +14 -11
- package/chunks/{qwenOAuth2-UYMYRXBB.js → qwenOAuth2-RRQTCP4W.js} +6 -4
- package/chunks/{read-file-FMTE6LPA.js → read-file-3M6WXDXP.js} +4 -2
- package/chunks/{resumeHistoryUtils-Z34RCZFF.js → resumeHistoryUtils-D6TAY3HX.js} +16 -13
- package/chunks/{ripGrep-DUIYUZGM.js → ripGrep-PLPENT3E.js} +13 -10
- package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
- package/chunks/{run-qwen-serve-KOHHR3F4.js → run-qwen-serve-ZAFIJKJC.js} +93 -40
- package/chunks/{runtime-K4NTZSAU.js → runtime-ZED7CYOZ.js} +23 -20
- package/chunks/{scheduler-6G6AMURS.js → scheduler-MD3AL2W5.js} +13 -10
- package/chunks/{serve-NMG2TM5K.js → serve-E3VUDRZN.js} +20 -17
- package/chunks/{server-FS7KDELS.js → server-OWMEMAKR.js} +381 -192
- package/chunks/{session-XZADUVKJ.js → session-HZ57QK7K.js} +141 -81
- package/chunks/{settings-G75R6FOA.js → settings-V7BR3RKP.js} +19 -16
- package/chunks/{shell-3D3PMQHE.js → shell-23OMNMW6.js} +13 -10
- package/chunks/{skill-TSEYMVQ2.js → skill-6HBDYZRS.js} +4 -2
- package/chunks/{skill-settings-HJC2CPBJ.js → skill-settings-HWJLTU7M.js} +19 -16
- package/chunks/{spawnChannel-YWCN74G5.js → spawnChannel-N6KKUW5B.js} +13 -10
- package/chunks/{standalone-update-HLYOLX6V.js → standalone-update-QGIKHATD.js} +15 -12
- package/chunks/{startInteractiveUI-ROUIQ5KU.js → startInteractiveUI-GX2CRL42.js} +269 -118
- package/chunks/{team-create-OTP5SSB2.js → team-create-CFFKU7KL.js} +13 -10
- package/chunks/{team-plan-approval-TQX5TMXU.js → team-plan-approval-6EFOKR6A.js} +13 -10
- package/chunks/{terminal-image-renderer-KF3GKNWW.js → terminal-image-renderer-TLDNACQY.js} +13 -10
- package/chunks/{theme-manager-XVWAAGAM.js → theme-manager-5LJ3H7VO.js} +13 -10
- package/chunks/{tool-search-7N4D4O56.js → tool-search-UJV3A24H.js} +4 -2
- package/chunks/{total-session-admission-ZQ4VKIRW.js → total-session-admission-D63QYXGO.js} +15 -12
- package/chunks/{trustedFolders-4XYFPWVV.js → trustedFolders-KZCOB53W.js} +17 -12
- package/chunks/{update-relaunch-L4GSBLUU.js → update-relaunch-IFILM3SA.js} +5 -5
- package/chunks/{updateCheck-PCUTVRFE.js → updateCheck-YZ2CRCFC.js} +16 -13
- package/chunks/{useAutoAcceptIndicator-WMXY7MND.js → useAutoAcceptIndicator-AXEVNA3Q.js} +22 -19
- package/chunks/{validateNonInterActiveAuth-5S3U2D56.js → validateNonInterActiveAuth-3WTOJFWA.js} +44 -41
- package/chunks/{version-P57IQU2T.js → version-GXK7OHZY.js} +1 -1
- package/chunks/{web-fetch-5ZLLLCDD.js → web-fetch-ILB4GAVR.js} +10 -6
- package/chunks/{web-search-NELKANTW.js → web-search-HKRPGPZZ.js} +5 -3
- package/chunks/{workflow-RXKBF3LO.js → workflow-FXIPRQQA.js} +735 -134
- package/chunks/{workspace-providers-status-HAEMNAWC.js → workspace-providers-status-NYHC7HSR.js} +22 -19
- package/chunks/{workspace-registration-store-U3U3YM6V.js → workspace-registration-store-AKEB7OMW.js} +1 -1
- package/chunks/{workspace-registry-ZFP33GVB.js → workspace-registry-CDAS5TVZ.js} +15 -12
- package/chunks/{workspace-service-QMISJBMA.js → workspace-service-PAMUKMAV.js} +23 -20
- package/chunks/{workspace-skills-status-K7EOUGXL.js → workspace-skills-status-YQSHCCMS.js} +20 -17
- package/chunks/{workspace-trust-reconciler-BFPKULDZ.js → workspace-trust-reconciler-RPTXOIY2.js} +22 -19
- package/chunks/{write-file-2F76RRFE.js → write-file-CGS57TS4.js} +13 -10
- package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
- package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
- package/chunks/{zoom-image-DPR22XWY.js → zoom-image-E7D72GYV.js} +4 -2
- package/cli.js +13 -13
- package/locales/ca.js +10 -0
- package/locales/de.js +9 -0
- package/locales/en.js +10 -0
- package/locales/fr.js +9 -0
- package/locales/ja.js +9 -0
- package/locales/pt.js +9 -0
- package/locales/ru.js +9 -0
- package/locales/zh-TW.js +10 -0
- package/locales/zh.js +10 -0
- package/package.json +3 -3
- package/web-shell/assets/{arc-CunFPPcQ.js → arc-DybZaz32.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-D3SqCgeM.js → architectureDiagram-3BPJPVTR-jN3qBd19.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CPRx90S_.js → blockDiagram-GPEHLZMM-Ct5DZPrj.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CahP9Ue4.js → c4Diagram-AAUBKEIU-CUAFMlUG.js} +1 -1
- package/web-shell/assets/channel-BMwLrwLW.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-DckIWZ12.js → chunk-2J33WTMH-CuV8n90B.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-D2Kfctyn.js → chunk-4BX2VUAB-BUzl_kls.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DkI11FTX.js → chunk-55IACEB6-BnDBLX6A.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-rR-TSCIi.js → chunk-727SXJPM-B83uTOjm.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DFGKcGRO.js → chunk-AQP2D5EJ-DM3HLgpT.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CjWqcTPE.js → chunk-FMBD7UC4-CSQ5hgyb.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-RXe-87UV.js → chunk-ND2GUHAM-BWOF4SxX.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-Dz0c_Yrn.js → chunk-QZHKN3VN-BsOH9LMi.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-ZHF0-jvV.js → cose-bilkent-S5V4N54A-IENqH2iJ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-7Umz_ygJ.js → dagre-BM42HDAG--dyzDTGo.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-DomN8nxq.js → diagram-2AECGRRQ-BE7Dcqof.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-eebvj2OL.js → diagram-5GNKFQAL-Cr8-5OTj.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-IR1mmn9d.js → diagram-KO2AKTUF-Bzey3uAY.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-CKysx5KF.js → diagram-LMA3HP47-sErl28Xb.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-cBy5puHn.js → diagram-OG6HWLK6-Dq30ATIo.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-B5RJagPG.js → erDiagram-TEJ5UH35-BkCoEfVW.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CfHgDmPg.js → flowDiagram-I6XJVG4X-DHwO0rrI.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DUfFF5nb.js → ganttDiagram-6RSMTGT7-s7vAPxWq.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-M9dt57k5.js → gitGraphDiagram-PVQCEYII-CQxhwPOU.js} +1 -1
- package/web-shell/assets/{index-B8e-CkuC.css → index-Bckpjr-I.css} +1 -1
- package/web-shell/assets/{index-CKjO4myk.js → index-CF4wApWp.js} +1 -1
- package/web-shell/assets/{index-Dc-fTO0V.js → index-DwEr9HEW.js} +316 -316
- package/web-shell/assets/{infoDiagram-5YYISTIA-CTKMmIro.js → infoDiagram-5YYISTIA-BnFrD0bq.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DJIJDP4s.js → ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-DgRnvn6S.js → journeyDiagram-JHISSGLW-CyGAhsxi.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-VUwO8yrg.js → kanban-definition-UN3LZRKU-CbsK5akB.js} +1 -1
- package/web-shell/assets/{linear-BCvgV5I_.js → linear-cQsF4P8D.js} +1 -1
- package/web-shell/assets/{mermaid.core-mv_kVV6q.js → mermaid.core-Z4HVqrKY.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-sfnjMlOd.js → mindmap-definition-RKZ34NQL-CYnrBo_f.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-BlhICse4.js → pieDiagram-4H26LBE5-CBzOfhrs.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BgTQzwen.js → quadrantDiagram-W4KKPZXB-D4LK1Ebn.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CZ-FTrrN.js → requirementDiagram-4Y6WPE33-Bzti2Lcj.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-G5Wp_jn3.js → sankeyDiagram-5OEKKPKP-yTBw5Z2s.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-C8MKZ3i1.js → sequenceDiagram-3UESZ5HK-D07UVRiZ.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-Bo0ZDm7y.js → stateDiagram-AJRCARHV-UE_lHsTn.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-M3L9E01f.js → timeline-definition-PNZ67QCA-DRvYdiTs.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DD4eHCrm.js → vennDiagram-CIIHVFJN-CQLIXs0u.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-DNEL_3g4.js → wardley-L42UT6IY-JZz_Xqse.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-q484OoqI.js → wardleyDiagram-YWT4CUSO--i7BiJwB.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-4mcNt1Yg.js → xychartDiagram-2RQKCTM6-Bkc-bW0S.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-ALFTV7GA.js +0 -92
- package/web-shell/assets/channel-zbv7GWAw.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-DSjLkJJZ.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DSjLkJJZ.js +0 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-31TSCPcH.js +0 -1
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
serveCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HWX5HPUG.js";
|
|
6
6
|
import {
|
|
7
7
|
listCommand
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EIVICVHM.js";
|
|
9
9
|
import {
|
|
10
10
|
getErrorMessage as getErrorMessage2
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IYES5WOT.js";
|
|
12
12
|
import {
|
|
13
13
|
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
14
14
|
ObservedChannelContactStore
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
collectProviderModelsForProtocol,
|
|
30
30
|
getAuthTypeFromEnv,
|
|
31
31
|
resolveCliGenerationConfig
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-GBDINRIL.js";
|
|
33
33
|
import {
|
|
34
34
|
resolvePath
|
|
35
35
|
} from "./chunk-AOHJKPKL.js";
|
|
@@ -52,17 +52,17 @@ import {
|
|
|
52
52
|
registerToolCallDispatch,
|
|
53
53
|
selectFirstModel,
|
|
54
54
|
sessionsPath
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-E4ZBKMSF.js";
|
|
56
56
|
import {
|
|
57
57
|
getExtensionManager,
|
|
58
58
|
requestChoicePluginNonInteractive,
|
|
59
59
|
requestConsentNonInteractive,
|
|
60
60
|
requestConsentOrFail,
|
|
61
61
|
resolveExtensionCommandScope
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-QQWD7LZV.js";
|
|
63
63
|
import {
|
|
64
64
|
parseChannelConfig
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-QXVSWG66.js";
|
|
66
66
|
import {
|
|
67
67
|
findCliEntryPath
|
|
68
68
|
} from "./chunk-V6WHFGST.js";
|
|
@@ -132,35 +132,36 @@ import {
|
|
|
132
132
|
assembleMcpServers,
|
|
133
133
|
getPendingGatedMcpServers,
|
|
134
134
|
mcpCommand
|
|
135
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-Y4TETC74.js";
|
|
136
136
|
import {
|
|
137
137
|
loadSettings
|
|
138
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-OHKJVAKG.js";
|
|
139
139
|
import {
|
|
140
140
|
detectSystemLanguage,
|
|
141
141
|
getCurrentLanguage,
|
|
142
142
|
initializeI18n,
|
|
143
143
|
resolveLanguageSetting,
|
|
144
144
|
t
|
|
145
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-PG62DFWD.js";
|
|
146
146
|
import {
|
|
147
147
|
loadEnvironment
|
|
148
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-B52AWKBB.js";
|
|
149
149
|
import {
|
|
150
|
-
resolveAcpChannelFallback
|
|
151
|
-
|
|
150
|
+
resolveAcpChannelFallback,
|
|
151
|
+
scrubAndReportInheritedLoaderEnv
|
|
152
|
+
} from "./chunk-UA5H3DS2.js";
|
|
152
153
|
import {
|
|
153
154
|
getCliVersion
|
|
154
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-FN6YXJOP.js";
|
|
155
156
|
import {
|
|
156
157
|
getPackageJson
|
|
157
158
|
} from "./chunk-VJNBRRZG.js";
|
|
158
159
|
import {
|
|
159
160
|
isWorkspaceTrusted
|
|
160
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-HA3SAB64.js";
|
|
161
162
|
import {
|
|
162
163
|
require_strip_json_comments
|
|
163
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-NPQ5ZKRP.js";
|
|
164
165
|
import {
|
|
165
166
|
hideBin,
|
|
166
167
|
yargs_default
|
|
@@ -199,7 +200,7 @@ import {
|
|
|
199
200
|
unquoteCStylePath,
|
|
200
201
|
updateChannelMemoryEntry,
|
|
201
202
|
updateSetting
|
|
202
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-GXSNGY5M.js";
|
|
203
204
|
import {
|
|
204
205
|
nextFireTime,
|
|
205
206
|
parseCron
|
|
@@ -215,14 +216,14 @@ import {
|
|
|
215
216
|
getAllGeminiMdFilenames,
|
|
216
217
|
parseLineTolerant,
|
|
217
218
|
setGeminiMdFilename
|
|
218
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-3PY4LPJF.js";
|
|
219
220
|
import {
|
|
220
221
|
SchemaValidator,
|
|
221
222
|
ToolNames
|
|
222
223
|
} from "./chunk-PYQADEFD.js";
|
|
223
224
|
import {
|
|
224
225
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
225
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-F6WFNA7U.js";
|
|
226
227
|
import {
|
|
227
228
|
isTlsVerificationDisabled
|
|
228
229
|
} from "./chunk-KKBPOU75.js";
|
|
@@ -2729,7 +2730,7 @@ var stopCommand = {
|
|
|
2729
2730
|
if (argv["daemon-url"]) {
|
|
2730
2731
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2731
2732
|
try {
|
|
2732
|
-
const sdk = await import("./daemon-
|
|
2733
|
+
const sdk = await import("./daemon-VZBGJUNL.js");
|
|
2733
2734
|
const client = new sdk.DaemonClient({
|
|
2734
2735
|
baseUrl: argv["daemon-url"],
|
|
2735
2736
|
...token ? { token } : {}
|
|
@@ -2915,7 +2916,7 @@ var statusCommand = {
|
|
|
2915
2916
|
if (argv["daemon-url"]) {
|
|
2916
2917
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2917
2918
|
try {
|
|
2918
|
-
const sdk = await import("./daemon-
|
|
2919
|
+
const sdk = await import("./daemon-VZBGJUNL.js");
|
|
2919
2920
|
const client = new sdk.DaemonClient({
|
|
2920
2921
|
baseUrl: argv["daemon-url"],
|
|
2921
2922
|
...token ? { token } : {}
|
|
@@ -3026,7 +3027,7 @@ var reloadCommand = {
|
|
|
3026
3027
|
const token = resolveToken(argv.token);
|
|
3027
3028
|
let sdk;
|
|
3028
3029
|
try {
|
|
3029
|
-
sdk = await import("./daemon-
|
|
3030
|
+
sdk = await import("./daemon-VZBGJUNL.js");
|
|
3030
3031
|
} catch (err) {
|
|
3031
3032
|
writeStderrLine(
|
|
3032
3033
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(err)}`
|
|
@@ -3106,7 +3107,7 @@ var setCommand2 = {
|
|
|
3106
3107
|
const selection = names[0] === "all" ? { mode: "all" } : { mode: "names", names };
|
|
3107
3108
|
let sdk;
|
|
3108
3109
|
try {
|
|
3109
|
-
sdk = await import("./daemon-
|
|
3110
|
+
sdk = await import("./daemon-VZBGJUNL.js");
|
|
3110
3111
|
} catch (error) {
|
|
3111
3112
|
writeStderrLine(
|
|
3112
3113
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(error)}`
|
|
@@ -3232,7 +3233,7 @@ function createDaemonChannelBridgeFacade(bridge, opts) {
|
|
|
3232
3233
|
}
|
|
3233
3234
|
__name(createDaemonChannelBridgeFacade, "createDaemonChannelBridgeFacade");
|
|
3234
3235
|
async function loadDaemonSdk() {
|
|
3235
|
-
return await import("./daemon-
|
|
3236
|
+
return await import("./daemon-VZBGJUNL.js");
|
|
3236
3237
|
}
|
|
3237
3238
|
__name(loadDaemonSdk, "loadDaemonSdk");
|
|
3238
3239
|
function selectedChannelNames(channelsConfig, selection) {
|
|
@@ -3792,6 +3793,11 @@ var daemonWorkerCommand = {
|
|
|
3792
3793
|
try {
|
|
3793
3794
|
assertInternalDaemonWorkerInvocation();
|
|
3794
3795
|
const { daemonToken, daemonUrl, workspace } = readDaemonWorkerEnv();
|
|
3796
|
+
scrubAndReportInheritedLoaderEnv(
|
|
3797
|
+
process.env,
|
|
3798
|
+
"qwen channel daemon-worker",
|
|
3799
|
+
"channel daemon worker"
|
|
3800
|
+
);
|
|
3795
3801
|
const send = process.send;
|
|
3796
3802
|
channelLoopMcpHost = new ChannelLoopMcpWorkerHost(
|
|
3797
3803
|
(message, callback) => send.call(process, message, callback ?? (() => {
|
|
@@ -4829,224 +4835,587 @@ var parseArgsCommand = {
|
|
|
4829
4835
|
}, "handler")
|
|
4830
4836
|
};
|
|
4831
4837
|
|
|
4832
|
-
// packages/cli/src/commands/review/
|
|
4833
|
-
init_esbuild_shims();
|
|
4834
|
-
import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
4835
|
-
import { dirname as dirname5, join as join10 } from "node:path";
|
|
4836
|
-
|
|
4837
|
-
// packages/cli/src/commands/review/lib/coverage.ts
|
|
4838
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
4838
4839
|
init_esbuild_shims();
|
|
4839
|
-
import { readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
|
|
4840
4840
|
|
|
4841
|
-
// packages/cli/src/commands/review/lib/
|
|
4841
|
+
// packages/cli/src/commands/review/lib/gh.ts
|
|
4842
4842
|
init_esbuild_shims();
|
|
4843
|
-
import {
|
|
4844
|
-
|
|
4845
|
-
var
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
}
|
|
4849
|
-
};
|
|
4850
|
-
function transcriptPaths(env = process.env) {
|
|
4851
|
-
const projectDir = env["QWEN_CODE_PROJECT_DIR"]?.trim();
|
|
4852
|
-
const sessionId = env["QWEN_CODE_SESSION_ID"]?.trim();
|
|
4853
|
-
if (!projectDir || !sessionId) {
|
|
4854
|
-
throw new TranscriptsUnavailableError(
|
|
4855
|
-
"the CLI did not export QWEN_CODE_PROJECT_DIR / QWEN_CODE_SESSION_ID, so this run cannot find the harness's record of what its agents did"
|
|
4856
|
-
);
|
|
4857
|
-
}
|
|
4858
|
-
return {
|
|
4859
|
-
projectDir,
|
|
4860
|
-
sessionId,
|
|
4861
|
-
dir: join6(projectDir, "subagents", sessionId)
|
|
4862
|
-
};
|
|
4863
|
-
}
|
|
4864
|
-
__name(transcriptPaths, "transcriptPaths");
|
|
4865
|
-
function transcriptDir(env = process.env) {
|
|
4866
|
-
return transcriptPaths(env).dir;
|
|
4867
|
-
}
|
|
4868
|
-
__name(transcriptDir, "transcriptDir");
|
|
4869
|
-
function textOf(rec) {
|
|
4870
|
-
const msg = rec["message"];
|
|
4871
|
-
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
4872
|
-
return parts.map((p) => p.text).filter((t2) => typeof t2 === "string").join("");
|
|
4873
|
-
}
|
|
4874
|
-
__name(textOf, "textOf");
|
|
4875
|
-
function isErrorPart(part) {
|
|
4876
|
-
const resp = part.functionResponse?.response;
|
|
4877
|
-
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
4843
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4844
|
+
var MAX_RETRIES = 2;
|
|
4845
|
+
var BASE_DELAY_MS = 3e3;
|
|
4846
|
+
function sleepSync(ms) {
|
|
4847
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
4878
4848
|
}
|
|
4879
|
-
__name(
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
const
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
}
|
|
4886
|
-
const off = typeof offset === "number" && Number.isInteger(offset) && offset >= 0 ? offset : 0;
|
|
4887
|
-
return [off + 1, off + limit];
|
|
4849
|
+
__name(sleepSync, "sleepSync");
|
|
4850
|
+
var TRANSIENT_RE = /HTTP 5\d{2}|server is currently unavailable|service unavailable|bad gateway|internal server error/i;
|
|
4851
|
+
function isTransientGhError(err) {
|
|
4852
|
+
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
4853
|
+
const msg = err instanceof Error ? err.message : "";
|
|
4854
|
+
return TRANSIENT_RE.test(stderr) || TRANSIENT_RE.test(msg);
|
|
4888
4855
|
}
|
|
4889
|
-
__name(
|
|
4890
|
-
function
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
}
|
|
4897
|
-
|
|
4898
|
-
if (lines.length === 0) return null;
|
|
4899
|
-
let agentId = "";
|
|
4900
|
-
let agentName = "";
|
|
4901
|
-
let launchPrompt = "";
|
|
4902
|
-
let finalText = "";
|
|
4903
|
-
let successfulToolCalls = 0;
|
|
4904
|
-
let diffToolCalls = 0;
|
|
4905
|
-
const diffReads = [];
|
|
4906
|
-
const successfulCallArgs = [];
|
|
4907
|
-
const successfulReadFileArgs = [];
|
|
4908
|
-
const byId = /* @__PURE__ */ new Map();
|
|
4909
|
-
const anonymous = [];
|
|
4910
|
-
for (const line of lines) {
|
|
4911
|
-
let rec;
|
|
4856
|
+
__name(isTransientGhError, "isTransientGhError");
|
|
4857
|
+
function execGhWithRetry(args, options) {
|
|
4858
|
+
const execOptions = {
|
|
4859
|
+
encoding: "utf8",
|
|
4860
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4861
|
+
env: ghEnv(),
|
|
4862
|
+
...options.input !== void 0 ? { input: options.input } : {}
|
|
4863
|
+
};
|
|
4864
|
+
for (let attempt = 0; ; attempt++) {
|
|
4912
4865
|
try {
|
|
4913
|
-
|
|
4914
|
-
} catch {
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
const type = rec["type"];
|
|
4923
|
-
if (!launchPrompt && type === "user") launchPrompt = textOf(rec);
|
|
4924
|
-
const msg = rec["message"];
|
|
4925
|
-
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
4926
|
-
for (const part of parts) {
|
|
4927
|
-
const fc = part.functionCall;
|
|
4928
|
-
if (!fc) continue;
|
|
4929
|
-
const args = fc.args ?? {};
|
|
4930
|
-
const namedTheDiff = diffPath ? JSON.stringify(args).includes(JSON.stringify(diffPath)) : false;
|
|
4931
|
-
const pending = {
|
|
4932
|
-
namedTheDiff,
|
|
4933
|
-
readFile: fc.name === ToolNames.READ_FILE,
|
|
4934
|
-
range: namedTheDiff ? rangeOf(args) : null,
|
|
4935
|
-
args: JSON.stringify(args)
|
|
4936
|
-
};
|
|
4937
|
-
if (typeof fc.id === "string" && fc.id) byId.set(fc.id, pending);
|
|
4938
|
-
else anonymous.push(pending);
|
|
4939
|
-
}
|
|
4940
|
-
for (const part of parts) {
|
|
4941
|
-
const fr = part.functionResponse;
|
|
4942
|
-
if (!fr) continue;
|
|
4943
|
-
let pending;
|
|
4944
|
-
if (typeof fr.id === "string" && byId.has(fr.id)) {
|
|
4945
|
-
pending = byId.get(fr.id);
|
|
4946
|
-
byId.delete(fr.id);
|
|
4947
|
-
} else if (anonymous.length > 0) {
|
|
4948
|
-
pending = anonymous.shift();
|
|
4949
|
-
} else {
|
|
4866
|
+
return execFileSync2("gh", args, execOptions).replace(/\r\n/g, "\n").trim();
|
|
4867
|
+
} catch (err) {
|
|
4868
|
+
if (attempt < MAX_RETRIES && isTransientGhError(err)) {
|
|
4869
|
+
const delay = BASE_DELAY_MS * (attempt + 1);
|
|
4870
|
+
process.stderr.write(
|
|
4871
|
+
`gh transient error (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms\u2026
|
|
4872
|
+
`
|
|
4873
|
+
);
|
|
4874
|
+
sleepSync(delay);
|
|
4950
4875
|
continue;
|
|
4951
4876
|
}
|
|
4952
|
-
|
|
4953
|
-
successfulToolCalls++;
|
|
4954
|
-
successfulCallArgs.push(pending.args);
|
|
4955
|
-
if (pending.readFile) successfulReadFileArgs.push(pending.args);
|
|
4956
|
-
if (pending.namedTheDiff) {
|
|
4957
|
-
diffToolCalls++;
|
|
4958
|
-
if (pending.range) diffReads.push(pending.range);
|
|
4959
|
-
}
|
|
4960
|
-
}
|
|
4961
|
-
}
|
|
4962
|
-
if (type === "assistant") {
|
|
4963
|
-
const t2 = textOf(rec);
|
|
4964
|
-
if (t2) finalText = t2;
|
|
4877
|
+
throw err;
|
|
4965
4878
|
}
|
|
4966
4879
|
}
|
|
4967
|
-
if (!agentId) return null;
|
|
4968
|
-
let mtimeMs = 0;
|
|
4969
|
-
try {
|
|
4970
|
-
mtimeMs = statSync2(file).mtimeMs;
|
|
4971
|
-
} catch {
|
|
4972
|
-
}
|
|
4973
|
-
return {
|
|
4974
|
-
agentId,
|
|
4975
|
-
agentName,
|
|
4976
|
-
launchPrompt,
|
|
4977
|
-
successfulToolCalls,
|
|
4978
|
-
diffToolCalls,
|
|
4979
|
-
diffReads,
|
|
4980
|
-
successfulCallArgs,
|
|
4981
|
-
successfulReadFileArgs,
|
|
4982
|
-
finalText,
|
|
4983
|
-
mtimeMs
|
|
4984
|
-
};
|
|
4985
4880
|
}
|
|
4986
|
-
__name(
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
let names;
|
|
4994
|
-
try {
|
|
4995
|
-
names = listAgentTranscriptFiles(dir);
|
|
4996
|
-
} catch (err) {
|
|
4997
|
-
throw new TranscriptsUnavailableError(
|
|
4998
|
-
`no subagent transcripts at ${dir} (${err.message}). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.`
|
|
4999
|
-
);
|
|
4881
|
+
__name(execGhWithRetry, "execGhWithRetry");
|
|
4882
|
+
var ghHost;
|
|
4883
|
+
var HOSTNAME_RE = /^[A-Za-z0-9.-]+(?::\d+)?$/;
|
|
4884
|
+
function setGhHost(host) {
|
|
4885
|
+
if (host === void 0 || host === "") {
|
|
4886
|
+
ghHost = void 0;
|
|
4887
|
+
return;
|
|
5000
4888
|
}
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
if (since !== void 0 && rec.mtimeMs < since) continue;
|
|
5006
|
-
out.push(rec);
|
|
4889
|
+
if (!HOSTNAME_RE.test(host)) {
|
|
4890
|
+
throw new TypeError(
|
|
4891
|
+
`--host must be a hostname (optionally :port), got ${JSON.stringify(host)}`
|
|
4892
|
+
);
|
|
5007
4893
|
}
|
|
5008
|
-
|
|
4894
|
+
ghHost = host;
|
|
5009
4895
|
}
|
|
5010
|
-
__name(
|
|
5011
|
-
function
|
|
5012
|
-
|
|
5013
|
-
if (!p) return false;
|
|
5014
|
-
return p.includes(diffPath);
|
|
4896
|
+
__name(setGhHost, "setGhHost");
|
|
4897
|
+
function getGhHost() {
|
|
4898
|
+
return ghHost;
|
|
5015
4899
|
}
|
|
5016
|
-
__name(
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
init_esbuild_shims();
|
|
5020
|
-
import {
|
|
5021
|
-
mkdirSync as mkdirSync3,
|
|
5022
|
-
readFileSync as readFileSync6,
|
|
5023
|
-
readdirSync as readdirSync4,
|
|
5024
|
-
statSync as statSync3,
|
|
5025
|
-
writeFileSync as writeFileSync3
|
|
5026
|
-
} from "node:fs";
|
|
5027
|
-
import { dirname as dirname3, join as join7, basename as basename4, resolve as resolve4 } from "node:path";
|
|
5028
|
-
function promptRecordDir(planPath) {
|
|
5029
|
-
const p = resolve4(planPath);
|
|
5030
|
-
return join7(dirname3(p), `${basename4(p).replace(/\.json$/i, "")}-prompts`);
|
|
4900
|
+
__name(getGhHost, "getGhHost");
|
|
4901
|
+
function resolveGhHost(flagHost) {
|
|
4902
|
+
return flagHost ?? (process.env["GH_HOST"]?.trim() || void 0);
|
|
5031
4903
|
}
|
|
5032
|
-
__name(
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
return join7(promptRecordDir(planPath), `${encodeURIComponent(key)}.brief.md`);
|
|
4904
|
+
__name(resolveGhHost, "resolveGhHost");
|
|
4905
|
+
function ghEnv() {
|
|
4906
|
+
return ghHost ? { ...process.env, GH_HOST: ghHost } : void 0;
|
|
5036
4907
|
}
|
|
5037
|
-
__name(
|
|
5038
|
-
function
|
|
5039
|
-
return
|
|
5040
|
-
promptRecordDir(planPath),
|
|
5041
|
-
`${encodeURIComponent(key)}.findings.md`
|
|
5042
|
-
);
|
|
4908
|
+
__name(ghEnv, "ghEnv");
|
|
4909
|
+
function gh(...args) {
|
|
4910
|
+
return execGhWithRetry(args, {});
|
|
5043
4911
|
}
|
|
5044
|
-
__name(
|
|
5045
|
-
function
|
|
5046
|
-
|
|
5047
|
-
return m && m[1] !== void 0 ? m[1] : null;
|
|
4912
|
+
__name(gh, "gh");
|
|
4913
|
+
function ghWithInputRetried(input, ...args) {
|
|
4914
|
+
return execGhWithRetry(args, { input });
|
|
5048
4915
|
}
|
|
5049
|
-
__name(
|
|
4916
|
+
__name(ghWithInputRetried, "ghWithInputRetried");
|
|
4917
|
+
function ghWithInput(input, ...args) {
|
|
4918
|
+
return execFileSync2("gh", args, {
|
|
4919
|
+
encoding: "utf8",
|
|
4920
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
4921
|
+
env: ghEnv(),
|
|
4922
|
+
input
|
|
4923
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
4924
|
+
}
|
|
4925
|
+
__name(ghWithInput, "ghWithInput");
|
|
4926
|
+
function ghApiAll(path3) {
|
|
4927
|
+
const out = gh("api", "--paginate", path3);
|
|
4928
|
+
if (!out) return [];
|
|
4929
|
+
const parsed = JSON.parse(out);
|
|
4930
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4931
|
+
}
|
|
4932
|
+
__name(ghApiAll, "ghApiAll");
|
|
4933
|
+
function ghApiAllNested(path3, key) {
|
|
4934
|
+
return parseNdjson(gh("api", "--paginate", path3, "--jq", `.${key}[]`), {
|
|
4935
|
+
strict: true
|
|
4936
|
+
});
|
|
4937
|
+
}
|
|
4938
|
+
__name(ghApiAllNested, "ghApiAllNested");
|
|
4939
|
+
function parseNdjson(out, opts = {}) {
|
|
4940
|
+
const strict = opts.strict ?? true;
|
|
4941
|
+
if (!out) return [];
|
|
4942
|
+
const values = [];
|
|
4943
|
+
for (const line of out.split("\n")) {
|
|
4944
|
+
if (line.trim().length === 0) continue;
|
|
4945
|
+
if (strict) {
|
|
4946
|
+
values.push(JSON.parse(line));
|
|
4947
|
+
continue;
|
|
4948
|
+
}
|
|
4949
|
+
try {
|
|
4950
|
+
values.push(JSON.parse(line));
|
|
4951
|
+
} catch {
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
return values;
|
|
4955
|
+
}
|
|
4956
|
+
__name(parseNdjson, "parseNdjson");
|
|
4957
|
+
function currentUser() {
|
|
4958
|
+
return gh("api", "user", "--jq", ".login");
|
|
4959
|
+
}
|
|
4960
|
+
__name(currentUser, "currentUser");
|
|
4961
|
+
function ensureAuthenticated() {
|
|
4962
|
+
for (let attempt = 0; ; attempt++) {
|
|
4963
|
+
try {
|
|
4964
|
+
execFileSync2("gh", ["auth", "status"], { stdio: "pipe", env: ghEnv() });
|
|
4965
|
+
return;
|
|
4966
|
+
} catch (err) {
|
|
4967
|
+
if (attempt === 0 && err.code !== "ENOENT") {
|
|
4968
|
+
sleepSync(2e3);
|
|
4969
|
+
continue;
|
|
4970
|
+
}
|
|
4971
|
+
throw new Error(
|
|
4972
|
+
"gh CLI is not authenticated. Run `gh auth login` and retry."
|
|
4973
|
+
);
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
__name(ensureAuthenticated, "ensureAuthenticated");
|
|
4978
|
+
|
|
4979
|
+
// packages/cli/src/commands/review/lib/git.ts
|
|
4980
|
+
init_esbuild_shims();
|
|
4981
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
4982
|
+
import { existsSync as existsSync4, rmSync as rmSync2 } from "node:fs";
|
|
4983
|
+
var GIT_TIMEOUT_MS2 = 12e4;
|
|
4984
|
+
function gitOpts() {
|
|
4985
|
+
return {
|
|
4986
|
+
timeout: GIT_TIMEOUT_MS2,
|
|
4987
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
__name(gitOpts, "gitOpts");
|
|
4991
|
+
function git(...args) {
|
|
4992
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8" }).replace(/\r\n/g, "\n").trim();
|
|
4993
|
+
}
|
|
4994
|
+
__name(git, "git");
|
|
4995
|
+
function gitWithInput(input, args) {
|
|
4996
|
+
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8", input }).replace(/\r\n/g, "\n").trim();
|
|
4997
|
+
}
|
|
4998
|
+
__name(gitWithInput, "gitWithInput");
|
|
4999
|
+
function gitOpt(...args) {
|
|
5000
|
+
try {
|
|
5001
|
+
return execFileSync3("git", args, {
|
|
5002
|
+
...gitOpts(),
|
|
5003
|
+
encoding: "utf8",
|
|
5004
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5005
|
+
}).replace(/\r\n/g, "\n").trim();
|
|
5006
|
+
} catch {
|
|
5007
|
+
return null;
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
__name(gitOpt, "gitOpt");
|
|
5011
|
+
function refExists(ref) {
|
|
5012
|
+
return gitOpt("rev-parse", "--verify", "--quiet", ref) !== null;
|
|
5013
|
+
}
|
|
5014
|
+
__name(refExists, "refExists");
|
|
5015
|
+
function worktreeReleaseResult(existed, stillThere, removeError) {
|
|
5016
|
+
const freed = existed && !stillThere;
|
|
5017
|
+
if (!existed || freed) {
|
|
5018
|
+
return { existed, freed, reason: void 0 };
|
|
5019
|
+
}
|
|
5020
|
+
return {
|
|
5021
|
+
existed,
|
|
5022
|
+
freed,
|
|
5023
|
+
reason: removeError ? removeError instanceof Error ? removeError.message : String(removeError) : "the path is still there after `git worktree remove --force` and `rm -rf`"
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
__name(worktreeReleaseResult, "worktreeReleaseResult");
|
|
5027
|
+
function releaseWorktree(worktreePath2) {
|
|
5028
|
+
const existed = existsSync4(worktreePath2);
|
|
5029
|
+
let removeError;
|
|
5030
|
+
if (existed) {
|
|
5031
|
+
gitOpt("worktree", "remove", worktreePath2, "--force");
|
|
5032
|
+
try {
|
|
5033
|
+
rmSync2(worktreePath2, { recursive: true, force: true });
|
|
5034
|
+
} catch (e) {
|
|
5035
|
+
removeError = e;
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
gitOpt("worktree", "prune");
|
|
5039
|
+
return worktreeReleaseResult(existed, existsSync4(worktreePath2), removeError);
|
|
5040
|
+
}
|
|
5041
|
+
__name(releaseWorktree, "releaseWorktree");
|
|
5042
|
+
function gitRaw(...args) {
|
|
5043
|
+
return execFileSync3("git", args, {
|
|
5044
|
+
...gitOpts(),
|
|
5045
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
5046
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
__name(gitRaw, "gitRaw");
|
|
5050
|
+
function gitRawTolerateDiff(...args) {
|
|
5051
|
+
try {
|
|
5052
|
+
return gitRaw(...args);
|
|
5053
|
+
} catch (err) {
|
|
5054
|
+
const e = err;
|
|
5055
|
+
if (e.status === 1 && e.stdout && e.stdout.length > 0) return e.stdout;
|
|
5056
|
+
throw err;
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
__name(gitRawTolerateDiff, "gitRawTolerateDiff");
|
|
5060
|
+
|
|
5061
|
+
// packages/cli/src/commands/review/lib/remote-match.ts
|
|
5062
|
+
init_esbuild_shims();
|
|
5063
|
+
function normalizeSegment(value) {
|
|
5064
|
+
const v = value.toLowerCase();
|
|
5065
|
+
return v.endsWith(".git") ? v.slice(0, -4) : v;
|
|
5066
|
+
}
|
|
5067
|
+
__name(normalizeSegment, "normalizeSegment");
|
|
5068
|
+
function parseRemoteUrl(raw) {
|
|
5069
|
+
const url = raw.trim();
|
|
5070
|
+
if (url === "") return null;
|
|
5071
|
+
let host;
|
|
5072
|
+
let pathPart;
|
|
5073
|
+
const schemeIdx = url.indexOf("://");
|
|
5074
|
+
if (schemeIdx !== -1) {
|
|
5075
|
+
let parsed;
|
|
5076
|
+
try {
|
|
5077
|
+
parsed = new URL(url);
|
|
5078
|
+
} catch {
|
|
5079
|
+
return null;
|
|
5080
|
+
}
|
|
5081
|
+
if (parsed.hostname === "") return null;
|
|
5082
|
+
host = parsed.hostname;
|
|
5083
|
+
pathPart = parsed.pathname;
|
|
5084
|
+
} else {
|
|
5085
|
+
const colonIdx = url.indexOf(":");
|
|
5086
|
+
const slashIdx = url.indexOf("/");
|
|
5087
|
+
if (colonIdx === -1 || slashIdx === -1 || colonIdx > slashIdx) {
|
|
5088
|
+
return null;
|
|
5089
|
+
}
|
|
5090
|
+
host = url.slice(0, colonIdx);
|
|
5091
|
+
const atIdx = host.lastIndexOf("@");
|
|
5092
|
+
if (atIdx !== -1) host = host.slice(atIdx + 1);
|
|
5093
|
+
pathPart = url.slice(colonIdx + 1);
|
|
5094
|
+
}
|
|
5095
|
+
const segments = pathPart.split("/").map((s) => s.trim()).filter((s) => s !== "");
|
|
5096
|
+
if (segments.length !== 2) return null;
|
|
5097
|
+
if (host === "") return null;
|
|
5098
|
+
return {
|
|
5099
|
+
host: host.toLowerCase(),
|
|
5100
|
+
owner: normalizeSegment(segments[0]),
|
|
5101
|
+
repo: normalizeSegment(segments[1])
|
|
5102
|
+
};
|
|
5103
|
+
}
|
|
5104
|
+
__name(parseRemoteUrl, "parseRemoteUrl");
|
|
5105
|
+
function matchRemotes(remoteVOutput, { owner, repo, host = "github.com" }) {
|
|
5106
|
+
const wantOwner = normalizeSegment(owner);
|
|
5107
|
+
const wantRepo = normalizeSegment(repo);
|
|
5108
|
+
const wantHost = normalizeSegment(host.replace(/:\d+$/, ""));
|
|
5109
|
+
const matched = [];
|
|
5110
|
+
for (const line of remoteVOutput.split("\n")) {
|
|
5111
|
+
const trimmed = line.trim();
|
|
5112
|
+
if (trimmed === "" || !/\(fetch\)(\s+\[[^\]]*\])?$/.test(trimmed)) {
|
|
5113
|
+
continue;
|
|
5114
|
+
}
|
|
5115
|
+
const nameMatch = trimmed.match(
|
|
5116
|
+
/^(\S+)\s+(.*)\s+\(fetch\)(\s+\[[^\]]*\])?$/
|
|
5117
|
+
);
|
|
5118
|
+
if (!nameMatch) continue;
|
|
5119
|
+
const identity = parseRemoteUrl(nameMatch[2]);
|
|
5120
|
+
if (identity === null) continue;
|
|
5121
|
+
if (identity.host === wantHost && identity.owner === wantOwner && identity.repo === wantRepo) {
|
|
5122
|
+
matched.push(nameMatch[1]);
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
return { matched };
|
|
5126
|
+
}
|
|
5127
|
+
__name(matchRemotes, "matchRemotes");
|
|
5128
|
+
|
|
5129
|
+
// packages/cli/src/commands/review/match-remote.ts
|
|
5130
|
+
function runMatchRemote(args) {
|
|
5131
|
+
try {
|
|
5132
|
+
git("rev-parse", "--is-inside-work-tree");
|
|
5133
|
+
} catch (err) {
|
|
5134
|
+
writeStderrLineSafe(
|
|
5135
|
+
`match-remote: git cannot resolve this repository: ${err.message}`
|
|
5136
|
+
);
|
|
5137
|
+
process.exitCode = 1;
|
|
5138
|
+
return;
|
|
5139
|
+
}
|
|
5140
|
+
const host = resolveGhHost(args.host) ?? "github.com";
|
|
5141
|
+
let remoteV;
|
|
5142
|
+
try {
|
|
5143
|
+
remoteV = git("remote", "-v");
|
|
5144
|
+
} catch (err) {
|
|
5145
|
+
writeStderrLineSafe(
|
|
5146
|
+
`match-remote: \`git remote -v\` failed: ${err.message}`
|
|
5147
|
+
);
|
|
5148
|
+
process.exitCode = 1;
|
|
5149
|
+
return;
|
|
5150
|
+
}
|
|
5151
|
+
const { matched } = matchRemotes(remoteV, {
|
|
5152
|
+
owner: args.owner,
|
|
5153
|
+
repo: args.repo,
|
|
5154
|
+
host
|
|
5155
|
+
});
|
|
5156
|
+
if (matched.length === 1) {
|
|
5157
|
+
writeStdoutLine(matched[0]);
|
|
5158
|
+
return;
|
|
5159
|
+
}
|
|
5160
|
+
if (matched.length === 0) {
|
|
5161
|
+
writeStdoutLine("none");
|
|
5162
|
+
writeStderrLineSafe(
|
|
5163
|
+
`match-remote: no remote matches ${host}/${args.owner}/${args.repo} by exact host + owner/repo equality \u2014 the PR is not served by any remote of this repository.`
|
|
5164
|
+
);
|
|
5165
|
+
process.exitCode = 6;
|
|
5166
|
+
return;
|
|
5167
|
+
}
|
|
5168
|
+
for (const name of matched) {
|
|
5169
|
+
writeStdoutLine(name);
|
|
5170
|
+
}
|
|
5171
|
+
writeStderrLineSafe(
|
|
5172
|
+
`warning: ${matched.length} remotes match ${host}/${args.owner}/${args.repo} (${matched.join(", ")}); refusing to pick one \u2014 the review stops here.`
|
|
5173
|
+
);
|
|
5174
|
+
process.exitCode = 7;
|
|
5175
|
+
}
|
|
5176
|
+
__name(runMatchRemote, "runMatchRemote");
|
|
5177
|
+
var matchRemoteCommand = {
|
|
5178
|
+
command: "match-remote",
|
|
5179
|
+
describe: "Print the git remote whose URL matches an owner/repo by exact host + owner/repo equality (exit 6 when none, exit 7 when several)",
|
|
5180
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.option("owner", {
|
|
5181
|
+
type: "string",
|
|
5182
|
+
demandOption: true,
|
|
5183
|
+
describe: "The repository owner (from the PR URL, or `gh repo view`)"
|
|
5184
|
+
}).option("repo", {
|
|
5185
|
+
type: "string",
|
|
5186
|
+
demandOption: true,
|
|
5187
|
+
describe: "The repository name"
|
|
5188
|
+
}).option("host", {
|
|
5189
|
+
type: "string",
|
|
5190
|
+
describe: "The PR's host \u2014 from its URL, or from `gh repo view` for a bare number (omitted: inherit an operator-exported GH_HOST, else github.com)"
|
|
5191
|
+
}), "builder"),
|
|
5192
|
+
handler: /* @__PURE__ */ __name((argv) => {
|
|
5193
|
+
runMatchRemote({
|
|
5194
|
+
owner: String(argv["owner"]),
|
|
5195
|
+
repo: String(argv["repo"]),
|
|
5196
|
+
host: argv.host
|
|
5197
|
+
});
|
|
5198
|
+
}, "handler")
|
|
5199
|
+
};
|
|
5200
|
+
|
|
5201
|
+
// packages/cli/src/commands/review/compose-review.ts
|
|
5202
|
+
init_esbuild_shims();
|
|
5203
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
5204
|
+
import { dirname as dirname5, join as join10 } from "node:path";
|
|
5205
|
+
|
|
5206
|
+
// packages/cli/src/commands/review/lib/coverage.ts
|
|
5207
|
+
init_esbuild_shims();
|
|
5208
|
+
import { readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
|
|
5209
|
+
|
|
5210
|
+
// packages/cli/src/commands/review/lib/transcripts.ts
|
|
5211
|
+
init_esbuild_shims();
|
|
5212
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
5213
|
+
import { join as join6 } from "node:path";
|
|
5214
|
+
var TranscriptsUnavailableError = class extends Error {
|
|
5215
|
+
static {
|
|
5216
|
+
__name(this, "TranscriptsUnavailableError");
|
|
5217
|
+
}
|
|
5218
|
+
};
|
|
5219
|
+
function transcriptPaths(env = process.env) {
|
|
5220
|
+
const projectDir = env["QWEN_CODE_PROJECT_DIR"]?.trim();
|
|
5221
|
+
const sessionId = env["QWEN_CODE_SESSION_ID"]?.trim();
|
|
5222
|
+
if (!projectDir || !sessionId) {
|
|
5223
|
+
throw new TranscriptsUnavailableError(
|
|
5224
|
+
"the CLI did not export QWEN_CODE_PROJECT_DIR / QWEN_CODE_SESSION_ID, so this run cannot find the harness's record of what its agents did"
|
|
5225
|
+
);
|
|
5226
|
+
}
|
|
5227
|
+
return {
|
|
5228
|
+
projectDir,
|
|
5229
|
+
sessionId,
|
|
5230
|
+
dir: join6(projectDir, "subagents", sessionId)
|
|
5231
|
+
};
|
|
5232
|
+
}
|
|
5233
|
+
__name(transcriptPaths, "transcriptPaths");
|
|
5234
|
+
function transcriptDir(env = process.env) {
|
|
5235
|
+
return transcriptPaths(env).dir;
|
|
5236
|
+
}
|
|
5237
|
+
__name(transcriptDir, "transcriptDir");
|
|
5238
|
+
function textOf(rec) {
|
|
5239
|
+
const msg = rec["message"];
|
|
5240
|
+
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
5241
|
+
return parts.map((p) => p.text).filter((t2) => typeof t2 === "string").join("");
|
|
5242
|
+
}
|
|
5243
|
+
__name(textOf, "textOf");
|
|
5244
|
+
function isErrorPart(part) {
|
|
5245
|
+
const resp = part.functionResponse?.response;
|
|
5246
|
+
return !!resp && resp["error"] !== void 0 && resp["error"] !== null;
|
|
5247
|
+
}
|
|
5248
|
+
__name(isErrorPart, "isErrorPart");
|
|
5249
|
+
function rangeOf(args) {
|
|
5250
|
+
const offset = args["offset"];
|
|
5251
|
+
const limit = args["limit"];
|
|
5252
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
|
|
5253
|
+
return null;
|
|
5254
|
+
}
|
|
5255
|
+
const off = typeof offset === "number" && Number.isInteger(offset) && offset >= 0 ? offset : 0;
|
|
5256
|
+
return [off + 1, off + limit];
|
|
5257
|
+
}
|
|
5258
|
+
__name(rangeOf, "rangeOf");
|
|
5259
|
+
function parseTranscript(file, diffPath) {
|
|
5260
|
+
let raw;
|
|
5261
|
+
try {
|
|
5262
|
+
raw = readFileSync5(file, "utf8");
|
|
5263
|
+
} catch {
|
|
5264
|
+
return null;
|
|
5265
|
+
}
|
|
5266
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
5267
|
+
if (lines.length === 0) return null;
|
|
5268
|
+
let agentId = "";
|
|
5269
|
+
let agentName = "";
|
|
5270
|
+
let launchPrompt = "";
|
|
5271
|
+
let finalText = "";
|
|
5272
|
+
let successfulToolCalls = 0;
|
|
5273
|
+
let diffToolCalls = 0;
|
|
5274
|
+
const diffReads = [];
|
|
5275
|
+
const successfulCallArgs = [];
|
|
5276
|
+
const successfulReadFileArgs = [];
|
|
5277
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5278
|
+
const anonymous = [];
|
|
5279
|
+
for (const line of lines) {
|
|
5280
|
+
let rec;
|
|
5281
|
+
try {
|
|
5282
|
+
rec = JSON.parse(line);
|
|
5283
|
+
} catch {
|
|
5284
|
+
continue;
|
|
5285
|
+
}
|
|
5286
|
+
if (!agentId && typeof rec["agentId"] === "string")
|
|
5287
|
+
agentId = rec["agentId"];
|
|
5288
|
+
if (!agentName && typeof rec["agentName"] === "string") {
|
|
5289
|
+
agentName = rec["agentName"];
|
|
5290
|
+
}
|
|
5291
|
+
const type = rec["type"];
|
|
5292
|
+
if (!launchPrompt && type === "user") launchPrompt = textOf(rec);
|
|
5293
|
+
const msg = rec["message"];
|
|
5294
|
+
const parts = Array.isArray(msg?.parts) ? msg.parts : [];
|
|
5295
|
+
for (const part of parts) {
|
|
5296
|
+
const fc = part.functionCall;
|
|
5297
|
+
if (!fc) continue;
|
|
5298
|
+
const args = fc.args ?? {};
|
|
5299
|
+
const namedTheDiff = diffPath ? JSON.stringify(args).includes(JSON.stringify(diffPath)) : false;
|
|
5300
|
+
const pending = {
|
|
5301
|
+
namedTheDiff,
|
|
5302
|
+
readFile: fc.name === ToolNames.READ_FILE,
|
|
5303
|
+
range: namedTheDiff ? rangeOf(args) : null,
|
|
5304
|
+
args: JSON.stringify(args)
|
|
5305
|
+
};
|
|
5306
|
+
if (typeof fc.id === "string" && fc.id) byId.set(fc.id, pending);
|
|
5307
|
+
else anonymous.push(pending);
|
|
5308
|
+
}
|
|
5309
|
+
for (const part of parts) {
|
|
5310
|
+
const fr = part.functionResponse;
|
|
5311
|
+
if (!fr) continue;
|
|
5312
|
+
let pending;
|
|
5313
|
+
if (typeof fr.id === "string" && byId.has(fr.id)) {
|
|
5314
|
+
pending = byId.get(fr.id);
|
|
5315
|
+
byId.delete(fr.id);
|
|
5316
|
+
} else if (anonymous.length > 0) {
|
|
5317
|
+
pending = anonymous.shift();
|
|
5318
|
+
} else {
|
|
5319
|
+
continue;
|
|
5320
|
+
}
|
|
5321
|
+
if (!isErrorPart(part)) {
|
|
5322
|
+
successfulToolCalls++;
|
|
5323
|
+
successfulCallArgs.push(pending.args);
|
|
5324
|
+
if (pending.readFile) successfulReadFileArgs.push(pending.args);
|
|
5325
|
+
if (pending.namedTheDiff) {
|
|
5326
|
+
diffToolCalls++;
|
|
5327
|
+
if (pending.range) diffReads.push(pending.range);
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
if (type === "assistant") {
|
|
5332
|
+
const t2 = textOf(rec);
|
|
5333
|
+
if (t2) finalText = t2;
|
|
5334
|
+
}
|
|
5335
|
+
}
|
|
5336
|
+
if (!agentId) return null;
|
|
5337
|
+
let mtimeMs = 0;
|
|
5338
|
+
try {
|
|
5339
|
+
mtimeMs = statSync2(file).mtimeMs;
|
|
5340
|
+
} catch {
|
|
5341
|
+
}
|
|
5342
|
+
return {
|
|
5343
|
+
agentId,
|
|
5344
|
+
agentName,
|
|
5345
|
+
launchPrompt,
|
|
5346
|
+
successfulToolCalls,
|
|
5347
|
+
diffToolCalls,
|
|
5348
|
+
diffReads,
|
|
5349
|
+
successfulCallArgs,
|
|
5350
|
+
successfulReadFileArgs,
|
|
5351
|
+
finalText,
|
|
5352
|
+
mtimeMs
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
5355
|
+
__name(parseTranscript, "parseTranscript");
|
|
5356
|
+
function listAgentTranscriptFiles(dir) {
|
|
5357
|
+
return readdirSync3(dir).filter((name) => name.endsWith(".jsonl"));
|
|
5358
|
+
}
|
|
5359
|
+
__name(listAgentTranscriptFiles, "listAgentTranscriptFiles");
|
|
5360
|
+
function readTranscripts(since, env = process.env, diffPath) {
|
|
5361
|
+
const dir = transcriptDir(env);
|
|
5362
|
+
let names;
|
|
5363
|
+
try {
|
|
5364
|
+
names = listAgentTranscriptFiles(dir);
|
|
5365
|
+
} catch (err) {
|
|
5366
|
+
throw new TranscriptsUnavailableError(
|
|
5367
|
+
`no subagent transcripts at ${dir} (${err.message}). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.`
|
|
5368
|
+
);
|
|
5369
|
+
}
|
|
5370
|
+
const out = [];
|
|
5371
|
+
for (const name of names) {
|
|
5372
|
+
const rec = parseTranscript(join6(dir, name), diffPath);
|
|
5373
|
+
if (!rec) continue;
|
|
5374
|
+
if (since !== void 0 && rec.mtimeMs < since) continue;
|
|
5375
|
+
out.push(rec);
|
|
5376
|
+
}
|
|
5377
|
+
return out;
|
|
5378
|
+
}
|
|
5379
|
+
__name(readTranscripts, "readTranscripts");
|
|
5380
|
+
function wasGivenTheDiff(rec, diffPath) {
|
|
5381
|
+
const p = rec.launchPrompt;
|
|
5382
|
+
if (!p) return false;
|
|
5383
|
+
return p.includes(diffPath);
|
|
5384
|
+
}
|
|
5385
|
+
__name(wasGivenTheDiff, "wasGivenTheDiff");
|
|
5386
|
+
|
|
5387
|
+
// packages/cli/src/commands/review/lib/prompt-record.ts
|
|
5388
|
+
init_esbuild_shims();
|
|
5389
|
+
import {
|
|
5390
|
+
mkdirSync as mkdirSync3,
|
|
5391
|
+
readFileSync as readFileSync6,
|
|
5392
|
+
readdirSync as readdirSync4,
|
|
5393
|
+
statSync as statSync3,
|
|
5394
|
+
writeFileSync as writeFileSync3
|
|
5395
|
+
} from "node:fs";
|
|
5396
|
+
import { dirname as dirname3, join as join7, basename as basename4, resolve as resolve4 } from "node:path";
|
|
5397
|
+
function promptRecordDir(planPath) {
|
|
5398
|
+
const p = resolve4(planPath);
|
|
5399
|
+
return join7(dirname3(p), `${basename4(p).replace(/\.json$/i, "")}-prompts`);
|
|
5400
|
+
}
|
|
5401
|
+
__name(promptRecordDir, "promptRecordDir");
|
|
5402
|
+
var fileFor = /* @__PURE__ */ __name((key) => `${encodeURIComponent(key)}.txt`, "fileFor");
|
|
5403
|
+
function briefPath(planPath, key) {
|
|
5404
|
+
return join7(promptRecordDir(planPath), `${encodeURIComponent(key)}.brief.md`);
|
|
5405
|
+
}
|
|
5406
|
+
__name(briefPath, "briefPath");
|
|
5407
|
+
function findingsFilePath(planPath, key) {
|
|
5408
|
+
return join7(
|
|
5409
|
+
promptRecordDir(planPath),
|
|
5410
|
+
`${encodeURIComponent(key)}.findings.md`
|
|
5411
|
+
);
|
|
5412
|
+
}
|
|
5413
|
+
__name(findingsFilePath, "findingsFilePath");
|
|
5414
|
+
function findingsPointerOf(prompt) {
|
|
5415
|
+
const m = /^read_file\(file_path="([^"]*\.findings\.md)"\)$/m.exec(prompt);
|
|
5416
|
+
return m && m[1] !== void 0 ? m[1] : null;
|
|
5417
|
+
}
|
|
5418
|
+
__name(findingsPointerOf, "findingsPointerOf");
|
|
5050
5419
|
function writeFindingsFile(planPath, key, content) {
|
|
5051
5420
|
const p = findingsFilePath(planPath, key);
|
|
5052
5421
|
try {
|
|
@@ -5177,6 +5546,10 @@ __name(isRepositoryContextRoleId, "isRepositoryContextRoleId");
|
|
|
5177
5546
|
var REVERSE_AUDIT_EXAMPLE_RECEIPT = "No issues found \u2014 re-walked the reconnect state machine and the two changed exports' call sites; every gap I checked was already in the list";
|
|
5178
5547
|
var BRIEFS = {
|
|
5179
5548
|
"0": {
|
|
5549
|
+
// Budget-exempt: Issue-sized mandatory work, not diff-sized: a small bugfix
|
|
5550
|
+
// referencing many issues would exhaust a diff-derived ceiling on
|
|
5551
|
+
// required fetches alone.
|
|
5552
|
+
budgetExempt: true,
|
|
5180
5553
|
label: "Agent 0: Issue fidelity & root-cause ownership",
|
|
5181
5554
|
publicLabel: "the linked-issue fidelity pass",
|
|
5182
5555
|
publicLabelZh: "\u5173\u8054 issue \u4E00\u81F4\u6027\u68C0\u67E5",
|
|
@@ -5467,6 +5840,10 @@ Under that framing, look at:
|
|
|
5467
5840
|
You are undirected on purpose. Do not restrict yourself to the list.`
|
|
5468
5841
|
},
|
|
5469
5842
|
"7": {
|
|
5843
|
+
// Budget-exempt: Deterministic build/test commands — the run costs what the
|
|
5844
|
+
// project scripts cost, and stopping early is the one thing it must
|
|
5845
|
+
// never do.
|
|
5846
|
+
budgetExempt: true,
|
|
5470
5847
|
label: "Agent 7: Build & test verification",
|
|
5471
5848
|
publicLabel: "the build-and-test check",
|
|
5472
5849
|
publicLabelZh: "\u6784\u5EFA\u4E0E\u6D4B\u8BD5\u9A8C\u8BC1",
|
|
@@ -5551,6 +5928,9 @@ This file is largely rewritten, and reviewing it as a diff is the wrong frame. T
|
|
|
5551
5928
|
Report a **Critical** for each violation, and give **both** locations that together make it a bug (\`<file>:<lineA>\` and \`<file>:<lineB>\`), not just one.`
|
|
5552
5929
|
},
|
|
5553
5930
|
verify: {
|
|
5931
|
+
// Budget-exempt: Its per-finding re-trace must not stop early; `verifyShard`
|
|
5932
|
+
// already governs its load.
|
|
5933
|
+
budgetExempt: true,
|
|
5554
5934
|
reviewsCode: true,
|
|
5555
5935
|
output: "verdicts",
|
|
5556
5936
|
acceptsFindings: true,
|
|
@@ -5811,7 +6191,7 @@ import {
|
|
|
5811
6191
|
writeFileSync as writeFileSync4,
|
|
5812
6192
|
mkdirSync as mkdirSync4,
|
|
5813
6193
|
mkdtempSync,
|
|
5814
|
-
rmSync as
|
|
6194
|
+
rmSync as rmSync3,
|
|
5815
6195
|
lstatSync,
|
|
5816
6196
|
realpathSync as realpathSync2,
|
|
5817
6197
|
openSync,
|
|
@@ -6286,7 +6666,7 @@ function emptyHadolintConfig() {
|
|
|
6286
6666
|
const d = mkdtempSync(join8(tmpdir(), "qwen-review-hadolint-"));
|
|
6287
6667
|
process.on("exit", () => {
|
|
6288
6668
|
try {
|
|
6289
|
-
|
|
6669
|
+
rmSync3(d, { recursive: true, force: true });
|
|
6290
6670
|
} catch {
|
|
6291
6671
|
}
|
|
6292
6672
|
});
|
|
@@ -6831,31 +7211,182 @@ function writeBudgetStop(planPath, spent, round, nowMs = Date.now()) {
|
|
|
6831
7211
|
} catch {
|
|
6832
7212
|
}
|
|
6833
7213
|
}
|
|
6834
|
-
__name(writeBudgetStop, "writeBudgetStop");
|
|
6835
|
-
function readBudgetStop(planPath) {
|
|
6836
|
-
try {
|
|
6837
|
-
const raw = readFileSync8(
|
|
6838
|
-
join9(promptRecordDir(planPath), STOP_FILE),
|
|
6839
|
-
"utf8"
|
|
6840
|
-
);
|
|
6841
|
-
const parsed = JSON.parse(raw);
|
|
6842
|
-
if (typeof parsed !== "object" || parsed === null || typeof parsed.entry !== "string" || typeof parsed.atMs !== "number" || parsed.atMs < runEpochMs(planPath)) {
|
|
6843
|
-
return null;
|
|
7214
|
+
__name(writeBudgetStop, "writeBudgetStop");
|
|
7215
|
+
function readBudgetStop(planPath) {
|
|
7216
|
+
try {
|
|
7217
|
+
const raw = readFileSync8(
|
|
7218
|
+
join9(promptRecordDir(planPath), STOP_FILE),
|
|
7219
|
+
"utf8"
|
|
7220
|
+
);
|
|
7221
|
+
const parsed = JSON.parse(raw);
|
|
7222
|
+
if (typeof parsed !== "object" || parsed === null || typeof parsed.entry !== "string" || typeof parsed.atMs !== "number" || parsed.atMs < runEpochMs(planPath)) {
|
|
7223
|
+
return null;
|
|
7224
|
+
}
|
|
7225
|
+
return parsed;
|
|
7226
|
+
} catch {
|
|
7227
|
+
return null;
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
__name(readBudgetStop, "readBudgetStop");
|
|
7231
|
+
function reverseAuditBudgetMessage(spent, round) {
|
|
7232
|
+
const minutesLeft = Math.max(0, Math.floor(spent.remainingSeconds / 60));
|
|
7233
|
+
const reserveMinutes = Math.round(spent.reserveSeconds / 60);
|
|
7234
|
+
const roundMinutes = Math.round(spent.expectedRoundSeconds / 60);
|
|
7235
|
+
const which = round !== void 0 ? `round ${round}` : "the next round";
|
|
7236
|
+
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.`;
|
|
7237
|
+
}
|
|
7238
|
+
__name(reverseAuditBudgetMessage, "reverseAuditBudgetMessage");
|
|
7239
|
+
|
|
7240
|
+
// packages/cli/src/commands/review/lib/budget.ts
|
|
7241
|
+
init_esbuild_shims();
|
|
7242
|
+
var SWEEP_FLOOR = 25;
|
|
7243
|
+
var SPECIALIST_FLOOR = 80;
|
|
7244
|
+
var LINES_PER_ANGLE = 60;
|
|
7245
|
+
var MIN_INLINE_ANGLES = 3;
|
|
7246
|
+
var MAX_INLINE_ANGLES = 6;
|
|
7247
|
+
var VERIFY_SHARD = 8;
|
|
7248
|
+
var MIN_AGENT_TOOL_BUDGET = 30;
|
|
7249
|
+
var MAX_AGENT_TOOL_BUDGET = 60;
|
|
7250
|
+
var LINES_PER_TOOL_CALL = 20;
|
|
7251
|
+
function reviewBudget(input) {
|
|
7252
|
+
const src = sane(input.srcDiffLines);
|
|
7253
|
+
const total = sane(input.diffLines);
|
|
7254
|
+
const effective = Math.max(src, Math.floor(total / 8));
|
|
7255
|
+
const extraAngles = Math.floor(effective / LINES_PER_ANGLE);
|
|
7256
|
+
const inlineAngles = clamp(
|
|
7257
|
+
MIN_INLINE_ANGLES + extraAngles,
|
|
7258
|
+
MIN_INLINE_ANGLES,
|
|
7259
|
+
MAX_INLINE_ANGLES
|
|
7260
|
+
);
|
|
7261
|
+
return {
|
|
7262
|
+
inlineAngles,
|
|
7263
|
+
sweep: effective >= SWEEP_FLOOR,
|
|
7264
|
+
specialistCap: src >= SPECIALIST_FLOOR ? 2 : 0,
|
|
7265
|
+
verifyShard: VERIFY_SHARD,
|
|
7266
|
+
agentToolBudget: clamp(
|
|
7267
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(effective / LINES_PER_TOOL_CALL),
|
|
7268
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7269
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7270
|
+
)
|
|
7271
|
+
};
|
|
7272
|
+
}
|
|
7273
|
+
__name(reviewBudget, "reviewBudget");
|
|
7274
|
+
var MAX_TOTAL_TOOL_CALLS = 200;
|
|
7275
|
+
function launchToolBudget(planBudget, territoryLines, mandatoryReads) {
|
|
7276
|
+
const base = clamp(
|
|
7277
|
+
sane(planBudget) || MIN_AGENT_TOOL_BUDGET,
|
|
7278
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7279
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7280
|
+
);
|
|
7281
|
+
const allowance = territoryLines === null ? base : Math.min(
|
|
7282
|
+
base,
|
|
7283
|
+
clamp(
|
|
7284
|
+
MIN_AGENT_TOOL_BUDGET + Math.floor(sane(territoryLines) / LINES_PER_TOOL_CALL),
|
|
7285
|
+
MIN_AGENT_TOOL_BUDGET,
|
|
7286
|
+
MAX_AGENT_TOOL_BUDGET
|
|
7287
|
+
)
|
|
7288
|
+
);
|
|
7289
|
+
return Math.min(
|
|
7290
|
+
MAX_TOTAL_TOOL_CALLS,
|
|
7291
|
+
allowance + Math.max(0, Math.floor(sane(mandatoryReads)))
|
|
7292
|
+
);
|
|
7293
|
+
}
|
|
7294
|
+
__name(launchToolBudget, "launchToolBudget");
|
|
7295
|
+
var BUDGET_GAP_LINE_RE = /^[ \t]*(?:[-*+]|\d+[.)])?[ \t]*(`?)[*_~]{0,3}(?:budget gap|预算(?:缺口|不足|用尽))[*_~]{0,3}[ \t]*[::][*_~]{0,3}[ \t]*(.+?)[ \t]*$/i;
|
|
7296
|
+
var GAP_HINT_RE = /budget gap|预算(?:缺口|不足|用尽)/i;
|
|
7297
|
+
var INLINE_BUDGET_GAP_RE = /(?:budget gap|预算(?:缺口|不足|用尽))[*_~`]{0,3}[ \t]*[::]/i;
|
|
7298
|
+
var PLACEHOLDER_GAP_RE = /^(?:<[^>]*>|none\b.*|n\/a\b.*|nothing\b.*|no (?:gaps?|checks?)\b.*|[-—*_~`]+)$/i;
|
|
7299
|
+
var MAX_GAP_LENGTH = 160;
|
|
7300
|
+
var MAX_GAPS_PER_AGENT = 8;
|
|
7301
|
+
var DANGEROUS_CHARS_RE = (
|
|
7302
|
+
// eslint-disable-next-line no-control-regex
|
|
7303
|
+
/[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e]/g
|
|
7304
|
+
);
|
|
7305
|
+
var WRAPPER_PAIRS = [
|
|
7306
|
+
["**", "**"],
|
|
7307
|
+
["__", "__"],
|
|
7308
|
+
["*", "*"],
|
|
7309
|
+
["_", "_"],
|
|
7310
|
+
["~", "~"],
|
|
7311
|
+
["`", "`"]
|
|
7312
|
+
];
|
|
7313
|
+
function stripWrappers(s) {
|
|
7314
|
+
let out = s;
|
|
7315
|
+
let changed = true;
|
|
7316
|
+
while (changed) {
|
|
7317
|
+
changed = false;
|
|
7318
|
+
for (const [open, close] of WRAPPER_PAIRS) {
|
|
7319
|
+
if (out.length > open.length + close.length && out.startsWith(open) && out.endsWith(close)) {
|
|
7320
|
+
out = out.slice(open.length, out.length - close.length).trim();
|
|
7321
|
+
changed = true;
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
return out;
|
|
7326
|
+
}
|
|
7327
|
+
__name(stripWrappers, "stripWrappers");
|
|
7328
|
+
function truncateGap(s) {
|
|
7329
|
+
const points = [...s];
|
|
7330
|
+
return points.length > MAX_GAP_LENGTH ? `${points.slice(0, MAX_GAP_LENGTH).join("")}\u2026` : s;
|
|
7331
|
+
}
|
|
7332
|
+
__name(truncateGap, "truncateGap");
|
|
7333
|
+
function budgetGapDisclosures(finalText) {
|
|
7334
|
+
if (!GAP_HINT_RE.test(finalText)) return [];
|
|
7335
|
+
const gaps = [];
|
|
7336
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7337
|
+
let inFence = false;
|
|
7338
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7339
|
+
if (/^[ \t]*(?:```|~~~)/.test(line)) {
|
|
7340
|
+
inFence = !inFence;
|
|
7341
|
+
continue;
|
|
6844
7342
|
}
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
7343
|
+
if (inFence) continue;
|
|
7344
|
+
if (/^[ \t]*>/.test(line)) continue;
|
|
7345
|
+
const m = BUDGET_GAP_LINE_RE.exec(line.replace(DANGEROUS_CHARS_RE, " "));
|
|
7346
|
+
if (!m) continue;
|
|
7347
|
+
let raw = m[2] ?? "";
|
|
7348
|
+
if (m[1] === "`") {
|
|
7349
|
+
if (!raw.endsWith("`")) continue;
|
|
7350
|
+
raw = raw.slice(0, -1);
|
|
7351
|
+
}
|
|
7352
|
+
raw = stripWrappers(raw.trim()).trim();
|
|
7353
|
+
const normalized = raw.replace(/[.!…,;:\s]+$/, "").trim();
|
|
7354
|
+
if (normalized.length === 0 || PLACEHOLDER_GAP_RE.test(normalized)) {
|
|
7355
|
+
continue;
|
|
7356
|
+
}
|
|
7357
|
+
const key = normalized.toLowerCase();
|
|
7358
|
+
if (seen.has(key)) continue;
|
|
7359
|
+
seen.add(key);
|
|
7360
|
+
gaps.push(truncateGap(raw));
|
|
7361
|
+
if (gaps.length >= MAX_GAPS_PER_AGENT) break;
|
|
6848
7362
|
}
|
|
7363
|
+
return gaps;
|
|
6849
7364
|
}
|
|
6850
|
-
__name(
|
|
6851
|
-
function
|
|
6852
|
-
|
|
6853
|
-
const
|
|
6854
|
-
|
|
6855
|
-
const
|
|
6856
|
-
|
|
7365
|
+
__name(budgetGapDisclosures, "budgetGapDisclosures");
|
|
7366
|
+
function stripBudgetGapLines(finalText) {
|
|
7367
|
+
if (!GAP_HINT_RE.test(finalText)) return finalText;
|
|
7368
|
+
const kept = [];
|
|
7369
|
+
let inFence = false;
|
|
7370
|
+
for (const line of finalText.split(/\r?\n/)) {
|
|
7371
|
+
const fence = /^[ \t]*(?:```|~~~)/.test(line);
|
|
7372
|
+
if (fence) inFence = !inFence;
|
|
7373
|
+
if (!fence && !inFence && !/^[ \t]*>/.test(line) && BUDGET_GAP_LINE_RE.test(line)) {
|
|
7374
|
+
continue;
|
|
7375
|
+
}
|
|
7376
|
+
kept.push(line);
|
|
7377
|
+
}
|
|
7378
|
+
return kept.join("\n");
|
|
6857
7379
|
}
|
|
6858
|
-
__name(
|
|
7380
|
+
__name(stripBudgetGapLines, "stripBudgetGapLines");
|
|
7381
|
+
function sane(n) {
|
|
7382
|
+
const v = Number(n);
|
|
7383
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 0;
|
|
7384
|
+
}
|
|
7385
|
+
__name(sane, "sane");
|
|
7386
|
+
function clamp(v, lo, hi) {
|
|
7387
|
+
return Math.min(hi, Math.max(lo, v));
|
|
7388
|
+
}
|
|
7389
|
+
__name(clamp, "clamp");
|
|
6859
7390
|
|
|
6860
7391
|
// packages/cli/src/commands/review/lib/shell-quote.ts
|
|
6861
7392
|
init_esbuild_shims();
|
|
@@ -7001,6 +7532,37 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
7001
7532
|
return false;
|
|
7002
7533
|
}, "keySatisfied");
|
|
7003
7534
|
const superseded = /* @__PURE__ */ __name((rec, chunk2) => chunk2 !== null ? chunkSatisfied(chunk2, rec) : keySatisfied(rec), "superseded");
|
|
7535
|
+
const gapsMemo = /* @__PURE__ */ new Map();
|
|
7536
|
+
const gapsOf = /* @__PURE__ */ __name((rec) => {
|
|
7537
|
+
let g = gapsMemo.get(rec);
|
|
7538
|
+
if (g === void 0) {
|
|
7539
|
+
g = budgetGapDisclosures(rec.finalText);
|
|
7540
|
+
gapsMemo.set(rec, g);
|
|
7541
|
+
}
|
|
7542
|
+
return g;
|
|
7543
|
+
}, "gapsOf");
|
|
7544
|
+
const gapsSuperseded = /* @__PURE__ */ __name((rec, chunk2) => {
|
|
7545
|
+
if (chunk2 !== null) {
|
|
7546
|
+
const b = builtOf(`chunk-${chunk2}`);
|
|
7547
|
+
if (b === void 0) return false;
|
|
7548
|
+
return records.some(
|
|
7549
|
+
(r) => r !== rec && assignedChunk(r) === chunk2 && wasDeliveredVerbatim(r.launchPrompt, b) && r.diffToolCalls > 0 && gapsOf(r).length === 0
|
|
7550
|
+
);
|
|
7551
|
+
}
|
|
7552
|
+
for (const key of built.keys()) {
|
|
7553
|
+
const b = builtOf(key);
|
|
7554
|
+
if (b === void 0) continue;
|
|
7555
|
+
if (!wasDeliveredVerbatim(rec.launchPrompt, b)) continue;
|
|
7556
|
+
const needle = JSON.stringify(briefPath(planPath, key));
|
|
7557
|
+
if (records.some(
|
|
7558
|
+
(r) => r !== rec && wasDeliveredVerbatim(r.launchPrompt, b) && r.successfulCallArgs.some((a) => a.includes(needle)) && gapsOf(r).length === 0
|
|
7559
|
+
)) {
|
|
7560
|
+
return true;
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
return false;
|
|
7564
|
+
}, "gapsSuperseded");
|
|
7565
|
+
const budgetGaps = [];
|
|
7004
7566
|
for (const rec of records) {
|
|
7005
7567
|
const chunk2 = assignedChunk(rec);
|
|
7006
7568
|
const name = label(rec, chunk2);
|
|
@@ -7058,6 +7620,10 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
7058
7620
|
}
|
|
7059
7621
|
continue;
|
|
7060
7622
|
}
|
|
7623
|
+
const gaps = gapsOf(rec);
|
|
7624
|
+
if (gaps.length > 0 && !gapsSuperseded(rec, chunk2)) {
|
|
7625
|
+
budgetGaps.push({ agent: name, gaps });
|
|
7626
|
+
}
|
|
7061
7627
|
const ranges = merge([...told, ...rec.diffReads]);
|
|
7062
7628
|
if (ranges.length === 0) continue;
|
|
7063
7629
|
const u = UNCOVERABLE_RE.exec(rec.finalText);
|
|
@@ -7215,6 +7781,7 @@ function coverageFromTranscripts(planPath, env = process.env) {
|
|
|
7215
7781
|
unreadBriefs,
|
|
7216
7782
|
missingChunks,
|
|
7217
7783
|
uncoverableChunks: [...uncoverable].sort((a, b) => a - b),
|
|
7784
|
+
budgetGaps,
|
|
7218
7785
|
coveredChunks: [...covered].sort((a, b) => a - b),
|
|
7219
7786
|
plannedChunks: plan.chunks.map((c) => ({
|
|
7220
7787
|
id: c.id,
|
|
@@ -7351,223 +7918,89 @@ function verificationGaps(planPath, opts, env = process.env) {
|
|
|
7351
7918
|
if (gotTheBuiltPrompt.length > 0) return "brief-unread";
|
|
7352
7919
|
if (records.some(opened)) return "rewritten";
|
|
7353
7920
|
return "not-launched";
|
|
7354
|
-
}, "deliveryOf");
|
|
7355
|
-
const bestDelivery = /* @__PURE__ */ __name((keys) => {
|
|
7356
|
-
if (keys.length === 0) return "not-built";
|
|
7357
|
-
const rank = {
|
|
7358
|
-
ok: 0,
|
|
7359
|
-
"findings-unread": 1,
|
|
7360
|
-
"brief-unread": 2,
|
|
7361
|
-
rewritten: 3,
|
|
7362
|
-
"not-launched": 4,
|
|
7363
|
-
"not-built": 5
|
|
7364
|
-
};
|
|
7365
|
-
return keys.map(deliveryOf).sort((a, b) => rank[a] - rank[b])[0];
|
|
7366
|
-
}, "bestDelivery");
|
|
7367
|
-
const reverseKeys = [...built.keys()].filter(
|
|
7368
|
-
(k) => k === "reverse-audit" || k.startsWith("reverse-audit--")
|
|
7369
|
-
);
|
|
7370
|
-
const reverse = bestDelivery(reverseKeys);
|
|
7371
|
-
const budgetStopped = readBudgetStop(planPath) !== null;
|
|
7372
|
-
const reverseByDesign = budgetStopped && reverse === "not-built";
|
|
7373
|
-
const reverseGap = !balancedMedium && !reverseByDesign && reverse !== "ok";
|
|
7374
|
-
if (reverseGap) {
|
|
7375
|
-
remediation.push(
|
|
7376
|
-
`reverse audit: ${REVERSE_AUDIT_GAP[reverse].fix.replace(
|
|
7377
|
-
"--plan <plan>",
|
|
7378
|
-
() => `--plan ${shellQuotePath(planPath)}`
|
|
7379
|
-
)}`
|
|
7380
|
-
);
|
|
7381
|
-
}
|
|
7382
|
-
let unverifiedFindings = false;
|
|
7383
|
-
let verify = null;
|
|
7384
|
-
if (opts.postsFindings) {
|
|
7385
|
-
const verifyKeys = [...built.keys()].filter(
|
|
7386
|
-
(k) => k === "verify" || k.startsWith("verify--")
|
|
7387
|
-
);
|
|
7388
|
-
verify = bestDelivery(verifyKeys);
|
|
7389
|
-
if (verify !== "ok") {
|
|
7390
|
-
unverifiedFindings = true;
|
|
7391
|
-
remediation.push(
|
|
7392
|
-
`verification: ${VERIFY_GAP[verify].fix.replace(
|
|
7393
|
-
"--plan <plan>",
|
|
7394
|
-
// A function replacer: a plain string gives `$&`/`$\`` special
|
|
7395
|
-
// meaning, and a path is not a place for replacement patterns.
|
|
7396
|
-
() => `--plan ${shellQuotePath(planPath)}`
|
|
7397
|
-
)}`
|
|
7398
|
-
);
|
|
7399
|
-
}
|
|
7400
|
-
}
|
|
7401
|
-
if (reverseGap && verify !== null && verify === reverse) {
|
|
7402
|
-
gaps.push({
|
|
7403
|
-
subject: "verification and reverse audit",
|
|
7404
|
-
reason: COMBINED_STEP45_GAP[reverse].en,
|
|
7405
|
-
subjectZh: "\u9A8C\u8BC1\u4E0E\u53CD\u5411\u5BA1\u8BA1",
|
|
7406
|
-
reasonZh: COMBINED_STEP45_GAP[reverse].zh
|
|
7407
|
-
});
|
|
7408
|
-
} else {
|
|
7409
|
-
if (reverseGap) {
|
|
7410
|
-
gaps.push({
|
|
7411
|
-
subject: "reverse audit",
|
|
7412
|
-
reason: REVERSE_AUDIT_GAP[reverse].gap,
|
|
7413
|
-
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7414
|
-
reasonZh: REVERSE_AUDIT_GAP[reverse].gapZh
|
|
7415
|
-
});
|
|
7416
|
-
}
|
|
7417
|
-
if (verify !== null && verify !== "ok") {
|
|
7418
|
-
gaps.push({
|
|
7419
|
-
subject: "verification",
|
|
7420
|
-
reason: VERIFY_GAP[verify].gap,
|
|
7421
|
-
subjectZh: "\u9A8C\u8BC1",
|
|
7422
|
-
reasonZh: VERIFY_GAP[verify].gapZh
|
|
7423
|
-
});
|
|
7424
|
-
}
|
|
7425
|
-
}
|
|
7426
|
-
if (balancedMedium) {
|
|
7427
|
-
gaps.push({
|
|
7428
|
-
subject: "reverse audit",
|
|
7429
|
-
reason: "not run \u2014 the balanced (medium) tier skips the second-look pass, so this verdict is capped at Comment rather than Approve",
|
|
7430
|
-
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7431
|
-
reasonZh: "\u672A\u8FD0\u884C\u2014\u2014\u5747\u8861\uFF08medium\uFF09\u6863\u8DF3\u8FC7\u4E8C\u6B21\u5BA1\u67E5\u6B65\u9AA4\uFF0C\u56E0\u6B64\u672C\u6B21\u5224\u5B9A\u4E0A\u9650\u4E3A Comment\uFF0C\u4E0D\u4F1A Approve"
|
|
7432
|
-
});
|
|
7433
|
-
}
|
|
7434
|
-
return { ok: gaps.length === 0, gaps, remediation, unverifiedFindings };
|
|
7435
|
-
}
|
|
7436
|
-
__name(verificationGaps, "verificationGaps");
|
|
7437
|
-
|
|
7438
|
-
// packages/cli/src/commands/review/lib/gh.ts
|
|
7439
|
-
init_esbuild_shims();
|
|
7440
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
7441
|
-
var MAX_RETRIES = 2;
|
|
7442
|
-
var BASE_DELAY_MS = 3e3;
|
|
7443
|
-
function sleepSync(ms) {
|
|
7444
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
7445
|
-
}
|
|
7446
|
-
__name(sleepSync, "sleepSync");
|
|
7447
|
-
var TRANSIENT_RE = /HTTP 5\d{2}|server is currently unavailable|service unavailable|bad gateway|internal server error/i;
|
|
7448
|
-
function isTransientGhError(err) {
|
|
7449
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
7450
|
-
const msg = err instanceof Error ? err.message : "";
|
|
7451
|
-
return TRANSIENT_RE.test(stderr) || TRANSIENT_RE.test(msg);
|
|
7452
|
-
}
|
|
7453
|
-
__name(isTransientGhError, "isTransientGhError");
|
|
7454
|
-
function execGhWithRetry(args, options) {
|
|
7455
|
-
const execOptions = {
|
|
7456
|
-
encoding: "utf8",
|
|
7457
|
-
maxBuffer: 64 * 1024 * 1024,
|
|
7458
|
-
env: ghEnv(),
|
|
7459
|
-
...options.input !== void 0 ? { input: options.input } : {}
|
|
7460
|
-
};
|
|
7461
|
-
for (let attempt = 0; ; attempt++) {
|
|
7462
|
-
try {
|
|
7463
|
-
return execFileSync2("gh", args, execOptions).replace(/\r\n/g, "\n").trim();
|
|
7464
|
-
} catch (err) {
|
|
7465
|
-
if (attempt < MAX_RETRIES && isTransientGhError(err)) {
|
|
7466
|
-
const delay = BASE_DELAY_MS * (attempt + 1);
|
|
7467
|
-
process.stderr.write(
|
|
7468
|
-
`gh transient error (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms\u2026
|
|
7469
|
-
`
|
|
7470
|
-
);
|
|
7471
|
-
sleepSync(delay);
|
|
7472
|
-
continue;
|
|
7473
|
-
}
|
|
7474
|
-
throw err;
|
|
7475
|
-
}
|
|
7476
|
-
}
|
|
7477
|
-
}
|
|
7478
|
-
__name(execGhWithRetry, "execGhWithRetry");
|
|
7479
|
-
var ghHost;
|
|
7480
|
-
var HOSTNAME_RE = /^[A-Za-z0-9.-]+(?::\d+)?$/;
|
|
7481
|
-
function setGhHost(host) {
|
|
7482
|
-
if (host === void 0 || host === "") {
|
|
7483
|
-
ghHost = void 0;
|
|
7484
|
-
return;
|
|
7485
|
-
}
|
|
7486
|
-
if (!HOSTNAME_RE.test(host)) {
|
|
7487
|
-
throw new TypeError(
|
|
7488
|
-
`--host must be a hostname (optionally :port), got ${JSON.stringify(host)}`
|
|
7489
|
-
);
|
|
7490
|
-
}
|
|
7491
|
-
ghHost = host;
|
|
7492
|
-
}
|
|
7493
|
-
__name(setGhHost, "setGhHost");
|
|
7494
|
-
function getGhHost() {
|
|
7495
|
-
return ghHost;
|
|
7496
|
-
}
|
|
7497
|
-
__name(getGhHost, "getGhHost");
|
|
7498
|
-
function ghEnv() {
|
|
7499
|
-
return ghHost ? { ...process.env, GH_HOST: ghHost } : void 0;
|
|
7500
|
-
}
|
|
7501
|
-
__name(ghEnv, "ghEnv");
|
|
7502
|
-
function gh(...args) {
|
|
7503
|
-
return execGhWithRetry(args, {});
|
|
7504
|
-
}
|
|
7505
|
-
__name(gh, "gh");
|
|
7506
|
-
function ghWithInputRetried(input, ...args) {
|
|
7507
|
-
return execGhWithRetry(args, { input });
|
|
7508
|
-
}
|
|
7509
|
-
__name(ghWithInputRetried, "ghWithInputRetried");
|
|
7510
|
-
function ghWithInput(input, ...args) {
|
|
7511
|
-
return execFileSync2("gh", args, {
|
|
7512
|
-
encoding: "utf8",
|
|
7513
|
-
maxBuffer: 64 * 1024 * 1024,
|
|
7514
|
-
env: ghEnv(),
|
|
7515
|
-
input
|
|
7516
|
-
}).replace(/\r\n/g, "\n").trim();
|
|
7517
|
-
}
|
|
7518
|
-
__name(ghWithInput, "ghWithInput");
|
|
7519
|
-
function ghApiAll(path3) {
|
|
7520
|
-
const out = gh("api", "--paginate", path3);
|
|
7521
|
-
if (!out) return [];
|
|
7522
|
-
const parsed = JSON.parse(out);
|
|
7523
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
7524
|
-
}
|
|
7525
|
-
__name(ghApiAll, "ghApiAll");
|
|
7526
|
-
function ghApiAllNested(path3, key) {
|
|
7527
|
-
return parseNdjson(gh("api", "--paginate", path3, "--jq", `.${key}[]`), {
|
|
7528
|
-
strict: true
|
|
7529
|
-
});
|
|
7530
|
-
}
|
|
7531
|
-
__name(ghApiAllNested, "ghApiAllNested");
|
|
7532
|
-
function parseNdjson(out, opts = {}) {
|
|
7533
|
-
const strict = opts.strict ?? true;
|
|
7534
|
-
if (!out) return [];
|
|
7535
|
-
const values = [];
|
|
7536
|
-
for (const line of out.split("\n")) {
|
|
7537
|
-
if (line.trim().length === 0) continue;
|
|
7538
|
-
if (strict) {
|
|
7539
|
-
values.push(JSON.parse(line));
|
|
7540
|
-
continue;
|
|
7541
|
-
}
|
|
7542
|
-
try {
|
|
7543
|
-
values.push(JSON.parse(line));
|
|
7544
|
-
} catch {
|
|
7545
|
-
}
|
|
7921
|
+
}, "deliveryOf");
|
|
7922
|
+
const bestDelivery = /* @__PURE__ */ __name((keys) => {
|
|
7923
|
+
if (keys.length === 0) return "not-built";
|
|
7924
|
+
const rank = {
|
|
7925
|
+
ok: 0,
|
|
7926
|
+
"findings-unread": 1,
|
|
7927
|
+
"brief-unread": 2,
|
|
7928
|
+
rewritten: 3,
|
|
7929
|
+
"not-launched": 4,
|
|
7930
|
+
"not-built": 5
|
|
7931
|
+
};
|
|
7932
|
+
return keys.map(deliveryOf).sort((a, b) => rank[a] - rank[b])[0];
|
|
7933
|
+
}, "bestDelivery");
|
|
7934
|
+
const reverseKeys = [...built.keys()].filter(
|
|
7935
|
+
(k) => k === "reverse-audit" || k.startsWith("reverse-audit--")
|
|
7936
|
+
);
|
|
7937
|
+
const reverse = bestDelivery(reverseKeys);
|
|
7938
|
+
const budgetStopped = readBudgetStop(planPath) !== null;
|
|
7939
|
+
const reverseByDesign = budgetStopped && reverse === "not-built";
|
|
7940
|
+
const reverseGap = !balancedMedium && !reverseByDesign && reverse !== "ok";
|
|
7941
|
+
if (reverseGap) {
|
|
7942
|
+
remediation.push(
|
|
7943
|
+
`reverse audit: ${REVERSE_AUDIT_GAP[reverse].fix.replace(
|
|
7944
|
+
"--plan <plan>",
|
|
7945
|
+
() => `--plan ${shellQuotePath(planPath)}`
|
|
7946
|
+
)}`
|
|
7947
|
+
);
|
|
7546
7948
|
}
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
}
|
|
7564
|
-
throw new Error(
|
|
7565
|
-
"gh CLI is not authenticated. Run `gh auth login` and retry."
|
|
7949
|
+
let unverifiedFindings = false;
|
|
7950
|
+
let verify = null;
|
|
7951
|
+
if (opts.postsFindings) {
|
|
7952
|
+
const verifyKeys = [...built.keys()].filter(
|
|
7953
|
+
(k) => k === "verify" || k.startsWith("verify--")
|
|
7954
|
+
);
|
|
7955
|
+
verify = bestDelivery(verifyKeys);
|
|
7956
|
+
if (verify !== "ok") {
|
|
7957
|
+
unverifiedFindings = true;
|
|
7958
|
+
remediation.push(
|
|
7959
|
+
`verification: ${VERIFY_GAP[verify].fix.replace(
|
|
7960
|
+
"--plan <plan>",
|
|
7961
|
+
// A function replacer: a plain string gives `$&`/`$\`` special
|
|
7962
|
+
// meaning, and a path is not a place for replacement patterns.
|
|
7963
|
+
() => `--plan ${shellQuotePath(planPath)}`
|
|
7964
|
+
)}`
|
|
7566
7965
|
);
|
|
7567
7966
|
}
|
|
7568
7967
|
}
|
|
7968
|
+
if (reverseGap && verify !== null && verify === reverse) {
|
|
7969
|
+
gaps.push({
|
|
7970
|
+
subject: "verification and reverse audit",
|
|
7971
|
+
reason: COMBINED_STEP45_GAP[reverse].en,
|
|
7972
|
+
subjectZh: "\u9A8C\u8BC1\u4E0E\u53CD\u5411\u5BA1\u8BA1",
|
|
7973
|
+
reasonZh: COMBINED_STEP45_GAP[reverse].zh
|
|
7974
|
+
});
|
|
7975
|
+
} else {
|
|
7976
|
+
if (reverseGap) {
|
|
7977
|
+
gaps.push({
|
|
7978
|
+
subject: "reverse audit",
|
|
7979
|
+
reason: REVERSE_AUDIT_GAP[reverse].gap,
|
|
7980
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7981
|
+
reasonZh: REVERSE_AUDIT_GAP[reverse].gapZh
|
|
7982
|
+
});
|
|
7983
|
+
}
|
|
7984
|
+
if (verify !== null && verify !== "ok") {
|
|
7985
|
+
gaps.push({
|
|
7986
|
+
subject: "verification",
|
|
7987
|
+
reason: VERIFY_GAP[verify].gap,
|
|
7988
|
+
subjectZh: "\u9A8C\u8BC1",
|
|
7989
|
+
reasonZh: VERIFY_GAP[verify].gapZh
|
|
7990
|
+
});
|
|
7991
|
+
}
|
|
7992
|
+
}
|
|
7993
|
+
if (balancedMedium) {
|
|
7994
|
+
gaps.push({
|
|
7995
|
+
subject: "reverse audit",
|
|
7996
|
+
reason: "not run \u2014 the balanced (medium) tier skips the second-look pass, so this verdict is capped at Comment rather than Approve",
|
|
7997
|
+
subjectZh: "\u53CD\u5411\u5BA1\u8BA1",
|
|
7998
|
+
reasonZh: "\u672A\u8FD0\u884C\u2014\u2014\u5747\u8861\uFF08medium\uFF09\u6863\u8DF3\u8FC7\u4E8C\u6B21\u5BA1\u67E5\u6B65\u9AA4\uFF0C\u56E0\u6B64\u672C\u6B21\u5224\u5B9A\u4E0A\u9650\u4E3A Comment\uFF0C\u4E0D\u4F1A Approve"
|
|
7999
|
+
});
|
|
8000
|
+
}
|
|
8001
|
+
return { ok: gaps.length === 0, gaps, remediation, unverifiedFindings };
|
|
7569
8002
|
}
|
|
7570
|
-
__name(
|
|
8003
|
+
__name(verificationGaps, "verificationGaps");
|
|
7571
8004
|
|
|
7572
8005
|
// packages/cli/src/commands/review/lib/ledger.ts
|
|
7573
8006
|
init_esbuild_shims();
|
|
@@ -7812,6 +8245,8 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7812
8245
|
}
|
|
7813
8246
|
}
|
|
7814
8247
|
const remediation = [];
|
|
8248
|
+
const budgetGapNotes = [];
|
|
8249
|
+
const MAX_BUDGET_GAP_LINES = 5;
|
|
7815
8250
|
const planRef = input.planPath ? shellQuotePath(input.planPath) : "<plan>";
|
|
7816
8251
|
const missingReceipts = [];
|
|
7817
8252
|
let plannedChunks = [];
|
|
@@ -7890,6 +8325,7 @@ function composeReviewBody(input, cliVersion) {
|
|
|
7890
8325
|
"agents that never opened the diff: relaunch each with the same printed prompt \u2014 the prompt already names the diff and its ranges; the read is what proves the review happened"
|
|
7891
8326
|
);
|
|
7892
8327
|
}
|
|
8328
|
+
budgetGapNotes.push(...cov.budgetGaps);
|
|
7893
8329
|
coverageEntries.push(...cov.disclosures);
|
|
7894
8330
|
if (cov.rewrittenPrompts.length > 0) {
|
|
7895
8331
|
remediation.push(
|
|
@@ -8127,6 +8563,23 @@ ${footer}`;
|
|
|
8127
8563
|
zh: `\u672A\u5BA1\u67E5\uFF1A${d}\u3002`
|
|
8128
8564
|
});
|
|
8129
8565
|
}
|
|
8566
|
+
const budgetGapItems = [];
|
|
8567
|
+
for (const g of budgetGapNotes) {
|
|
8568
|
+
for (const gap of g.gaps) budgetGapItems.push({ agent: g.agent, gap });
|
|
8569
|
+
}
|
|
8570
|
+
const keptBudgetGaps = budgetGapItems.filter(
|
|
8571
|
+
(it) => !unreviewed.some((d) => d.includes(it.gap))
|
|
8572
|
+
);
|
|
8573
|
+
if (keptBudgetGaps.length > 0) {
|
|
8574
|
+
const shown = keptBudgetGaps.slice(0, MAX_BUDGET_GAP_LINES);
|
|
8575
|
+
const more = keptBudgetGaps.length - shown.length;
|
|
8576
|
+
const enList = shown.map((it) => `${it.agent}: ${mdField(it.gap)}`).join("; ") + (more > 0 ? `, and ${more} more` : "");
|
|
8577
|
+
const zhList = shown.map((it) => `${it.agent}\uFF1A${mdField(it.gap)}`).join("\uFF1B") + (more > 0 ? `\uFF0C\u53E6\u6709 ${more} \u6761` : "");
|
|
8578
|
+
notReviewedParts.push({
|
|
8579
|
+
en: `Not explored to full depth (tool budget reached): ${enList}.`,
|
|
8580
|
+
zh: `\u672A\u63A2\u7D22\u5230\u5168\u90E8\u6DF1\u5EA6\uFF08\u8FBE\u5230\u5DE5\u5177\u8C03\u7528\u9884\u7B97\uFF09\uFF1A${zhList}\u3002`
|
|
8581
|
+
});
|
|
8582
|
+
}
|
|
8130
8583
|
const seenSubjects = /* @__PURE__ */ new Set();
|
|
8131
8584
|
const byReason = /* @__PURE__ */ new Map();
|
|
8132
8585
|
const reasonZhOf = /* @__PURE__ */ new Map();
|
|
@@ -8234,11 +8687,12 @@ ${footer}`;
|
|
|
8234
8687
|
body: render(
|
|
8235
8688
|
[
|
|
8236
8689
|
{ en: "No issues found. LGTM! \u2705", zh: "\u672A\u53D1\u73B0\u95EE\u9898\u3002LGTM\uFF01\u2705" },
|
|
8690
|
+
...notReviewedParts,
|
|
8237
8691
|
...deferredBlock,
|
|
8238
8692
|
...testPlanBlock,
|
|
8239
8693
|
...repositoryContextBlock2
|
|
8240
8694
|
],
|
|
8241
|
-
deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8695
|
+
notReviewedParts.length || deferredBlock.length || testPlanBlock.length || repositoryContextBlock2.length ? "\n\n" : " "
|
|
8242
8696
|
),
|
|
8243
8697
|
baseEvent,
|
|
8244
8698
|
cappedBy,
|
|
@@ -8264,7 +8718,12 @@ ${footer}`;
|
|
|
8264
8718
|
// body could open "Reviewed — no blockers." two lines above "nobody read
|
|
8265
8719
|
// them." Nothing nobody read can be certified blocker-free — and neither
|
|
8266
8720
|
// can a loop that ended with findings no verifier ever ruled on.
|
|
8267
|
-
missingReceipts.length === 0 &&
|
|
8721
|
+
missingReceipts.length === 0 && // A disclosed budget gap is not a blocker, but "Reviewed — no
|
|
8722
|
+
// blockers." two lines above "Not explored to full depth" is the
|
|
8723
|
+
// opener certifying what the disclosure takes back — the exact
|
|
8724
|
+
// shape the comment below forbids. (A gap the caller promoted into
|
|
8725
|
+
// `unreviewedDimensions` already denies certification above.)
|
|
8726
|
+
keptBudgetGaps.length === 0 && !findingsUnverifiedAtCompose;
|
|
8268
8727
|
const disclosedChunkIds = /* @__PURE__ */ new Set();
|
|
8269
8728
|
for (const e of coverageEntries) {
|
|
8270
8729
|
const m = /^chunk (\d+)$/.exec(e.subject);
|
|
@@ -8696,7 +9155,7 @@ __name(verdictLine, "verdictLine");
|
|
|
8696
9155
|
|
|
8697
9156
|
// packages/cli/src/commands/review/findings.ts
|
|
8698
9157
|
init_esbuild_shims();
|
|
8699
|
-
import { existsSync as
|
|
9158
|
+
import { existsSync as existsSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
8700
9159
|
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
8701
9160
|
var SEVERITIES = ["Critical", "Suggestion", "Nice to have"];
|
|
8702
9161
|
var CONFIDENCES = ["high", "low"];
|
|
@@ -9119,7 +9578,7 @@ var findingsCommand = {
|
|
|
9119
9578
|
let readjudicated = [];
|
|
9120
9579
|
if (testDelta !== void 0) {
|
|
9121
9580
|
let measurement;
|
|
9122
|
-
if (
|
|
9581
|
+
if (existsSync5(resolve6(testDelta))) {
|
|
9123
9582
|
try {
|
|
9124
9583
|
measurement = readJson(testDelta, "test-delta");
|
|
9125
9584
|
} catch (err) {
|
|
@@ -9176,88 +9635,6 @@ import { execFileSync as execFileSync4 } from "node:child_process";
|
|
|
9176
9635
|
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
9177
9636
|
import { dirname as dirname7, resolve as resolve7 } from "node:path";
|
|
9178
9637
|
|
|
9179
|
-
// packages/cli/src/commands/review/lib/git.ts
|
|
9180
|
-
init_esbuild_shims();
|
|
9181
|
-
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
9182
|
-
import { existsSync as existsSync5, rmSync as rmSync3 } from "node:fs";
|
|
9183
|
-
var GIT_TIMEOUT_MS2 = 12e4;
|
|
9184
|
-
function gitOpts() {
|
|
9185
|
-
return {
|
|
9186
|
-
timeout: GIT_TIMEOUT_MS2,
|
|
9187
|
-
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
9188
|
-
};
|
|
9189
|
-
}
|
|
9190
|
-
__name(gitOpts, "gitOpts");
|
|
9191
|
-
function git(...args) {
|
|
9192
|
-
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8" }).replace(/\r\n/g, "\n").trim();
|
|
9193
|
-
}
|
|
9194
|
-
__name(git, "git");
|
|
9195
|
-
function gitWithInput(input, args) {
|
|
9196
|
-
return execFileSync3("git", args, { ...gitOpts(), encoding: "utf8", input }).replace(/\r\n/g, "\n").trim();
|
|
9197
|
-
}
|
|
9198
|
-
__name(gitWithInput, "gitWithInput");
|
|
9199
|
-
function gitOpt(...args) {
|
|
9200
|
-
try {
|
|
9201
|
-
return execFileSync3("git", args, {
|
|
9202
|
-
...gitOpts(),
|
|
9203
|
-
encoding: "utf8",
|
|
9204
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
9205
|
-
}).replace(/\r\n/g, "\n").trim();
|
|
9206
|
-
} catch {
|
|
9207
|
-
return null;
|
|
9208
|
-
}
|
|
9209
|
-
}
|
|
9210
|
-
__name(gitOpt, "gitOpt");
|
|
9211
|
-
function refExists(ref) {
|
|
9212
|
-
return gitOpt("rev-parse", "--verify", "--quiet", ref) !== null;
|
|
9213
|
-
}
|
|
9214
|
-
__name(refExists, "refExists");
|
|
9215
|
-
function worktreeReleaseResult(existed, stillThere, removeError) {
|
|
9216
|
-
const freed = existed && !stillThere;
|
|
9217
|
-
if (!existed || freed) {
|
|
9218
|
-
return { existed, freed, reason: void 0 };
|
|
9219
|
-
}
|
|
9220
|
-
return {
|
|
9221
|
-
existed,
|
|
9222
|
-
freed,
|
|
9223
|
-
reason: removeError ? removeError instanceof Error ? removeError.message : String(removeError) : "the path is still there after `git worktree remove --force` and `rm -rf`"
|
|
9224
|
-
};
|
|
9225
|
-
}
|
|
9226
|
-
__name(worktreeReleaseResult, "worktreeReleaseResult");
|
|
9227
|
-
function releaseWorktree(worktreePath2) {
|
|
9228
|
-
const existed = existsSync5(worktreePath2);
|
|
9229
|
-
let removeError;
|
|
9230
|
-
if (existed) {
|
|
9231
|
-
gitOpt("worktree", "remove", worktreePath2, "--force");
|
|
9232
|
-
try {
|
|
9233
|
-
rmSync3(worktreePath2, { recursive: true, force: true });
|
|
9234
|
-
} catch (e) {
|
|
9235
|
-
removeError = e;
|
|
9236
|
-
}
|
|
9237
|
-
}
|
|
9238
|
-
gitOpt("worktree", "prune");
|
|
9239
|
-
return worktreeReleaseResult(existed, existsSync5(worktreePath2), removeError);
|
|
9240
|
-
}
|
|
9241
|
-
__name(releaseWorktree, "releaseWorktree");
|
|
9242
|
-
function gitRaw(...args) {
|
|
9243
|
-
return execFileSync3("git", args, {
|
|
9244
|
-
...gitOpts(),
|
|
9245
|
-
maxBuffer: 512 * 1024 * 1024,
|
|
9246
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
9247
|
-
});
|
|
9248
|
-
}
|
|
9249
|
-
__name(gitRaw, "gitRaw");
|
|
9250
|
-
function gitRawTolerateDiff(...args) {
|
|
9251
|
-
try {
|
|
9252
|
-
return gitRaw(...args);
|
|
9253
|
-
} catch (err) {
|
|
9254
|
-
const e = err;
|
|
9255
|
-
if (e.status === 1 && e.stdout && e.stdout.length > 0) return e.stdout;
|
|
9256
|
-
throw err;
|
|
9257
|
-
}
|
|
9258
|
-
}
|
|
9259
|
-
__name(gitRawTolerateDiff, "gitRawTolerateDiff");
|
|
9260
|
-
|
|
9261
9638
|
// packages/cli/src/commands/review/lib/diff-flags.ts
|
|
9262
9639
|
init_esbuild_shims();
|
|
9263
9640
|
var PINNED_DIFF_CONFIG = [
|
|
@@ -9323,42 +9700,6 @@ function classifyHeavy(input) {
|
|
|
9323
9700
|
}
|
|
9324
9701
|
__name(classifyHeavy, "classifyHeavy");
|
|
9325
9702
|
|
|
9326
|
-
// packages/cli/src/commands/review/lib/budget.ts
|
|
9327
|
-
init_esbuild_shims();
|
|
9328
|
-
var SWEEP_FLOOR = 25;
|
|
9329
|
-
var SPECIALIST_FLOOR = 80;
|
|
9330
|
-
var LINES_PER_ANGLE = 60;
|
|
9331
|
-
var MIN_INLINE_ANGLES = 3;
|
|
9332
|
-
var MAX_INLINE_ANGLES = 6;
|
|
9333
|
-
var VERIFY_SHARD = 8;
|
|
9334
|
-
function reviewBudget(input) {
|
|
9335
|
-
const src = sane(input.srcDiffLines);
|
|
9336
|
-
const total = sane(input.diffLines);
|
|
9337
|
-
const effective = Math.max(src, Math.floor(total / 8));
|
|
9338
|
-
const extraAngles = Math.floor(effective / LINES_PER_ANGLE);
|
|
9339
|
-
const inlineAngles = clamp(
|
|
9340
|
-
MIN_INLINE_ANGLES + extraAngles,
|
|
9341
|
-
MIN_INLINE_ANGLES,
|
|
9342
|
-
MAX_INLINE_ANGLES
|
|
9343
|
-
);
|
|
9344
|
-
return {
|
|
9345
|
-
inlineAngles,
|
|
9346
|
-
sweep: effective >= SWEEP_FLOOR,
|
|
9347
|
-
specialistCap: src >= SPECIALIST_FLOOR ? 2 : 0,
|
|
9348
|
-
verifyShard: VERIFY_SHARD
|
|
9349
|
-
};
|
|
9350
|
-
}
|
|
9351
|
-
__name(reviewBudget, "reviewBudget");
|
|
9352
|
-
function sane(n) {
|
|
9353
|
-
const v = Number(n);
|
|
9354
|
-
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 0;
|
|
9355
|
-
}
|
|
9356
|
-
__name(sane, "sane");
|
|
9357
|
-
function clamp(v, lo, hi) {
|
|
9358
|
-
return Math.min(hi, Math.max(lo, v));
|
|
9359
|
-
}
|
|
9360
|
-
__name(clamp, "clamp");
|
|
9361
|
-
|
|
9362
9703
|
// packages/cli/src/commands/review/lib/report.ts
|
|
9363
9704
|
function buildPlanReport(plan, postImageLines) {
|
|
9364
9705
|
const files = plan.files.map((f) => {
|
|
@@ -12580,7 +12921,7 @@ function runPublishAssets(args) {
|
|
|
12580
12921
|
return;
|
|
12581
12922
|
}
|
|
12582
12923
|
const repo = repoResult.repo;
|
|
12583
|
-
const effectiveHost = args.host
|
|
12924
|
+
const effectiveHost = resolveGhHost(args.host);
|
|
12584
12925
|
const auth = reviewWriteAuthorization({
|
|
12585
12926
|
userAuthorized: args.userAuthorized,
|
|
12586
12927
|
skillArgs: args.skillArgs,
|
|
@@ -13182,7 +13523,7 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
13182
13523
|
}
|
|
13183
13524
|
if (report.missingChunks.length > 0) {
|
|
13184
13525
|
writeStderrLine(
|
|
13185
|
-
`NOTE: a chunk counts as read when an agent was pointed at its lines AND the harness recorded that agent opening the diff. An agent handed the diff with no line ranges covers nothing.
|
|
13526
|
+
`NOTE: a chunk counts as read when an agent was pointed at its lines AND the harness recorded that agent opening the diff. An agent handed the diff with no line ranges covers nothing. Every rostered agent's launch block \u2014 its diff reads included \u2014 comes from \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt --plan ${shellQuotePath(args.plan)} --roster\` (or \`--role <r>\` for one, \`--chunk <id>\` for a chunk agent \u2014 the usual reader of a missing chunk, which \`--role\` cannot rebuild); pass each verbatim. \`--whole-diff\` builds the reading block for an Agent 8 specialist alone \u2014 prepending it to a rostered brief double-budgets the agent.`
|
|
13186
13527
|
);
|
|
13187
13528
|
}
|
|
13188
13529
|
if (report.idleAgents.length > 0) {
|
|
@@ -13200,6 +13541,12 @@ This is an environment problem, not a finding about the agents. Coverage cannot
|
|
|
13200
13541
|
`ERROR: ${report.missingChunks.length} chunk(s) were not reviewed \u2014 ${report.missingChunks.join(", ")}. Nobody read those lines. Do not aggregate findings over a diff that was not read.`
|
|
13201
13542
|
);
|
|
13202
13543
|
}
|
|
13544
|
+
if (report.budgetGaps.length > 0) {
|
|
13545
|
+
const total = report.budgetGaps.reduce((n, g) => n + g.gaps.length, 0);
|
|
13546
|
+
writeStderrLine(
|
|
13547
|
+
`NOTE: ${total} budget-gap disclosure(s) from ${report.budgetGaps.length} agent(s). Do not relaunch over these; rule on each: a gap naming an incomplete required trace goes in unreviewedDimensions, optional depth is disclosed in the report's "Not reviewed" section. The disclosures \u2014 ` + report.budgetGaps.map((g) => `${g.agent}: ${g.gaps.join("; ")}`).join(" | ")
|
|
13548
|
+
);
|
|
13549
|
+
}
|
|
13203
13550
|
if (!report.ok) {
|
|
13204
13551
|
process.exitCode = 3;
|
|
13205
13552
|
}
|
|
@@ -13297,8 +13644,12 @@ function classifyReturn(rec, territory, findingsList) {
|
|
|
13297
13644
|
return "yielded";
|
|
13298
13645
|
}
|
|
13299
13646
|
}
|
|
13300
|
-
const
|
|
13301
|
-
|
|
13647
|
+
const judged = stripBudgetGapLines(text);
|
|
13648
|
+
const receipt = DRY_RECEIPT_RE.exec(judged);
|
|
13649
|
+
const clause = receipt?.[1] ?? "";
|
|
13650
|
+
const inlineGap = INLINE_BUDGET_GAP_RE.exec(clause);
|
|
13651
|
+
const judgedClause = inlineGap === null ? clause : clause.slice(0, inlineGap.index);
|
|
13652
|
+
if (rec.successfulToolCalls > 0 && rec.diffToolCalls > 0 && openedTheTerritory(rec.diffReads, territory) && receipt !== null && substantiveClause(judgedClause)) {
|
|
13302
13653
|
return "dry";
|
|
13303
13654
|
}
|
|
13304
13655
|
return "unknown";
|
|
@@ -13598,6 +13949,60 @@ function chunkFrom(report, id) {
|
|
|
13598
13949
|
return { diffPath, chunk: chunk2, total: chunks.length };
|
|
13599
13950
|
}
|
|
13600
13951
|
__name(chunkFrom, "chunkFrom");
|
|
13952
|
+
var FINDINGS_LIST_READS = 3;
|
|
13953
|
+
var LINES_PER_FILE_READ = 500;
|
|
13954
|
+
function wholeDiffReadPages(report) {
|
|
13955
|
+
return (Array.isArray(report.chunks) ? report.chunks : []).reduce(
|
|
13956
|
+
(n, c) => {
|
|
13957
|
+
const chars = c?.chars;
|
|
13958
|
+
return n + Math.max(
|
|
13959
|
+
1,
|
|
13960
|
+
Math.ceil(
|
|
13961
|
+
(typeof chars === "number" && Number.isFinite(chars) ? chars : 0) / READ_FILE_CHAR_CAP
|
|
13962
|
+
)
|
|
13963
|
+
);
|
|
13964
|
+
},
|
|
13965
|
+
0
|
|
13966
|
+
);
|
|
13967
|
+
}
|
|
13968
|
+
__name(wholeDiffReadPages, "wholeDiffReadPages");
|
|
13969
|
+
function weightedTerritoryLines(report, chunk2) {
|
|
13970
|
+
const lines = typeof chunk2.lines === "number" && Number.isFinite(chunk2.lines) ? Math.max(0, Math.floor(chunk2.lines)) : 0;
|
|
13971
|
+
if (lines === 0) return 0;
|
|
13972
|
+
const kinds = new Map(
|
|
13973
|
+
(Array.isArray(report.files) ? report.files : []).filter((f) => !!f && typeof f.path === "string").map((f) => [f.path, f.kind])
|
|
13974
|
+
);
|
|
13975
|
+
let src = 0;
|
|
13976
|
+
let other = 0;
|
|
13977
|
+
for (const f of Array.isArray(chunk2.files) ? chunk2.files : []) {
|
|
13978
|
+
const e = f;
|
|
13979
|
+
const span = typeof e?.newStart === "number" && typeof e?.newEnd === "number" ? e.newEnd - e.newStart + 1 : 0;
|
|
13980
|
+
if (!(span > 0)) continue;
|
|
13981
|
+
const kind = typeof e.path === "string" ? kinds.get(e.path) : void 0;
|
|
13982
|
+
if (kind === void 0 || kind === "source") src += span;
|
|
13983
|
+
else other += span;
|
|
13984
|
+
}
|
|
13985
|
+
const total = src + other;
|
|
13986
|
+
if (total === 0) return lines;
|
|
13987
|
+
return Math.max(1, Math.round(lines * (src + other / 8) / total));
|
|
13988
|
+
}
|
|
13989
|
+
__name(weightedTerritoryLines, "weightedTerritoryLines");
|
|
13990
|
+
function toolBudgetBlock(report, launch) {
|
|
13991
|
+
const base = report.budget?.agentToolBudget;
|
|
13992
|
+
if (typeof base !== "number" || !Number.isFinite(base) || base <= 0) {
|
|
13993
|
+
return [];
|
|
13994
|
+
}
|
|
13995
|
+
const reads = Number.isFinite(launch.mandatoryReads) ? Math.max(0, Math.floor(launch.mandatoryReads)) : 0;
|
|
13996
|
+
const territory = typeof launch.territoryLines === "number" && Number.isFinite(launch.territoryLines) ? launch.territoryLines : launch.territoryLines === null || launch.territoryLines === void 0 ? null : 0;
|
|
13997
|
+
const total = launchToolBudget(base, territory, reads);
|
|
13998
|
+
return [
|
|
13999
|
+
"",
|
|
14000
|
+
"## Tool budget",
|
|
14001
|
+
"",
|
|
14002
|
+
`About **${total} tool calls** for this whole review \u2014 reads, greps, shell, everything \u2014 and the ~${reads} reads your launch is assigned (your brief, the diff pages, any files your method mandates) are already counted in. It is a soft ceiling. At the ceiling: stop exploring, write your findings from the evidence already in hand, and disclose each unfinished check on its own line, exactly as \`Budget gap: <the check>\` \u2014 the coverage tool reads those lines, so the format is load-bearing. The budget never suppresses a finding: a candidate you can already name goes in your return regardless (at \`Confidence: low\` if the budget stopped you before verifying it).`
|
|
14003
|
+
];
|
|
14004
|
+
}
|
|
14005
|
+
__name(toolBudgetBlock, "toolBudgetBlock");
|
|
13601
14006
|
function buildChunkAgentPrompt(report, id, rules) {
|
|
13602
14007
|
const { chunk: chunk2, total } = chunkFrom(report, id);
|
|
13603
14008
|
const files = (Array.isArray(chunk2.files) ? chunk2.files : []).filter(
|
|
@@ -13653,6 +14058,21 @@ function buildChunkAgentPrompt(report, id, rules) {
|
|
|
13653
14058
|
if (repositoryContext) {
|
|
13654
14059
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13655
14060
|
}
|
|
14061
|
+
if (!unreachable) {
|
|
14062
|
+
parts.push(
|
|
14063
|
+
...toolBudgetBlock(report, {
|
|
14064
|
+
territoryLines: weightedTerritoryLines(report, chunk2),
|
|
14065
|
+
// The launch's whole reading list: the brief file, plus the diff pages
|
|
14066
|
+
// this chunk takes.
|
|
14067
|
+
mandatoryReads: 1 + Math.max(
|
|
14068
|
+
1,
|
|
14069
|
+
Math.ceil(
|
|
14070
|
+
(Number.isFinite(chunk2.chars) ? chunk2.chars : 0) / READ_FILE_CHAR_CAP
|
|
14071
|
+
)
|
|
14072
|
+
)
|
|
14073
|
+
})
|
|
14074
|
+
);
|
|
14075
|
+
}
|
|
13656
14076
|
parts.push(
|
|
13657
14077
|
"",
|
|
13658
14078
|
"## When you are done",
|
|
@@ -13702,6 +14122,9 @@ function buildWholeDiffBlock(report, rules) {
|
|
|
13702
14122
|
if (repositoryContext) {
|
|
13703
14123
|
parts.push("", ...repositoryContextBlock(repositoryContext));
|
|
13704
14124
|
}
|
|
14125
|
+
parts.push(
|
|
14126
|
+
...toolBudgetBlock(report, { mandatoryReads: wholeDiffReadPages(report) })
|
|
14127
|
+
);
|
|
13705
14128
|
parts.push(...tail(rules));
|
|
13706
14129
|
return parts.join("\n");
|
|
13707
14130
|
}
|
|
@@ -13889,6 +14312,56 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
13889
14312
|
parts.push("");
|
|
13890
14313
|
}
|
|
13891
14314
|
parts.push("## Your dimension", "", brief.brief);
|
|
14315
|
+
if (!brief.budgetExempt) {
|
|
14316
|
+
const chunks = Array.isArray(report.chunks) ? report.chunks : [];
|
|
14317
|
+
if (typeof opts.chunk === "number") {
|
|
14318
|
+
const c = chunks.find((x) => x?.id === opts.chunk);
|
|
14319
|
+
parts.push(
|
|
14320
|
+
...toolBudgetBlock(report, {
|
|
14321
|
+
territoryLines: weightedTerritoryLines(report, c ?? {}),
|
|
14322
|
+
// Its reading list: the brief file, the chunk's diff pages, and
|
|
14323
|
+
// the cumulative findings list its brief orders read in full —
|
|
14324
|
+
// measured at 65-82 KB on real runs, several pages of it.
|
|
14325
|
+
mandatoryReads: 1 + Math.max(
|
|
14326
|
+
1,
|
|
14327
|
+
Math.ceil(
|
|
14328
|
+
(typeof c?.chars === "number" && Number.isFinite(c.chars) ? c.chars : 0) / READ_FILE_CHAR_CAP
|
|
14329
|
+
)
|
|
14330
|
+
) + FINDINGS_LIST_READS
|
|
14331
|
+
})
|
|
14332
|
+
);
|
|
14333
|
+
} else if (role.startsWith("invariant-") && opts.file) {
|
|
14334
|
+
const files = Array.isArray(report.files) ? report.files : [];
|
|
14335
|
+
const f = files.find((x) => x?.path === opts.file);
|
|
14336
|
+
const added = typeof f?.addedLines === "number" ? f.addedLines : 0;
|
|
14337
|
+
const fileLines = typeof f?.fileLines === "number" && Number.isFinite(f.fileLines) ? f.fileLines : 0;
|
|
14338
|
+
const changed = added + (typeof f?.removedLines === "number" ? f.removedLines : 0);
|
|
14339
|
+
parts.push(
|
|
14340
|
+
...toolBudgetBlock(report, {
|
|
14341
|
+
territoryLines: changed,
|
|
14342
|
+
// Its reading list: the brief, its own diff slice, and the whole
|
|
14343
|
+
// post-change file paged to the end. The pages come from
|
|
14344
|
+
// `fileLines` — the post-change length the plan records for
|
|
14345
|
+
// every file — with `addedLines` as the fallback lower bound
|
|
14346
|
+
// for an older plan without it: a file can go heavy by VOLUME
|
|
14347
|
+
// in a large file it barely rewrote, and estimating its paging
|
|
14348
|
+
// from added lines alone told exactly that agent its mandatory
|
|
14349
|
+
// reading was already overspending. Floors at the old flat 4 so
|
|
14350
|
+
// no launch gets less than before.
|
|
14351
|
+
mandatoryReads: Math.max(
|
|
14352
|
+
4,
|
|
14353
|
+
2 + Math.ceil(Math.max(added, fileLines) / LINES_PER_FILE_READ)
|
|
14354
|
+
)
|
|
14355
|
+
})
|
|
14356
|
+
);
|
|
14357
|
+
} else {
|
|
14358
|
+
parts.push(
|
|
14359
|
+
...toolBudgetBlock(report, {
|
|
14360
|
+
mandatoryReads: 1 + wholeDiffReadPages(report) + (brief.acceptsFindings ? FINDINGS_LIST_READS : 0)
|
|
14361
|
+
})
|
|
14362
|
+
);
|
|
14363
|
+
}
|
|
14364
|
+
}
|
|
13892
14365
|
const repositoryContext = repositoryContextOf(report);
|
|
13893
14366
|
if (role === "7") {
|
|
13894
14367
|
if (repositoryContext) {
|
|
@@ -16948,12 +17421,8 @@ function authorization(args) {
|
|
|
16948
17421
|
repo: args.repo,
|
|
16949
17422
|
// The EFFECTIVE host, not merely the flag: with --host absent the gh
|
|
16950
17423
|
// child inherits an operator-exported GH_HOST, so that is where this
|
|
16951
|
-
// write would route — and what the gate must bind.
|
|
16952
|
-
|
|
16953
|
-
// `|| undefined`, not `??`: an exported-but-empty GH_HOST ("" survives
|
|
16954
|
-
// `??`, being non-nullish) must read as "no host", not as a host named
|
|
16955
|
-
// "" that fails every comparison.
|
|
16956
|
-
host: args.host ?? (process.env["GH_HOST"]?.trim() || void 0)
|
|
17424
|
+
// write would route — and what the gate must bind.
|
|
17425
|
+
host: resolveGhHost(args.host)
|
|
16957
17426
|
});
|
|
16958
17427
|
}
|
|
16959
17428
|
__name(authorization, "authorization");
|
|
@@ -20241,9 +20710,9 @@ var saveArtifactCommand = {
|
|
|
20241
20710
|
var reviewCommand = {
|
|
20242
20711
|
command: "review",
|
|
20243
20712
|
describe: "Run a review non-interactively (`run`), plus the internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)",
|
|
20244
|
-
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(repoContextCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(costLedgerCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(saveArtifactCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
20713
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(matchRemoteCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(repoContextCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(baseTreeCommand).command(testDeltaCommand).command(driveCommand).command(mockProviderCommand).command(extractStepCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(costLedgerCommand).command(presubmitCommand).command(testEfficacyCommand).command(testPlanCommand).command(findingsCommand).command(publishAssetsCommand).command(composeReviewCommand).command(saveArtifactCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
20245
20714
|
1,
|
|
20246
|
-
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, repo-context, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, cost-ledger, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, save-artifact, submit, or cleanup."
|
|
20715
|
+
"Specify a subcommand: run, parse-args, match-remote, fetch-pr, capture-local, plan-diff, repo-context, pr-context, comment-status, load-rules, agent-prompt, build-test, base-tree, test-delta, drive, mock-provider, extract-step, script-lint, resolve-anchors, check-coverage, cost-ledger, presubmit, test-efficacy, test-plan, findings, publish-assets, compose-review, save-artifact, submit, or cleanup."
|
|
20247
20716
|
).version(false), "builder"),
|
|
20248
20717
|
handler: /* @__PURE__ */ __name(() => {
|
|
20249
20718
|
}, "handler")
|
|
@@ -20443,10 +20912,10 @@ var updateCommand3 = {
|
|
|
20443
20912
|
stdioHelpers,
|
|
20444
20913
|
{ updateEventEmitter }
|
|
20445
20914
|
] = await Promise.all([
|
|
20446
|
-
import("./settings-
|
|
20447
|
-
import("./updateCheck-
|
|
20448
|
-
import("./installationInfo-
|
|
20449
|
-
import("./standalone-update-
|
|
20915
|
+
import("./settings-V7BR3RKP.js"),
|
|
20916
|
+
import("./updateCheck-YZ2CRCFC.js"),
|
|
20917
|
+
import("./installationInfo-VGBXMYLY.js"),
|
|
20918
|
+
import("./standalone-update-QGIKHATD.js"),
|
|
20450
20919
|
import("./stdioHelpers-7A2EE64Z.js"),
|
|
20451
20920
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
20452
20921
|
]);
|
|
@@ -21613,7 +22082,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
21613
22082
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
21614
22083
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
21615
22084
|
terminalImageRenderSupportProvider: interactive ? async () => {
|
|
21616
|
-
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-
|
|
22085
|
+
const { getTerminalImageRenderSupport } = await import("./terminal-image-renderer-TLDNACQY.js");
|
|
21617
22086
|
return getTerminalImageRenderSupport();
|
|
21618
22087
|
} : void 0,
|
|
21619
22088
|
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|