@qwen-code/qwen-code 0.21.7 → 0.21.8

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