@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.
Files changed (254) hide show
  1. package/README.md +2 -0
  2. package/bundled/qc-helper/docs/configuration/settings.md +12 -8
  3. package/bundled/qc-helper/docs/features/commands.md +1 -1
  4. package/bundled/qc-helper/docs/features/hooks.md +50 -0
  5. package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
  6. package/bundled/qc-helper/docs/qwen-serve.md +1 -1
  7. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
  8. package/bundled/review/SKILL.md +24 -5
  9. package/chunks/{MaxSizedBox-COZBVNCI.js → MaxSizedBox-7PM6BGJ5.js} +13 -10
  10. package/chunks/{StandaloneSessionPicker-3OF2FS6S.js → StandaloneSessionPicker-3UQHM7GV.js} +29 -26
  11. package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
  12. package/chunks/{acpAgent-3JCJ6KWG.js → acpAgent-5UWLFV6V.js} +369 -148
  13. package/chunks/{agent-DBSC47CD.js → agent-624T2BLO.js} +13 -10
  14. package/chunks/{agent-headless-ZJHZ7I3S.js → agent-headless-2EE5J2KX.js} +13 -10
  15. package/chunks/{bridge-NFBYT4ZI.js → bridge-JENKGFFP.js} +15 -12
  16. package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
  17. package/chunks/{channel-management-service-LXSJXQGM.js → channel-management-service-DDWUPHMU.js} +1 -1
  18. package/chunks/{channel-settings-store-LABKDKSI.js → channel-settings-store-SA6JZSPH.js} +21 -18
  19. package/chunks/{channel-worker-group-MTW2AGT3.js → channel-worker-group-E67EN3RV.js} +2 -2
  20. package/chunks/{channel-worker-manager-UU6PTQSI.js → channel-worker-manager-SW4C45CF.js} +2 -2
  21. package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
  22. package/chunks/{chunk-HKCYGZZ4.js → chunk-2ILAOM2I.js} +30 -13
  23. package/chunks/{chunk-LDY4J4G6.js → chunk-2M4K4KYS.js} +176 -119
  24. package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
  25. package/chunks/{chunk-XCG76UE6.js → chunk-3PY4LPJF.js} +17 -129
  26. package/chunks/{chunk-26ISE5EG.js → chunk-3SE7J4DR.js} +3 -3
  27. package/chunks/{chunk-APMRLB2H.js → chunk-3WNQOYHQ.js} +12 -12
  28. package/chunks/{chunk-O7VQ3F22.js → chunk-4ALIARFY.js} +1 -1
  29. package/chunks/{chunk-FJ6YHWHZ.js → chunk-4DU3NCHG.js} +47 -54
  30. package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
  31. package/chunks/{chunk-3HS6Y4UA.js → chunk-4WU6NY7F.js} +2 -2
  32. package/chunks/{chunk-JRIJOZXO.js → chunk-5ZGR6RKJ.js} +3 -3
  33. package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
  34. package/chunks/{chunk-ZQGHESAS.js → chunk-6TR7CFXH.js} +1 -1
  35. package/chunks/{chunk-EZ53KMUN.js → chunk-757GB46F.js} +1 -1
  36. package/chunks/{chunk-5YT3Y33M.js → chunk-77QVBFCU.js} +3 -3
  37. package/chunks/{chunk-5PGKKSO6.js → chunk-7DVT4LVV.js} +35 -28
  38. package/chunks/{chunk-IMK3SJ43.js → chunk-7VUERJHS.js} +1066 -597
  39. package/chunks/{chunk-KPMB4JEZ.js → chunk-B52AWKBB.js} +64 -20
  40. package/chunks/{chunk-R2KZWK5Z.js → chunk-BF224XHL.js} +2 -2
  41. package/chunks/{chunk-TSYIQDG7.js → chunk-BF52U4XJ.js} +1 -1
  42. package/chunks/{chunk-LDUGDB5H.js → chunk-C5VWPTGT.js} +1 -1
  43. package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
  44. package/chunks/chunk-COBO5EBO.js +135 -0
  45. package/chunks/{chunk-ACHMWGC5.js → chunk-DQSDACD2.js} +1 -1
  46. package/chunks/{chunk-VT3VNFVW.js → chunk-DX5W5AON.js} +2 -2
  47. package/chunks/{chunk-JACAHYEN.js → chunk-E4ZBKMSF.js} +4 -4
  48. package/chunks/{chunk-MV7VUCIG.js → chunk-EIVICVHM.js} +4 -4
  49. package/chunks/{chunk-YHEEE624.js → chunk-EN2TKTFH.js} +1 -1
  50. package/chunks/chunk-F6WFNA7U.js +22 -0
  51. package/chunks/{chunk-Z6W3XDLN.js → chunk-FN6YXJOP.js} +1 -1
  52. package/chunks/{chunk-BJKFFPX2.js → chunk-FWBXMANW.js} +3 -3
  53. package/chunks/{chunk-764F335K.js → chunk-FYAXKJK7.js} +314 -63
  54. package/chunks/{chunk-XIDHBXUI.js → chunk-GBDINRIL.js} +3 -3
  55. package/chunks/{chunk-Z5ZAWED3.js → chunk-GOEVOFQI.js} +3 -3
  56. package/chunks/{chunk-ZKUJ4AO7.js → chunk-GQCEQPYQ.js} +3 -3
  57. package/chunks/{chunk-BFSQBXHV.js → chunk-GXSNGY5M.js} +399 -534
  58. package/chunks/{chunk-3ARO4N5G.js → chunk-HA3SAB64.js} +22 -69
  59. package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
  60. package/chunks/{chunk-LMEIS6WW.js → chunk-HWX5HPUG.js} +3 -3
  61. package/chunks/{chunk-VLFX3L3X.js → chunk-IBYULW65.js} +6 -6
  62. package/chunks/{chunk-SDUDZNF4.js → chunk-IUQ52YJK.js} +1 -1
  63. package/chunks/{chunk-H2352CX2.js → chunk-IYES5WOT.js} +2 -2
  64. package/chunks/{chunk-CE5UCTKO.js → chunk-KAQCJO6Y.js} +1 -1
  65. package/chunks/{chunk-DPH3MUAP.js → chunk-KKDVZLGL.js} +1 -1
  66. package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
  67. package/chunks/{chunk-P7HUJDBZ.js → chunk-M3STHEMM.js} +11 -16
  68. package/chunks/{chunk-VDS2WYM5.js → chunk-NGYI5EF5.js} +2 -2
  69. package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
  70. package/chunks/{chunk-GUFY6D3E.js → chunk-NPUXXRJI.js} +1 -1
  71. package/chunks/{chunk-4Q6N3SNL.js → chunk-NVRDQFCX.js} +1 -1
  72. package/chunks/{chunk-77WOUGCA.js → chunk-OHKJVAKG.js} +7 -7
  73. package/chunks/{chunk-TAOSTUHI.js → chunk-PG62DFWD.js} +10 -10
  74. package/chunks/{chunk-REHWPCG2.js → chunk-PLFATELK.js} +1 -1
  75. package/chunks/{chunk-APNNM3JC.js → chunk-QGHSP65Z.js} +2 -2
  76. package/chunks/{chunk-HY2INPTA.js → chunk-QQWD7LZV.js} +4 -4
  77. package/chunks/{chunk-P74TZRXD.js → chunk-QXVSWG66.js} +1 -1
  78. package/chunks/{chunk-TX3KSSDN.js → chunk-S3Y3GBFD.js} +1 -1
  79. package/chunks/{chunk-B23P3YWE.js → chunk-SNRT2TJJ.js} +6 -23
  80. package/chunks/chunk-SR7RZ4MS.js +202 -0
  81. package/chunks/{chunk-F3LPXDJP.js → chunk-TE3ZAJE7.js} +13 -3
  82. package/chunks/{chunk-AB4A73VL.js → chunk-TKSZJ5BV.js} +1 -1
  83. package/chunks/{chunk-RZMGG3HP.js → chunk-U5SLIG7E.js} +1 -1
  84. package/chunks/chunk-UA5H3DS2.js +203 -0
  85. package/chunks/{chunk-JSJTZ6GO.js → chunk-VWMUDKLC.js} +3 -3
  86. package/chunks/{chunk-RGTB44BO.js → chunk-VXZ5HAOV.js} +1 -1
  87. package/chunks/{chunk-BCMJPTXV.js → chunk-WG6542MA.js} +1 -1
  88. package/chunks/{chunk-AG3P2RES.js → chunk-WV5J6Q6N.js} +1 -1
  89. package/chunks/{chunk-MIA37QO3.js → chunk-XHD7CRP2.js} +2 -2
  90. package/chunks/{chunk-KKRGVSHC.js → chunk-XZKQT2B2.js} +4 -4
  91. package/chunks/{chunk-4QJJHIZ5.js → chunk-Y4TETC74.js} +5 -5
  92. package/chunks/{chunk-QKJT5K4Q.js → chunk-YEF7XEO2.js} +3 -3
  93. package/chunks/{chunk-UKAYEQDU.js → chunk-YHJFF7KH.js} +131 -38
  94. package/chunks/{chunk-64YLXLMY.js → chunk-YOM7DEGB.js} +2 -2
  95. package/chunks/{chunk-BN3OROB3.js → chunk-ZCLLJARV.js} +9 -9
  96. package/chunks/{chunk-RFA6VDCR.js → chunk-ZHA242R4.js} +2 -2
  97. package/chunks/{chunk-L4OW63GW.js → chunk-ZPLALRXZ.js} +17 -9
  98. package/chunks/{computer-use-QLJ27OCZ.js → computer-use-ESQYJ3JY.js} +13 -10
  99. package/chunks/{config-utils-KIEXWA4F.js → config-utils-XQHBJP7G.js} +2 -2
  100. package/chunks/{contextCommand-JDTOJRBO.js → contextCommand-CX3YF4ZE.js} +15 -12
  101. package/chunks/{core-runtime-MZIAVYQC.js → core-runtime-DIAU7JMG.js} +13 -10
  102. package/chunks/{create-sub-session-YBBCNSHE.js → create-sub-session-HDPD6HOA.js} +13 -10
  103. package/chunks/{daemon-SCTQMM7Z.js → daemon-VZBGJUNL.js} +30 -0
  104. package/chunks/{daemon-status-provider-BZ7RD4ZJ.js → daemon-status-provider-H6O4UQ4F.js} +19 -16
  105. package/chunks/{daemon-trust-policy-2E4C3M7S.js → daemon-trust-policy-BNUXG6MT.js} +20 -17
  106. package/chunks/{daemon-trust-policy-monitor-UYLFH6RW.js → daemon-trust-policy-monitor-E4EQ7GF4.js} +20 -17
  107. package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
  108. package/chunks/{deferred-core-runtime-6XZYMJZB.js → deferred-core-runtime-CBMSHPAU.js} +13 -10
  109. package/chunks/{dist-BATY7GI4.js → dist-EEEQGCZA.js} +731 -136
  110. package/chunks/{dist-26RK5XZO.js → dist-MKX5OSFF.js} +4 -3
  111. package/chunks/{earlyInputCapture-LATQCGDC.js → earlyInputCapture-UIOP7OIN.js} +13 -10
  112. package/chunks/{edit-72DP57CD.js → edit-ITMZYFKA.js} +13 -10
  113. package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
  114. package/chunks/{enter-worktree-B4FY2ZPP.js → enter-worktree-S4PL5UV6.js} +13 -10
  115. package/chunks/{enterPlanMode-TQBWGCPL.js → enterPlanMode-YV52NNJT.js} +13 -10
  116. package/chunks/{environment-MOGZGZDS.js → environment-NGOWPRZV.js} +17 -14
  117. package/chunks/{errors-PGON5GH7.js → errors-BU26DTDX.js} +15 -12
  118. package/chunks/{exit-worktree-EYUD4YP2.js → exit-worktree-XRM6LH5F.js} +13 -10
  119. package/chunks/{exitPlanMode-4Q7BSQXR.js → exitPlanMode-ZLI5F7KR.js} +13 -10
  120. package/chunks/{fast-path-WI7D5MER.js → fast-path-UJWORIED.js} +3 -3
  121. package/chunks/{fast-path-settings-YBRL24DB.js → fast-path-settings-37WQD5B2.js} +6 -3
  122. package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
  123. package/chunks/{gemini-ZXURGM6Y.js → gemini-ZSKNDUMU.js} +55 -48
  124. package/chunks/{geminiContentGenerator-EOODO75Y.js → geminiContentGenerator-YGEXOEKD.js} +1 -1
  125. package/chunks/{glob-QNRIUOS6.js → glob-7KZG44BR.js} +13 -10
  126. package/chunks/{goal-tools-QSYW65HV.js → goal-tools-PXWN5VK3.js} +3 -1
  127. package/chunks/{grep-56MTW67B.js → grep-6ZFC7RJ5.js} +13 -10
  128. package/chunks/{handleAutoUpdate-XGFIPVT4.js → handleAutoUpdate-KSEL3TQS.js} +17 -14
  129. package/chunks/{i18n-RZB35L4B.js → i18n-ZIUXBW5V.js} +14 -11
  130. package/chunks/{image-gen-OE2EEKN3.js → image-gen-AUIZJJNK.js} +6 -4
  131. package/chunks/{initializer-YPVMTMKD.js → initializer-7AHY3N6Q.js} +20 -17
  132. package/chunks/{installationInfo-ZTMTMYNW.js → installationInfo-VGBXMYLY.js} +14 -11
  133. package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
  134. package/chunks/{list-NIW3WID5.js → list-PSFKQHLB.js} +23 -20
  135. package/chunks/{loadedSettingsAdapter-VSLILTOZ.js → loadedSettingsAdapter-FTMRCTOF.js} +20 -17
  136. package/chunks/{loggingContentGenerator-KFZYVAGV.js → loggingContentGenerator-MZAN52UV.js} +5 -3
  137. package/chunks/{managed-npm-update-WHTA2K5V.js → managed-npm-update-O4NHK45X.js} +14 -11
  138. package/chunks/{mcp-7KGK3CS3.js → mcp-6CFP2AYQ.js} +20 -17
  139. package/chunks/{monitor-FDWEJQWP.js → monitor-DAKD6OU4.js} +13 -10
  140. package/chunks/{nonInteractiveCli-2MVJ6TCS.js → nonInteractiveCli-RC7VIUZL.js} +49 -44
  141. package/chunks/{notebook-edit-ZUVK2XWE.js → notebook-edit-474DPMRL.js} +13 -10
  142. package/chunks/{openaiContentGenerator-TNLWOPH5.js → openaiContentGenerator-2NFY2MWO.js} +6 -3
  143. package/chunks/{pidfile-BB6SKPH2.js → pidfile-KBFVDNQP.js} +13 -10
  144. package/chunks/{processUtils-WKHJOPDH.js → processUtils-6GRYH4Y3.js} +2 -2
  145. package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
  146. package/chunks/{qwenContentGenerator-FZS2DYF7.js → qwenContentGenerator-KAHU6IZY.js} +14 -11
  147. package/chunks/{qwenOAuth2-UYMYRXBB.js → qwenOAuth2-RRQTCP4W.js} +6 -4
  148. package/chunks/{read-file-FMTE6LPA.js → read-file-3M6WXDXP.js} +4 -2
  149. package/chunks/{resumeHistoryUtils-Z34RCZFF.js → resumeHistoryUtils-D6TAY3HX.js} +16 -13
  150. package/chunks/{ripGrep-DUIYUZGM.js → ripGrep-PLPENT3E.js} +13 -10
  151. package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
  152. package/chunks/{run-qwen-serve-KOHHR3F4.js → run-qwen-serve-ZAFIJKJC.js} +93 -40
  153. package/chunks/{runtime-K4NTZSAU.js → runtime-ZED7CYOZ.js} +23 -20
  154. package/chunks/{scheduler-6G6AMURS.js → scheduler-MD3AL2W5.js} +13 -10
  155. package/chunks/{serve-NMG2TM5K.js → serve-E3VUDRZN.js} +20 -17
  156. package/chunks/{server-FS7KDELS.js → server-OWMEMAKR.js} +381 -192
  157. package/chunks/{session-XZADUVKJ.js → session-HZ57QK7K.js} +141 -81
  158. package/chunks/{settings-G75R6FOA.js → settings-V7BR3RKP.js} +19 -16
  159. package/chunks/{shell-3D3PMQHE.js → shell-23OMNMW6.js} +13 -10
  160. package/chunks/{skill-TSEYMVQ2.js → skill-6HBDYZRS.js} +4 -2
  161. package/chunks/{skill-settings-HJC2CPBJ.js → skill-settings-HWJLTU7M.js} +19 -16
  162. package/chunks/{spawnChannel-YWCN74G5.js → spawnChannel-N6KKUW5B.js} +13 -10
  163. package/chunks/{standalone-update-HLYOLX6V.js → standalone-update-QGIKHATD.js} +15 -12
  164. package/chunks/{startInteractiveUI-ROUIQ5KU.js → startInteractiveUI-GX2CRL42.js} +269 -118
  165. package/chunks/{team-create-OTP5SSB2.js → team-create-CFFKU7KL.js} +13 -10
  166. package/chunks/{team-plan-approval-TQX5TMXU.js → team-plan-approval-6EFOKR6A.js} +13 -10
  167. package/chunks/{terminal-image-renderer-KF3GKNWW.js → terminal-image-renderer-TLDNACQY.js} +13 -10
  168. package/chunks/{theme-manager-XVWAAGAM.js → theme-manager-5LJ3H7VO.js} +13 -10
  169. package/chunks/{tool-search-7N4D4O56.js → tool-search-UJV3A24H.js} +4 -2
  170. package/chunks/{total-session-admission-ZQ4VKIRW.js → total-session-admission-D63QYXGO.js} +15 -12
  171. package/chunks/{trustedFolders-4XYFPWVV.js → trustedFolders-KZCOB53W.js} +17 -12
  172. package/chunks/{update-relaunch-L4GSBLUU.js → update-relaunch-IFILM3SA.js} +5 -5
  173. package/chunks/{updateCheck-PCUTVRFE.js → updateCheck-YZ2CRCFC.js} +16 -13
  174. package/chunks/{useAutoAcceptIndicator-WMXY7MND.js → useAutoAcceptIndicator-AXEVNA3Q.js} +22 -19
  175. package/chunks/{validateNonInterActiveAuth-5S3U2D56.js → validateNonInterActiveAuth-3WTOJFWA.js} +44 -41
  176. package/chunks/{version-P57IQU2T.js → version-GXK7OHZY.js} +1 -1
  177. package/chunks/{web-fetch-5ZLLLCDD.js → web-fetch-ILB4GAVR.js} +10 -6
  178. package/chunks/{web-search-NELKANTW.js → web-search-HKRPGPZZ.js} +5 -3
  179. package/chunks/{workflow-RXKBF3LO.js → workflow-FXIPRQQA.js} +735 -134
  180. package/chunks/{workspace-providers-status-HAEMNAWC.js → workspace-providers-status-NYHC7HSR.js} +22 -19
  181. package/chunks/{workspace-registration-store-U3U3YM6V.js → workspace-registration-store-AKEB7OMW.js} +1 -1
  182. package/chunks/{workspace-registry-ZFP33GVB.js → workspace-registry-CDAS5TVZ.js} +15 -12
  183. package/chunks/{workspace-service-QMISJBMA.js → workspace-service-PAMUKMAV.js} +23 -20
  184. package/chunks/{workspace-skills-status-K7EOUGXL.js → workspace-skills-status-YQSHCCMS.js} +20 -17
  185. package/chunks/{workspace-trust-reconciler-BFPKULDZ.js → workspace-trust-reconciler-RPTXOIY2.js} +22 -19
  186. package/chunks/{write-file-2F76RRFE.js → write-file-CGS57TS4.js} +13 -10
  187. package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
  188. package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
  189. package/chunks/{zoom-image-DPR22XWY.js → zoom-image-E7D72GYV.js} +4 -2
  190. package/cli.js +13 -13
  191. package/locales/ca.js +10 -0
  192. package/locales/de.js +9 -0
  193. package/locales/en.js +10 -0
  194. package/locales/fr.js +9 -0
  195. package/locales/ja.js +9 -0
  196. package/locales/pt.js +9 -0
  197. package/locales/ru.js +9 -0
  198. package/locales/zh-TW.js +10 -0
  199. package/locales/zh.js +10 -0
  200. package/package.json +3 -3
  201. package/web-shell/assets/{arc-CunFPPcQ.js → arc-DybZaz32.js} +1 -1
  202. package/web-shell/assets/{architectureDiagram-3BPJPVTR-D3SqCgeM.js → architectureDiagram-3BPJPVTR-jN3qBd19.js} +1 -1
  203. package/web-shell/assets/{blockDiagram-GPEHLZMM-CPRx90S_.js → blockDiagram-GPEHLZMM-Ct5DZPrj.js} +1 -1
  204. package/web-shell/assets/{c4Diagram-AAUBKEIU-CahP9Ue4.js → c4Diagram-AAUBKEIU-CUAFMlUG.js} +1 -1
  205. package/web-shell/assets/channel-BMwLrwLW.js +1 -0
  206. package/web-shell/assets/{chunk-2J33WTMH-DckIWZ12.js → chunk-2J33WTMH-CuV8n90B.js} +1 -1
  207. package/web-shell/assets/{chunk-4BX2VUAB-D2Kfctyn.js → chunk-4BX2VUAB-BUzl_kls.js} +1 -1
  208. package/web-shell/assets/{chunk-55IACEB6-DkI11FTX.js → chunk-55IACEB6-BnDBLX6A.js} +1 -1
  209. package/web-shell/assets/{chunk-727SXJPM-rR-TSCIi.js → chunk-727SXJPM-B83uTOjm.js} +1 -1
  210. package/web-shell/assets/{chunk-AQP2D5EJ-DFGKcGRO.js → chunk-AQP2D5EJ-DM3HLgpT.js} +1 -1
  211. package/web-shell/assets/{chunk-FMBD7UC4-CjWqcTPE.js → chunk-FMBD7UC4-CSQ5hgyb.js} +1 -1
  212. package/web-shell/assets/{chunk-ND2GUHAM-RXe-87UV.js → chunk-ND2GUHAM-BWOF4SxX.js} +1 -1
  213. package/web-shell/assets/{chunk-QZHKN3VN-Dz0c_Yrn.js → chunk-QZHKN3VN-BsOH9LMi.js} +1 -1
  214. package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +1 -0
  215. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +1 -0
  216. package/web-shell/assets/{cose-bilkent-S5V4N54A-ZHF0-jvV.js → cose-bilkent-S5V4N54A-IENqH2iJ.js} +1 -1
  217. package/web-shell/assets/{dagre-BM42HDAG-7Umz_ygJ.js → dagre-BM42HDAG--dyzDTGo.js} +1 -1
  218. package/web-shell/assets/{diagram-2AECGRRQ-DomN8nxq.js → diagram-2AECGRRQ-BE7Dcqof.js} +1 -1
  219. package/web-shell/assets/{diagram-5GNKFQAL-eebvj2OL.js → diagram-5GNKFQAL-Cr8-5OTj.js} +1 -1
  220. package/web-shell/assets/{diagram-KO2AKTUF-IR1mmn9d.js → diagram-KO2AKTUF-Bzey3uAY.js} +1 -1
  221. package/web-shell/assets/{diagram-LMA3HP47-CKysx5KF.js → diagram-LMA3HP47-sErl28Xb.js} +1 -1
  222. package/web-shell/assets/{diagram-OG6HWLK6-cBy5puHn.js → diagram-OG6HWLK6-Dq30ATIo.js} +1 -1
  223. package/web-shell/assets/{erDiagram-TEJ5UH35-B5RJagPG.js → erDiagram-TEJ5UH35-BkCoEfVW.js} +1 -1
  224. package/web-shell/assets/{flowDiagram-I6XJVG4X-CfHgDmPg.js → flowDiagram-I6XJVG4X-DHwO0rrI.js} +1 -1
  225. package/web-shell/assets/{ganttDiagram-6RSMTGT7-DUfFF5nb.js → ganttDiagram-6RSMTGT7-s7vAPxWq.js} +1 -1
  226. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-M9dt57k5.js → gitGraphDiagram-PVQCEYII-CQxhwPOU.js} +1 -1
  227. package/web-shell/assets/{index-B8e-CkuC.css → index-Bckpjr-I.css} +1 -1
  228. package/web-shell/assets/{index-CKjO4myk.js → index-CF4wApWp.js} +1 -1
  229. package/web-shell/assets/{index-Dc-fTO0V.js → index-DwEr9HEW.js} +316 -316
  230. package/web-shell/assets/{infoDiagram-5YYISTIA-CTKMmIro.js → infoDiagram-5YYISTIA-BnFrD0bq.js} +1 -1
  231. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DJIJDP4s.js → ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js} +1 -1
  232. package/web-shell/assets/{journeyDiagram-JHISSGLW-DgRnvn6S.js → journeyDiagram-JHISSGLW-CyGAhsxi.js} +1 -1
  233. package/web-shell/assets/{kanban-definition-UN3LZRKU-VUwO8yrg.js → kanban-definition-UN3LZRKU-CbsK5akB.js} +1 -1
  234. package/web-shell/assets/{linear-BCvgV5I_.js → linear-cQsF4P8D.js} +1 -1
  235. package/web-shell/assets/{mermaid.core-mv_kVV6q.js → mermaid.core-Z4HVqrKY.js} +5 -5
  236. package/web-shell/assets/{mindmap-definition-RKZ34NQL-sfnjMlOd.js → mindmap-definition-RKZ34NQL-CYnrBo_f.js} +1 -1
  237. package/web-shell/assets/{pieDiagram-4H26LBE5-BlhICse4.js → pieDiagram-4H26LBE5-CBzOfhrs.js} +1 -1
  238. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BgTQzwen.js → quadrantDiagram-W4KKPZXB-D4LK1Ebn.js} +1 -1
  239. package/web-shell/assets/{requirementDiagram-4Y6WPE33-CZ-FTrrN.js → requirementDiagram-4Y6WPE33-Bzti2Lcj.js} +1 -1
  240. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-G5Wp_jn3.js → sankeyDiagram-5OEKKPKP-yTBw5Z2s.js} +1 -1
  241. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-C8MKZ3i1.js → sequenceDiagram-3UESZ5HK-D07UVRiZ.js} +1 -1
  242. package/web-shell/assets/{stateDiagram-AJRCARHV-Bo0ZDm7y.js → stateDiagram-AJRCARHV-UE_lHsTn.js} +1 -1
  243. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +1 -0
  244. package/web-shell/assets/{timeline-definition-PNZ67QCA-M3L9E01f.js → timeline-definition-PNZ67QCA-DRvYdiTs.js} +1 -1
  245. package/web-shell/assets/{vennDiagram-CIIHVFJN-DD4eHCrm.js → vennDiagram-CIIHVFJN-CQLIXs0u.js} +1 -1
  246. package/web-shell/assets/{wardley-L42UT6IY-DNEL_3g4.js → wardley-L42UT6IY-JZz_Xqse.js} +1 -1
  247. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-q484OoqI.js → wardleyDiagram-YWT4CUSO--i7BiJwB.js} +1 -1
  248. package/web-shell/assets/{xychartDiagram-2RQKCTM6-4mcNt1Yg.js → xychartDiagram-2RQKCTM6-Bkc-bW0S.js} +1 -1
  249. package/web-shell/index.html +2 -2
  250. package/chunks/chunk-ALFTV7GA.js +0 -92
  251. package/web-shell/assets/channel-zbv7GWAw.js +0 -1
  252. package/web-shell/assets/classDiagram-4FO5ZUOK-DSjLkJJZ.js +0 -1
  253. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DSjLkJJZ.js +0 -1
  254. 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-LMEIS6WW.js";
5
+ } from "./chunk-HWX5HPUG.js";
6
6
  import {
7
7
  listCommand
8
- } from "./chunk-MV7VUCIG.js";
8
+ } from "./chunk-EIVICVHM.js";
9
9
  import {
10
10
  getErrorMessage as getErrorMessage2
11
- } from "./chunk-H2352CX2.js";
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-XIDHBXUI.js";
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-JACAHYEN.js";
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-HY2INPTA.js";
62
+ } from "./chunk-QQWD7LZV.js";
63
63
  import {
64
64
  parseChannelConfig
65
- } from "./chunk-P74TZRXD.js";
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-4QJJHIZ5.js";
135
+ } from "./chunk-Y4TETC74.js";
136
136
  import {
137
137
  loadSettings
138
- } from "./chunk-77WOUGCA.js";
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-TAOSTUHI.js";
145
+ } from "./chunk-PG62DFWD.js";
146
146
  import {
147
147
  loadEnvironment
148
- } from "./chunk-KPMB4JEZ.js";
148
+ } from "./chunk-B52AWKBB.js";
149
149
  import {
150
- resolveAcpChannelFallback
151
- } from "./chunk-ALFTV7GA.js";
150
+ resolveAcpChannelFallback,
151
+ scrubAndReportInheritedLoaderEnv
152
+ } from "./chunk-UA5H3DS2.js";
152
153
  import {
153
154
  getCliVersion
154
- } from "./chunk-Z6W3XDLN.js";
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-3ARO4N5G.js";
161
+ } from "./chunk-HA3SAB64.js";
161
162
  import {
162
163
  require_strip_json_comments
163
- } from "./chunk-ALGGS7UH.js";
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-BFSQBXHV.js";
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-XCG76UE6.js";
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-P7HUJDBZ.js";
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-SCTQMM7Z.js");
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-SCTQMM7Z.js");
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-SCTQMM7Z.js");
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-SCTQMM7Z.js");
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-SCTQMM7Z.js");
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/compose-review.ts
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/transcripts.ts
4841
+ // packages/cli/src/commands/review/lib/gh.ts
4842
4842
  init_esbuild_shims();
4843
- import { readFileSync as readFileSync5, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
4844
- import { join as join6 } from "node:path";
4845
- var TranscriptsUnavailableError = class extends Error {
4846
- static {
4847
- __name(this, "TranscriptsUnavailableError");
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(isErrorPart, "isErrorPart");
4880
- function rangeOf(args) {
4881
- const offset = args["offset"];
4882
- const limit = args["limit"];
4883
- if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
4884
- return null;
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(rangeOf, "rangeOf");
4890
- function parseTranscript(file, diffPath) {
4891
- let raw;
4892
- try {
4893
- raw = readFileSync5(file, "utf8");
4894
- } catch {
4895
- return null;
4896
- }
4897
- const lines = raw.split("\n").filter((l) => l.trim());
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
- rec = JSON.parse(line);
4914
- } catch {
4915
- continue;
4916
- }
4917
- if (!agentId && typeof rec["agentId"] === "string")
4918
- agentId = rec["agentId"];
4919
- if (!agentName && typeof rec["agentName"] === "string") {
4920
- agentName = rec["agentName"];
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
- if (!isErrorPart(part)) {
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(parseTranscript, "parseTranscript");
4987
- function listAgentTranscriptFiles(dir) {
4988
- return readdirSync3(dir).filter((name) => name.endsWith(".jsonl"));
4989
- }
4990
- __name(listAgentTranscriptFiles, "listAgentTranscriptFiles");
4991
- function readTranscripts(since, env = process.env, diffPath) {
4992
- const dir = transcriptDir(env);
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
- const out = [];
5002
- for (const name of names) {
5003
- const rec = parseTranscript(join6(dir, name), diffPath);
5004
- if (!rec) continue;
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
- return out;
4894
+ ghHost = host;
5009
4895
  }
5010
- __name(readTranscripts, "readTranscripts");
5011
- function wasGivenTheDiff(rec, diffPath) {
5012
- const p = rec.launchPrompt;
5013
- if (!p) return false;
5014
- return p.includes(diffPath);
4896
+ __name(setGhHost, "setGhHost");
4897
+ function getGhHost() {
4898
+ return ghHost;
5015
4899
  }
5016
- __name(wasGivenTheDiff, "wasGivenTheDiff");
5017
-
5018
- // packages/cli/src/commands/review/lib/prompt-record.ts
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(promptRecordDir, "promptRecordDir");
5033
- var fileFor = /* @__PURE__ */ __name((key) => `${encodeURIComponent(key)}.txt`, "fileFor");
5034
- function briefPath(planPath, key) {
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(briefPath, "briefPath");
5038
- function findingsFilePath(planPath, key) {
5039
- return join7(
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(findingsFilePath, "findingsFilePath");
5045
- function findingsPointerOf(prompt) {
5046
- const m = /^read_file\(file_path="([^"]*\.findings\.md)"\)$/m.exec(prompt);
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(findingsPointerOf, "findingsPointerOf");
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 rmSync2,
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
- rmSync2(d, { recursive: true, force: true });
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
- return parsed;
6846
- } catch {
6847
- return null;
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(readBudgetStop, "readBudgetStop");
6851
- function reverseAuditBudgetMessage(spent, round) {
6852
- const minutesLeft = Math.max(0, Math.floor(spent.remainingSeconds / 60));
6853
- const reserveMinutes = Math.round(spent.reserveSeconds / 60);
6854
- const roundMinutes = Math.round(spent.expectedRoundSeconds / 60);
6855
- const which = round !== void 0 ? `round ${round}` : "the next round";
6856
- 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.`;
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(reverseAuditBudgetMessage, "reverseAuditBudgetMessage");
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
- return values;
7548
- }
7549
- __name(parseNdjson, "parseNdjson");
7550
- function currentUser() {
7551
- return gh("api", "user", "--jq", ".login");
7552
- }
7553
- __name(currentUser, "currentUser");
7554
- function ensureAuthenticated() {
7555
- for (let attempt = 0; ; attempt++) {
7556
- try {
7557
- execFileSync2("gh", ["auth", "status"], { stdio: "pipe", env: ghEnv() });
7558
- return;
7559
- } catch (err) {
7560
- if (attempt === 0 && err.code !== "ENOENT") {
7561
- sleepSync(2e3);
7562
- continue;
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(ensureAuthenticated, "ensureAuthenticated");
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 && !findingsUnverifiedAtCompose;
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 existsSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
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 (existsSync4(resolve6(testDelta))) {
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 ?? (process.env["GH_HOST"]?.trim() || void 0);
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. Build every whole-diff agent's prompt with \`"\${QWEN_CODE_CLI:-qwen}" review agent-prompt --plan ${shellQuotePath(args.plan)} --whole-diff\` and paste it verbatim ahead of its brief.`
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 receipt = DRY_RECEIPT_RE.exec(text);
13301
- if (rec.successfulToolCalls > 0 && rec.diffToolCalls > 0 && openedTheTerritory(rec.diffReads, territory) && receipt !== null && substantiveClause(receipt[1] ?? "")) {
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. Same resolution as
16952
- // publish-assets.
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-G75R6FOA.js"),
20447
- import("./updateCheck-PCUTVRFE.js"),
20448
- import("./installationInfo-ZTMTMYNW.js"),
20449
- import("./standalone-update-HLYOLX6V.js"),
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-KF3GKNWW.js");
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),