@qwen-code/qwen-code 0.23.2 → 0.23.3-nightly.20260911.aaa6a32aae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -15
- package/bundled/computer-use/SKILL.md +1 -1
- package/bundled/goal-draft/SKILL.md +10 -10
- package/bundled/qc-helper/docs/configuration/model-providers.md +66 -28
- package/bundled/qc-helper/docs/configuration/settings.md +8 -3
- package/bundled/qc-helper/docs/features/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +0 -20
- package/bundled/qc-helper/docs/features/channels/dws.md +7 -1
- package/bundled/qc-helper/docs/features/channels/overview.md +5 -6
- package/bundled/qc-helper/docs/features/commands.md +62 -9
- package/bundled/qc-helper/docs/features/computer-use.md +1 -1
- package/bundled/qc-helper/docs/features/cross-session-protocol.md +338 -0
- package/bundled/qc-helper/docs/features/goals.md +22 -18
- package/bundled/qc-helper/docs/features/hooks.md +28 -22
- package/bundled/qc-helper/docs/features/sub-agents.md +27 -0
- package/bundled/qc-helper/docs/qwen-serve.md +23 -6
- package/bundled/review/SKILL.md +93 -80
- package/bundled/review/references/persistence.md +2 -0
- package/bundled/review/references/posting.md +31 -14
- package/bundled/workflow-authoring/SKILL.md +410 -0
- package/bundled/workflow-creator/SKILL.md +1 -1
- package/chunks/{MaxSizedBox-4C3BKKKY.js → MaxSizedBox-7C5XTBZI.js} +64 -53
- package/chunks/{StandaloneSessionPicker-TXVF65YW.js → StandaloneSessionPicker-IGTT3ZRX.js} +88 -76
- package/chunks/{acp-startup-profiler-KEU6VAYR.js → acp-startup-profiler-RUQNTNU5.js} +2 -2
- package/chunks/acp-subagent-executor-IUHVNVVO.js +140 -0
- package/chunks/{acpAgent-H5XBKGB4.js → acpAgent-W43WM2K4.js} +957 -243
- package/chunks/{agent-T5LEFJIU.js → agent-2XMXC5JW.js} +48 -38
- package/chunks/{agent-headless-VZKSRH36.js → agent-headless-2HHBVCP6.js} +48 -38
- package/chunks/{anthropicContentGenerator-PRJWWVYJ.js → anthropicContentGenerator-7RI3MPIW.js} +69 -36
- package/chunks/{artifact-tool-G5LHNECG.js → artifact-tool-HHVHCPNG.js} +59 -109
- package/chunks/{askUserQuestion-I5W5S3D6.js → askUserQuestion-RFMXTD3B.js} +2 -2
- package/chunks/{bridge-AOX5IY44.js → bridge-ID6N4IH5.js} +69 -58
- package/chunks/{ca-KC2AISNS.js → ca-MX3WCEEG.js} +1 -1
- package/chunks/{channel-management-service-MWQGHPAS.js → channel-management-service-ASCXI7FR.js} +6 -6
- package/chunks/{channel-settings-store-XZCGDGHW.js → channel-settings-store-TPJFQAZY.js} +76 -65
- package/chunks/{channel-worker-group-SQ5FRWOH.js → channel-worker-group-JR6JOELM.js} +9 -9
- package/chunks/{channel-worker-manager-TU4ZNWOE.js → channel-worker-manager-AVKJEZFL.js} +19 -10
- package/chunks/{channel-worker-supervisor-EMITFMCP.js → channel-worker-supervisor-OOYY7BAQ.js} +7 -7
- package/chunks/{chunk-4WMGYG3F.js → chunk-22FWWGSM.js} +2 -2
- package/chunks/{chunk-LWX4WDFF.js → chunk-2S5RIGZJ.js} +43 -15
- package/chunks/{chunk-CLKE4IY3.js → chunk-2SZH22YO.js} +1 -1
- package/chunks/{chunk-HJ5UJQQL.js → chunk-2UKKQGRA.js} +3639 -1804
- package/chunks/{chunk-MWIO7MF6.js → chunk-2WSLXP3W.js} +4 -0
- package/chunks/{chunk-HNLMYDQE.js → chunk-33LYAC4R.js} +10 -6
- package/chunks/{chunk-VBLAI2HA.js → chunk-3FPYT6QC.js} +0 -31
- package/chunks/{chunk-F53KKZUD.js → chunk-3LMDSCLU.js} +158 -10
- package/chunks/{chunk-WXFCI3O5.js → chunk-3MAUPOZ4.js} +2 -2
- package/chunks/{chunk-CRZBDVP2.js → chunk-432JQKIO.js} +10 -10
- package/chunks/{chunk-IRGDIDGJ.js → chunk-43RQ552L.js} +364 -84
- package/chunks/{chunk-PFKGV6PO.js → chunk-465USTVK.js} +9 -15
- package/chunks/{chunk-WG7BL3FY.js → chunk-473RJLIH.js} +1 -1
- package/chunks/{chunk-J3VZF2AL.js → chunk-4O2AXZXU.js} +2 -2
- package/chunks/{chunk-N6S3NUYJ.js → chunk-55VOWZ4C.js} +1 -1
- package/chunks/{chunk-OWCFKIFQ.js → chunk-5CZMWDJI.js} +2 -2
- package/chunks/{chunk-7NDZKE2M.js → chunk-5MUIHID6.js} +5 -5
- package/chunks/{chunk-RM244SCQ.js → chunk-5Z74GE4N.js} +1 -1
- package/chunks/{chunk-G5VOXCRX.js → chunk-6375QMAO.js} +2 -2
- package/chunks/{chunk-3LPJ776W.js → chunk-63GQZKXL.js} +164 -31
- package/chunks/{chunk-O2FEO2CB.js → chunk-6GDELAVL.js} +18 -2
- package/chunks/{chunk-7PD7ZMX5.js → chunk-6HI2I3OM.js} +168 -6
- package/chunks/{chunk-CALNF3Z3.js → chunk-7C57HCOR.js} +1 -1
- package/chunks/{chunk-UYDQYDW2.js → chunk-7IBS746B.js} +1 -1
- package/chunks/{chunk-AUTUFD5X.js → chunk-ABNX6E6K.js} +1 -1
- package/chunks/chunk-ACHCT36C.js +28 -0
- package/chunks/{chunk-2WC3Y7YY.js → chunk-AEY27Z35.js} +401 -23
- package/chunks/{chunk-AO2VMS72.js → chunk-AQFRRH73.js} +3 -3
- package/chunks/{chunk-PDN7FJZV.js → chunk-ASWEMQIZ.js} +4 -4
- package/chunks/chunk-AYEJOTIU.js +43 -0
- package/chunks/{chunk-QFJZAY7W.js → chunk-BKFRA4F5.js} +5 -5
- package/chunks/{chunk-KCF2436G.js → chunk-BNLW5N6U.js} +4 -4
- package/chunks/{chunk-GOKAOSCN.js → chunk-BRFOZEPA.js} +2 -2
- package/chunks/{process-registry-OAEG6WGC.js → chunk-BYUAT5OC.js} +1 -0
- package/chunks/chunk-C5CECJ46.js +340 -0
- package/chunks/{chunk-NOO4QFXM.js → chunk-C75BXMPM.js} +1 -3
- package/chunks/chunk-CAAMI77K.js +937 -0
- package/chunks/{chunk-QTB4VP4K.js → chunk-CBGHRAWM.js} +304 -23
- package/chunks/chunk-CF5KXZZX.js +150 -0
- package/chunks/chunk-CFMZLE3L.js +75 -0
- package/chunks/{chunk-TGNNLRC3.js → chunk-CJ3DHN5I.js} +1 -0
- package/chunks/{chunk-ERXNTINK.js → chunk-CQZJYGRX.js} +1 -1
- package/chunks/{chunk-WBU2PIZ5.js → chunk-CSDKDHWV.js} +23 -16
- package/chunks/{chunk-2EKVPSIJ.js → chunk-D754KKNZ.js} +9 -2
- package/chunks/{chunk-E6TI726I.js → chunk-DGC7BKEZ.js} +1 -1
- package/chunks/{chunk-7SVM3RP2.js → chunk-DMMOQWRF.js} +4 -6
- package/chunks/{chunk-J3TJH52D.js → chunk-DOTF2PF2.js} +1 -1
- package/chunks/{chunk-2BMXHB6N.js → chunk-DWBNQR53.js} +7 -7
- package/chunks/{chunk-ZN5TKAVR.js → chunk-E5LTUWKZ.js} +3 -3
- package/chunks/chunk-EGW3ZP6Y.js +32 -0
- package/chunks/chunk-ELRMZTPF.js +374 -0
- package/chunks/{chunk-RNAJVXUG.js → chunk-ENAUXRPG.js} +6 -6
- package/chunks/{chunk-WXD7INFV.js → chunk-EO4U2X47.js} +10 -8
- package/chunks/{chunk-WDVV3LRM.js → chunk-EPVEPTI3.js} +45 -152
- package/chunks/chunk-ERU3SDXT.js +27 -0
- package/chunks/{chunk-4HOEU2OR.js → chunk-EWJTAP3Y.js} +1 -19
- package/chunks/{chunk-GSFV5RQW.js → chunk-EYN3G5XD.js} +328 -4
- package/chunks/{chunk-QB3KS3N3.js → chunk-FGROOEKM.js} +5 -40
- package/chunks/{chunk-TOOOLHVS.js → chunk-FH5AVEWJ.js} +3 -3
- package/chunks/{chunk-DAI65CMX.js → chunk-FJZWRNEW.js} +1 -1
- package/chunks/{chunk-GNY7B3CA.js → chunk-FUQK5ZNL.js} +1 -1
- package/chunks/{chunk-GOEVQADN.js → chunk-GDIPPCW6.js} +330 -175
- package/chunks/{chunk-ALMR3E6Q.js → chunk-GDWE23OR.js} +3 -3
- package/chunks/{chunk-LNYV4GXX.js → chunk-GSKX53AN.js} +0 -139
- package/chunks/{chunk-ELD3OBPU.js → chunk-GWOVD63C.js} +3 -3
- package/chunks/{chunk-IWABUX6T.js → chunk-GX5FF2IE.js} +6 -6
- package/chunks/{chunk-22GORRNY.js → chunk-GZMNHAYC.js} +1 -1
- package/chunks/{chunk-YZTGGCEE.js → chunk-H3TFIFX3.js} +1 -1
- package/chunks/{chunk-6G4V7SE4.js → chunk-HG46TTAG.js} +1 -1
- package/chunks/{chunk-FETY36NQ.js → chunk-HGEUHUEV.js} +1 -1
- package/chunks/{chunk-KEPC5BOL.js → chunk-IBRQG2MP.js} +12 -15
- package/chunks/{chunk-OXR34GCD.js → chunk-IILWL3KY.js} +2054 -146
- package/chunks/{chunk-IW6RQPQB.js → chunk-IJOS26LH.js} +1 -3
- package/chunks/{chunk-ORFIYTI2.js → chunk-IK2MWJP5.js} +1 -1
- package/chunks/{chunk-CMWU6P4D.js → chunk-IRJRB3OD.js} +1 -1
- package/chunks/{chunk-QHLHE2OT.js → chunk-IUN5ZMFY.js} +1 -1
- package/chunks/{chunk-LYT2OU7D.js → chunk-IXXV6BVB.js} +172 -6
- package/chunks/{chunk-R3JIDRUL.js → chunk-J6H4JP25.js} +4 -4
- package/chunks/{chunk-NB3NDQQK.js → chunk-J6SBP5G2.js} +1 -1
- package/chunks/{chunk-TRQNRP2H.js → chunk-J7LBAKDH.js} +46 -3
- package/chunks/{chunk-67XTVRVB.js → chunk-JJFHISXU.js} +30 -25
- package/chunks/chunk-JL6APGBX.js +43 -0
- package/chunks/{chunk-NX7ZTXFF.js → chunk-JSKEW4E7.js} +2 -1
- package/chunks/{chunk-BK7D2JR6.js → chunk-JVTXAA35.js} +3 -3
- package/chunks/chunk-K2OJUPOE.js +78 -0
- package/chunks/{chunk-G3ZUMSFS.js → chunk-K3U6VB3O.js} +6 -6
- package/chunks/{chunk-4I3WFI3U.js → chunk-K4KWLF7Q.js} +12 -12
- package/chunks/{chunk-WXPPUPHM.js → chunk-KWFFJ6AK.js} +1 -1
- package/chunks/{chunk-46MMBZHI.js → chunk-KZYOFJ6V.js} +4 -4
- package/chunks/{chunk-ULZECEIP.js → chunk-LDQHA6L4.js} +2 -20
- package/chunks/{chunk-7LTCFO6T.js → chunk-LQBAFO5D.js} +6 -5
- package/chunks/{chunk-SOA4HKRJ.js → chunk-LT2XFADM.js} +2 -2
- package/chunks/{chunk-JYGIJA4W.js → chunk-LWWRJRCD.js} +1 -1
- package/chunks/{chunk-YQGW3M6Z.js → chunk-MFQWRBFB.js} +5 -5
- package/chunks/{chunk-TODNHE76.js → chunk-MUFGTWQH.js} +5 -5
- package/chunks/{chunk-5DQ4YTIZ.js → chunk-MV5XRRML.js} +3 -3
- package/chunks/{chunk-IR6JKBAP.js → chunk-NOUK63IR.js} +2 -2
- package/chunks/{chunk-XQ4RDO5B.js → chunk-NV77SEX3.js} +1 -1
- package/chunks/{chunk-OFVAS4AR.js → chunk-NWDPOFJI.js} +2 -2
- package/chunks/chunk-NY6OPAPS.js +820 -0
- package/chunks/{chunk-WDN64MVT.js → chunk-O5VX66FB.js} +127 -18
- package/chunks/{chunk-MV5DTLJV.js → chunk-OHCR4O3U.js} +1 -1
- package/chunks/{chunk-LEAOJ43M.js → chunk-OKOPKQ2X.js} +1310 -2107
- package/chunks/{chunk-B25JYXZE.js → chunk-ONLJBOI2.js} +971 -17
- package/chunks/{chunk-QQK4L3UU.js → chunk-OWUAZXXN.js} +132 -26
- package/chunks/{chunk-R457KFV7.js → chunk-P42IUOAO.js} +3 -3
- package/chunks/{chunk-LUNC5KCL.js → chunk-PRELUGCQ.js} +214 -39
- package/chunks/{chunk-5OZUKLL7.js → chunk-QSMQKTXV.js} +4 -4
- package/chunks/{chunk-FAJPLSYF.js → chunk-QTQYLQ5A.js} +85 -81
- package/chunks/{chunk-CALTQWTZ.js → chunk-QVZDV4ZS.js} +2 -2
- package/chunks/{chunk-J6MB5ZHZ.js → chunk-QZW6WRB7.js} +2 -1
- package/chunks/{chunk-KFECPHLV.js → chunk-RBWAGV73.js} +3 -3
- package/chunks/{chunk-4VY3ITHR.js → chunk-RF5RQRTD.js} +3 -3
- package/chunks/{chunk-HIXUUCGY.js → chunk-RPMXMR6U.js} +2 -2
- package/chunks/{chunk-3OAXF3UK.js → chunk-RRQEZBL2.js} +3756 -1343
- package/chunks/{chunk-4ALNJDHL.js → chunk-RSGEAWFJ.js} +19 -1
- package/chunks/{chunk-5BH2AIEY.js → chunk-RUE62UH6.js} +2 -2
- package/chunks/{chunk-PQEISIKS.js → chunk-SAH4BD2J.js} +0 -67
- package/chunks/{chunk-A7EFXK7P.js → chunk-SAOJHRWY.js} +2 -2
- package/chunks/{chunk-JO77FGNZ.js → chunk-SDUIETBG.js} +19 -7
- package/chunks/{chunk-6RZX2HIH.js → chunk-TBEXLLAO.js} +2 -2
- package/chunks/{chunk-PSPAM24S.js → chunk-TBSCTWKF.js} +6 -0
- package/chunks/{chunk-HRPFBHW7.js → chunk-TPKQIA7G.js} +1 -0
- package/chunks/{chunk-XDNFODER.js → chunk-TUIW5LLK.js} +1 -1
- package/chunks/{chunk-APXIW2TF.js → chunk-TVV5FA3G.js} +4 -4
- package/chunks/chunk-U6H3XTFA.js +95 -0
- package/chunks/{chunk-S5QR6CB5.js → chunk-UKMWZ5NS.js} +108 -887
- package/chunks/{chunk-U6REWGVR.js → chunk-VG2BRSEK.js} +2 -2
- package/chunks/chunk-VGBOJH2D.js +127 -0
- package/chunks/chunk-VGY2RGXL.js +100 -0
- package/chunks/{chunk-ZP5XDLSA.js → chunk-VLWG3EHY.js} +12 -12
- package/chunks/{chunk-4JNHNVAZ.js → chunk-W547PYQ7.js} +9 -4
- package/chunks/{chunk-7VEYUF3N.js → chunk-W5ZQMAEM.js} +1 -1
- package/chunks/{chunk-QAZ2MGYT.js → chunk-W7JJLUSB.js} +2 -2
- package/chunks/{chunk-CCBTNJB4.js → chunk-W7Q7XDQI.js} +39 -27
- package/chunks/{chunk-DARWOZY6.js → chunk-WD6YQI5M.js} +1 -1
- package/chunks/{chunk-F2NYVASI.js → chunk-WXAWG3JS.js} +30 -13
- package/chunks/{chunk-NPKCVSXX.js → chunk-XB5JRCAM.js} +11 -9
- package/chunks/{chunk-XSOXPG2L.js → chunk-XE46RQFI.js} +136 -8
- package/chunks/{chunk-QTNCGZHQ.js → chunk-XX5HQLCZ.js} +16 -0
- package/chunks/{chunk-2Z3T52OC.js → chunk-Y5TM7SBV.js} +7 -2
- package/chunks/chunk-YC6XOB5N.js +691 -0
- package/chunks/{chunk-CWVZBIZJ.js → chunk-YDW4ERSS.js} +1 -1
- package/chunks/{chunk-TRWQQBVH.js → chunk-YGCTOXUT.js} +10 -24
- package/chunks/{chunk-WK7P62DV.js → chunk-YKC67ZEF.js} +6 -6
- package/chunks/{chunk-KA5HR3G2.js → chunk-YKM6MITI.js} +5 -5
- package/chunks/{chunk-X7LFJF5D.js → chunk-YM6KUQ2S.js} +36 -84
- package/chunks/{chunk-HZ2HUXX7.js → chunk-YS2ZJSOA.js} +29 -12
- package/chunks/{chunk-G37O7YO6.js → chunk-ZAWM6KRF.js} +3 -3
- package/chunks/{chunk-H3Q3RSKZ.js → chunk-ZFIWHBJ3.js} +1 -1
- package/chunks/{chunk-XBVNNDPK.js → chunk-ZHKTKHMO.js} +8 -1
- package/chunks/{chunk-YLOHCA6I.js → chunk-ZKWO4CF4.js} +2 -2
- package/chunks/{chunk-VJJXG73H.js → chunk-ZMQL5BL5.js} +21 -6
- package/chunks/{chunk-FGHPZGOP.js → chunk-ZMUYBOYB.js} +39 -55
- package/chunks/{chunk-FV4DM2M4.js → chunk-ZNI3YJHS.js} +26 -6
- package/chunks/{chunk-565U2ANU.js → chunk-ZTTC7T4X.js} +1 -1
- package/chunks/{chunk-7OCIQNKX.js → chunk-ZW2EUO2A.js} +1 -1
- package/chunks/codex-subagent-executor-26XOHVKH.js +585 -0
- package/chunks/{config-utils-GPLIABL2.js → config-utils-JUG3MOYN.js} +68 -57
- package/chunks/{contextCommand-NCUQUDBY.js → contextCommand-6K3POZFA.js} +65 -54
- package/chunks/{core-runtime-WKYKWVYU.js → core-runtime-XQFZLA2V.js} +66 -55
- package/chunks/{create-sub-session-TGIX63YU.js → create-sub-session-4UJ6RM6W.js} +5 -2
- package/chunks/{create-sub-session-PPLXB3JJ.js → create-sub-session-T4IYIOC7.js} +178 -91
- package/chunks/{cron-create-GTPVMJCF.js → cron-create-6466RWSO.js} +2 -2
- package/chunks/{cron-delete-ZBK27Z4K.js → cron-delete-W4QUWHOA.js} +2 -2
- package/chunks/{cron-list-KTFKFDKC.js → cron-list-Q5LJ5PZE.js} +2 -2
- package/chunks/{daemon-2CKIAO3I.js → daemon-PHPJUXDZ.js} +4 -2
- package/chunks/{daemon-git-worktree-guard-73ZWOLKL.js → daemon-git-worktree-guard-5WEMZ64U.js} +65 -54
- package/chunks/{daemon-status-provider-OK7VONJG.js → daemon-status-provider-GMD7QD4T.js} +74 -63
- package/chunks/{daemon-trust-policy-CAUCREG2.js → daemon-trust-policy-IPBZES2Z.js} +71 -60
- package/chunks/{daemon-trust-policy-monitor-3Y36OOEQ.js → daemon-trust-policy-monitor-MHYEN7X7.js} +71 -60
- package/chunks/{de-UU2YTO37.js → de-OOLZAU2U.js} +1 -1
- package/chunks/{deferred-core-runtime-Q7WFWYD3.js → deferred-core-runtime-CY43FZNZ.js} +63 -52
- package/chunks/{discovery-XP4RMDUM.js → discovery-5KUEPR65.js} +2 -2
- package/chunks/{display-image-CTNHJRZC.js → display-image-6AZIHP3J.js} +3 -3
- package/chunks/{dist-F34J4FZX.js → dist-2QYIVNS6.js} +2 -5
- package/chunks/{dist-6YDUH3BB.js → dist-GIMQXYLI.js} +10 -631
- package/chunks/{dist-NP7QKLVG.js → dist-GUB7QRYA.js} +3 -6
- package/chunks/{dist-Y5KC3IHW.js → dist-L45UB6DG.js} +233 -35
- package/chunks/{dist-XLV33CLY.js → dist-MPUZZOG5.js} +5 -18
- package/chunks/{dist-ZDNJK74R.js → dist-PA7WPFVE.js} +6 -37
- package/chunks/{dist-F6JLAJLE.js → dist-T6DDPDLQ.js} +16 -36
- package/chunks/{dist-BNQVF565.js → dist-TFGETXFN.js} +14 -37
- package/chunks/{dist-UFTFGI6I.js → dist-VDLSBCLM.js} +2 -6
- package/chunks/{edit-YJD6IETK.js → edit-6NUP5IPX.js} +48 -38
- package/chunks/{en-YJNRUQG4.js → en-ZSZW3PZX.js} +4 -1
- package/chunks/{enter-worktree-YFTKHXHZ.js → enter-worktree-EETDMJRF.js} +5 -5
- package/chunks/{enterPlanMode-EFPVTWIH.js → enterPlanMode-AZHYHEII.js} +48 -38
- package/chunks/{environment-HP3AXFTB.js → environment-ON6GIQ4F.js} +66 -55
- package/chunks/{errors-22ON46G7.js → errors-DQE63SCC.js} +65 -54
- package/chunks/exec-66WQIVYU.js +505 -0
- package/chunks/{exit-worktree-NF2XEMES.js → exit-worktree-DIPJ6S55.js} +5 -5
- package/chunks/{exitPlanMode-MOQUNCBH.js → exitPlanMode-NHBV6LAI.js} +48 -38
- package/chunks/{fast-path-2X7BPMXX.js → fast-path-EPJSUZZC.js} +7 -7
- package/chunks/{fast-path-settings-SATXY3PD.js → fast-path-settings-XDYX7X5Z.js} +2 -2
- package/chunks/{fr-HKNWVXRJ.js → fr-JJWM2HUS.js} +1 -1
- package/chunks/{glob-Y7ACIB3P.js → glob-MNEXQ2NV.js} +51 -41
- package/chunks/{goal-tools-DABMICUC.js → goal-tools-D2A4QBCJ.js} +54 -40
- package/chunks/{grep-BLHF2S5D.js → grep-EFWPV3MM.js} +2 -2
- package/chunks/{handleAutoUpdate-MCAMHYDI.js → handleAutoUpdate-2RY3OQA6.js} +67 -56
- package/chunks/{i18n-C3GDCALP.js → i18n-HTHDB3I7.js} +64 -53
- package/chunks/{image-gen-XP4NNIYG.js → image-gen-2PHED3P4.js} +8 -6
- package/chunks/{initializer-4URDQL2G.js → initializer-JEVLJCQA.js} +71 -60
- package/chunks/{installationInfo-LBOL6SBV.js → installationInfo-ITRB6J4L.js} +63 -52
- package/chunks/{ja-GJS5RZGU.js → ja-L67TXFDJ.js} +1 -1
- package/chunks/list-KOUIMHT5.js +133 -0
- package/chunks/{list-agents-2CXPGJUE.js → list-agents-IY4NEWLP.js} +17 -7
- package/chunks/{llm-2KPNSAVY.js → llm-F7WHGESY.js} +132 -120
- package/chunks/{llm-content-generator-GR3FOHLB.js → llm-content-generator-NYQ2NAVA.js} +6 -5
- package/chunks/{loadedSettingsAdapter-DVKROEJD.js → loadedSettingsAdapter-HZUAX5CX.js} +71 -60
- package/chunks/{loggingContentGenerator-P4K6K5W4.js → loggingContentGenerator-WMNU7C5J.js} +70 -59
- package/chunks/{loop-wakeup-HL6XOWI4.js → loop-wakeup-ANX25YW2.js} +3 -3
- package/chunks/{ls-YV7RKLKY.js → ls-4XCMJNZF.js} +4 -4
- package/chunks/{lsp-NO3AMRZT.js → lsp-K5E2Y64R.js} +1 -1
- package/chunks/{managed-npm-update-VWBKHNIN.js → managed-npm-update-EJJB65QI.js} +63 -52
- package/chunks/mcp-I73R6HS3.js +127 -0
- package/chunks/{monitor-A255TNZR.js → monitor-T56GJNA4.js} +50 -40
- package/chunks/{nonInteractiveCli-LXGIKQAT.js → nonInteractiveCli-CKHHJ423.js} +120 -109
- package/chunks/{notebook-edit-5UYHS2DM.js → notebook-edit-W5TU3EZ3.js} +48 -38
- package/chunks/openai-WX26N5OJ.js +47 -0
- package/chunks/{openaiContentGenerator-A6MAMEO5.js → openaiContentGenerator-TH6YAWAH.js} +33 -25
- package/chunks/openaiResponsesContentGenerator-EWLWQPKS.js +1738 -0
- package/chunks/{pidfile-B7DZC4TP.js → pidfile-RCC6TCEM.js} +63 -52
- package/chunks/process-registry-X6ZCASEN.js +10 -0
- package/chunks/{processUtils-BPZ2MCZS.js → processUtils-DQDQBRMC.js} +2 -2
- package/chunks/{prompt-terminal-ledger-FYYTAOXS.js → prompt-terminal-ledger-2LXWAGWU.js} +64 -53
- package/chunks/{pt-FXMYXEUV.js → pt-77SBDL4B.js} +1 -1
- package/chunks/{qwenContentGenerator-4IOJFD4S.js → qwenContentGenerator-LG65Z2YV.js} +61 -49
- package/chunks/{qwenOAuth2-KX6LVYQ3.js → qwenOAuth2-PJ63CCFD.js} +7 -5
- package/chunks/{read-file-A4H4O3VQ.js → read-file-72HMRUT4.js} +12 -9
- package/chunks/{read-mcp-resource-D3N75DGF.js → read-mcp-resource-NPF44YSC.js} +1 -1
- package/chunks/{record-artifact-Q5CRGJTP.js → record-artifact-MDXCCW2J.js} +3 -3
- package/chunks/record-source-VJLKDGGR.js +22 -0
- package/chunks/{report-findings-TJ34R7QK.js → report-findings-CZTYMZTC.js} +4 -4
- package/chunks/{request-shutdown-LRKMTBAD.js → request-shutdown-KOZHPVZU.js} +5 -5
- package/chunks/{resumeHistoryUtils-YQQ43E4N.js → resumeHistoryUtils-S2Q3M3EH.js} +69 -58
- package/chunks/{ripGrep-W32NWFTA.js → ripGrep-B2I3L5CO.js} +17 -13
- package/chunks/{ru-RMHURE5U.js → ru-UYWHKWF2.js} +1 -1
- package/chunks/{run-qwen-serve-WBSWWIRV.js → run-qwen-serve-AOPYFCVP.js} +305 -132
- package/chunks/{runtime-VRVBX2E5.js → runtime-TZMHKZAP.js} +77 -66
- package/chunks/{scheduled-tasks-D65KJDA3.js → scheduled-tasks-7RL6ZOYT.js} +72 -60
- package/chunks/{scheduler-M2YPN7Z7.js → scheduler-D6RLOFNU.js} +65 -54
- package/chunks/{sdk-exporters-grpc-MXTVSE3C.js → sdk-exporters-grpc-Y2ZUQDUQ.js} +2 -2
- package/chunks/{sdk-exporters-http-7R2ARBPV.js → sdk-exporters-http-VWTF4W6K.js} +3 -3
- package/chunks/{sdk-impl-YOLO7LV4.js → sdk-impl-G6FVTBQZ.js} +9 -9
- package/chunks/{send-message-76BKWKFZ.js → send-message-MMZVSS7P.js} +12 -9
- package/chunks/{serve-BE3H2P6P.js → serve-HWWDYI37.js} +72 -61
- package/chunks/{server-FLY5JERG.js → server-MD2X5U5L.js} +3156 -564
- package/chunks/{session-JVN62R5K.js → session-AFUMFNN7.js} +124 -113
- package/chunks/{session-attachments-root-7ACGLHXA.js → session-attachments-root-QPN3YWTY.js} +63 -52
- package/chunks/{session-pr-refresh-TQS57SDK.js → session-pr-refresh-4Y2ANMJX.js} +72 -60
- package/chunks/{settings-D44YMZFT.js → settings-QQRQ2LR7.js} +74 -63
- package/chunks/{shell-3VE6I4V5.js → shell-NUYUYMVI.js} +48 -38
- package/chunks/{skill-FHEGRRZU.js → skill-KHLDVOXW.js} +68 -30
- package/chunks/{skill-settings-VHEJMBFL.js → skill-settings-INLEGDEZ.js} +70 -59
- package/chunks/{spawnChannel-T6MX2ZDN.js → spawnChannel-KBGZHW2G.js} +67 -56
- package/chunks/{standalone-update-QUGHFMCS.js → standalone-update-3QP5NDVJ.js} +65 -54
- package/chunks/{start-opentui-ui-IHIIZ2LE.js → start-opentui-ui-VBT3XDWN.js} +2682 -2153
- package/chunks/{startInteractiveUI-LR7K2ARZ.js → startInteractiveUI-AZHKCHMR.js} +1562 -2317
- package/chunks/{syntheticOutput-D2P5V6RG.js → syntheticOutput-KRASPDE3.js} +2 -2
- package/chunks/{task-create-MWXJFRRM.js → task-create-TNXNT7ZD.js} +8 -8
- package/chunks/{task-list-EYO3FE57.js → task-list-FHNIJDKT.js} +1 -1
- package/chunks/{task-stop-BFSKRTGV.js → task-stop-MG4ZMTEI.js} +1 -1
- package/chunks/{task-update-2JJJRHMT.js → task-update-4HU62CJT.js} +8 -8
- package/chunks/{team-create-GY3VFY47.js → team-create-K5DNSJXR.js} +50 -40
- package/chunks/{team-delete-IQZ6XGFI.js → team-delete-2T44GUNN.js} +1 -1
- package/chunks/{team-plan-approval-BQPGZOT5.js → team-plan-approval-2ZNAQT2A.js} +48 -38
- package/chunks/{terminal-image-renderer-YNYW5CQG.js → terminal-image-renderer-23CW4A6Q.js} +65 -54
- package/chunks/{theme-manager-U6CIK3GM.js → theme-manager-G2333AMH.js} +63 -52
- package/chunks/{todoWrite-5ERKFWAK.js → todoWrite-BO2GR5MN.js} +4 -4
- package/chunks/{tool-search-XI3QWD5I.js → tool-search-MKQCKXN5.js} +22 -15
- package/chunks/{total-session-admission-3SNSJJ32.js → total-session-admission-ENKTM2KX.js} +69 -58
- package/chunks/{trustedFolders-OVAQKNV5.js → trustedFolders-2ETDL7OD.js} +64 -53
- package/chunks/{update-relaunch-XV5O74E3.js → update-relaunch-FMVNN5KA.js} +5 -5
- package/chunks/{updateCheck-CHUYWD6L.js → updateCheck-KWRV5KLJ.js} +66 -55
- package/chunks/{useAutoAcceptIndicator-VKSVIXZC.js → useAutoAcceptIndicator-7AUXAIQF.js} +73 -62
- package/chunks/{validateNonInterActiveAuth-ZNUTD3E5.js → validateNonInterActiveAuth-NETKLLDV.js} +117 -106
- package/chunks/{version-EK7VAGSI.js → version-DACNN2ZM.js} +1 -1
- package/chunks/{web-fetch-24KZO763.js → web-fetch-CIVCRET4.js} +16 -12
- package/chunks/{web-search-CRNXKZ2X.js → web-search-GOHZRGMM.js} +389 -327
- package/chunks/{web-shell-static-BFDESDD4.js → web-shell-static-T7UGLVE4.js} +2 -7
- package/chunks/workflow-IL2FOALZ.js +1324 -0
- package/chunks/workspace-providers-status-YGXL6N5U.js +131 -0
- package/chunks/{workspace-registration-store-HKLJEDQX.js → workspace-registration-store-E4IAOFFZ.js} +3 -1
- package/chunks/{workspace-registry-7RDDOBLN.js → workspace-registry-KX6BIBYK.js} +69 -58
- package/chunks/{workspace-runtime-coordinator-LEPDPXJO.js → workspace-runtime-coordinator-2KYYGDDR.js} +72 -59
- package/chunks/{workspace-service-5IFDCNN3.js → workspace-service-5Q6LWBYR.js} +76 -65
- package/chunks/{workspace-skills-status-FJ3HNH4H.js → workspace-skills-status-PJZTFPVV.js} +72 -61
- package/chunks/{workspace-trust-reconciler-PQFHIWLR.js → workspace-trust-reconciler-HS6PWNEA.js} +77 -66
- package/chunks/{write-file-ERG67ZFX.js → write-file-JB3DRM7O.js} +50 -40
- package/chunks/{zh-VBFCRQBL.js → zh-7UJA4ICT.js} +4 -1
- package/chunks/{zh-TW-N2TBF2F2.js → zh-TW-RV24PWUI.js} +4 -1
- package/chunks/{zoom-image-WQYEC3SR.js → zoom-image-AVHQFOOQ.js} +12 -9
- package/cli.js +16 -16
- package/codeModeHost.js +4425 -0
- package/export-transcript-document.css +1 -0
- package/export-transcript-document.js +164 -165
- package/locales/ca.js +2 -2
- package/locales/de.js +2 -2
- package/locales/en.js +5 -2
- package/locales/fr.js +2 -2
- package/locales/ja.js +2 -2
- package/locales/pt.js +2 -2
- package/locales/ru.js +2 -2
- package/locales/zh-TW.js +5 -2
- package/locales/zh.js +5 -2
- package/package.json +6 -4
- package/web-shell/assets/{abnfDiagram-VCTEODGH-BRLgQbnT.js → abnfDiagram-VCTEODGH-BH2nK5Z_.js} +1 -1
- package/web-shell/assets/{arc-qAF9_XsR.js → arc-CUUQ6krv.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-BorUttEz.js → architectureDiagram-5GKGNRK7-CJjiRuGx.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-Bj0qZVxu.js → blockDiagram-NRAW4CY4-GCDyU9ZX.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-BTqJis32.js → c4Diagram-UCG6FXSJ-C68MiN6h.js} +1 -1
- package/web-shell/assets/channel-DauVlmdF.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-RrQ5X8m-.js → chunk-2Q5K7J3B-_8B6frXZ.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-uUjDl8wO.js → chunk-5VM5RSS4-CroSinX7.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-C3JhpyzI.js → chunk-F27PBJKO-CGn4Z0Fx.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-C8ZNFs7F.js → chunk-G27WJ6UU-BI5nLQcf.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-DNpXtEOs.js → chunk-JWPE2WC7-CYJH0FuH.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-DagA2ZLw.js → chunk-LCL6LL3I-DjWZUqA1.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-R23uH7Xm.js → chunk-POPQ4Y6H-DcTkIHm8.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-Qz9RN_BR.js → chunk-SVP7TREG-E8sZT5uK.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-jYb1_hni.js → chunk-XXDRQBXY-CurjPKw_.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-BuIh7bj1.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-BuIh7bj1.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-Cv2OunpE.js → cose-bilkent-JH36ORCC-CJEnNhth.js} +1 -1
- package/web-shell/assets/{cynefin-OW5HDTMX-LH42KFJx.js → cynefin-OW5HDTMX-jwEkm0yw.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-Dha4_OoR.js → cynefinDiagram-5FMLGOSQ-B-OVQ6AO.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-Br5lnUKD.js → dagre-3AP2YEHR-CKKK9WNR.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-dpKq2bBX.js → diagram-S7CK7UJ4-D486veFQ.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-BAgHWpXr.js → diagram-UQ7AKVKN-C3GujqHv.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-GRRzpyE2.js → diagram-VSXAHHWV-BrOTDwuU.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-BNFiaYpG.js → diagram-VX7I27RA-C4D9kWE3.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-BisZzB_h.js → diagram-Z3DM3KII-7rAManT0.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-B1xbwycf.js → ebnfDiagram-PWID7BFC-CqVzKOdr.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-CQMzbGE5.js → erDiagram-SSCWMZ5O-D2s08fc_.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-CZ_Zondl.js → flowDiagram-A5DVABFB-CrKtBxB2.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-BTh2ShxS.js → ganttDiagram-EL5Y4UJY-CD1CKdlt.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-oHOB-Uxt.js → gitGraphDiagram-WWUBYQGX-CHDXdVNn.js} +1 -1
- package/web-shell/assets/index-D8tzgUOC.css +36 -0
- package/web-shell/assets/{index-DWoFMu5x.js → index-DWz95m74.js} +1 -1
- package/web-shell/assets/index-cDFf68Wd.js +2204 -0
- package/web-shell/assets/{infoDiagram-RXCK75RN-C0QpudbG.js → infoDiagram-RXCK75RN-Cr1oLCwe.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-a6B741uT.js → ishikawaDiagram-5VMMS53U--RghV1mm.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-Dbht9ICp.js → journeyDiagram-EYS64GPL-MN1ZkGW8.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-D4OFR8-h.js → kanban-definition-3QL26DDD-DL05VTn0.js} +1 -1
- package/web-shell/assets/{layout-Dvdh5jRH.js → layout-D_TvQzvn.js} +1 -1
- package/web-shell/assets/{linear-Dvc6KIW2.js → linear-B_0OH6XF.js} +1 -1
- package/web-shell/assets/{mermaid.core-CB36RfIb.js → mermaid.core-B9Nklh9I.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-Fmqo1CjP.js → mindmap-definition-FBJOCRG2-CevIQ0LR.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-CCxYBoA4.js → pegDiagram-XKGWAZYB-DQ8PIv0d.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-BVHKQFzt.js → pieDiagram-E7YTZNPT-BVTV1pPe.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-l95IznwR.js → quadrantDiagram-AXDQQJYC-DHN6nhpe.js} +1 -1
- package/web-shell/assets/qwen-code-notification-BRVagufF.png +0 -0
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-BlLdRdXp.js → railroadDiagram-O6MQD6OU-8HOyX0u-.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-BkDLBR5w.js → requirementDiagram-EFPCY7ZU-9W4_14i8.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-jAIqRp65.js → sankeyDiagram-P5KCCOFB-DSUBB2XP.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-f-soZYPr.js → sequenceDiagram-WJ2MYXX4-DD3jH6Jn.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-BzOuAfB2.js → sizeCapture-X5ZJPWSS-RAFTU3Cz.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-BPLSs12r.js → stateDiagram-HBIQ2CUA-Drk-oZ2x.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-QzYteVIm.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-D-9E_RIR.js → swimlanes-XN3QIQJK-Cy2nlOGx.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-xTr-HG26.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-CT56K-gV.js → timeline-definition-24CTP7MA-B7outYof.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-B-vi4IyO.js → vennDiagram-4TSXK5OY-Di_u1Ic6.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-C9O7Ju98.js → wardleyDiagram-VM6X3IG4-DYocuCAM.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-6d8w3jg2.js → xychartDiagram-S5SC5T6Z-AADDse54.js} +1 -1
- package/web-shell/index.html +29 -5
- package/chunks/chunk-V7RNNPGC.js +0 -44
- package/chunks/list-JOGBAC2R.js +0 -122
- package/chunks/mcp-6YYNSYLK.js +0 -116
- package/chunks/workflow-HD5NYMW5.js +0 -2907
- package/chunks/workspace-providers-status-MAM42IZS.js +0 -120
- package/web-shell/assets/channel-COIuCrVH.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-DoX6OYqu.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-DoX6OYqu.js +0 -1
- package/web-shell/assets/index-CI1ysIEv.js +0 -2154
- package/web-shell/assets/index-CpxXGH-8.css +0 -36
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-IRul-LaT.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-D6lgKepA.js +0 -8
- package/chunks/{chunk-JA5CBKRP.js → chunk-7NXSVSFB.js} +0 -0
- package/chunks/{open-with-auth-6MVIHMXB.js → open-with-auth-XFCCJOO6.js} +3 -3
|
@@ -72,6 +72,8 @@ The JSON helper is fail-closed because it carries the authoritative review resul
|
|
|
72
72
|
|
|
73
73
|
### Incremental review cache
|
|
74
74
|
|
|
75
|
+
The automatic `reviewProfile: "docs-nav"` pass never updates or promotes this cache. Its focused-coverage disclosure withholds the posted ledger's SHA/model anchor; preserve any earlier full-review cache unchanged.
|
|
76
|
+
|
|
75
77
|
If reviewing a PR **at high effort**, update the review cache for incremental review support. Low and medium reviews must NOT write it, and neither must a `--topology minimal` run at any effort — a cache hit would make a later high-effort review of the same SHA report "No new changes since last review", silently converting a cheaper pass into a full-review verdict.
|
|
76
78
|
|
|
77
79
|
**A local or file-path review at high effort writes its cache the same way, from the capture's candidate.** **Before promoting, CHECK the candidate is this round's own:** read the file at the plan's `cacheCandidatePath` and compare its `stateId` to the plan's `cacheCandidateStateId` — the path is stable per target and local/file reviews take no lease, so a concurrent same-target run overwrites the file mid-round, and promoting the foreign candidate would anchor the next round's "no changes" to a tree this round never reviewed. A mismatch (or an absent `cacheCandidateStateId` field on a plan that published a path) is treated exactly like a withheld candidate: skip the cache write and say so. `capture-local` wrote this round's content anchor to the plan's `cacheCandidatePath` (`.qwen/tmp/qwen-review-<target>-cache-candidate.json`): the hashed per-file state and HEAD of exactly what was captured, deterministic, not yours to recompute. Read that file, add the ledger fields — `lastReviewDate`, `round`, `findingsCount`, `verdict`, and `findings[]` under the same id-carrying rules as the PR cache below — and write the merged object to the path the capture named in its plan, `cachePath` — **read that field, do not compute the name**, for the reason the incremental bullet in Step 1 gives: `target` is derived inside the command and `safeTarget` is not hand-reproducible. **The fail-closed conditions here are keyed to the PR cache's marker rule below — one definition, read twice.** Do NOT apply that rule's literal CHECK here: it keys on a `sha` inside the posted review's `qwen-review-ledger` marker, and a local round posts nothing and has no marker to read — a literal check would skip this write on every round and the feature would never persist. What this write takes from that rule is its WITHHOLDING CONDITIONS, applied as conditions on this round's own caps. For a local or file-path round the rule is a POSITIVE one, deliberately — and its fail-closed half is deliberately NOT a list: the list that lived here was "completed" three times, and each time a fourth shape walked through it (the last one an Uncoverable chunk and a whiffed lens, which withheld the PR marker's `sha` but never this write). **Write the cache only when every Critical this round raised carries a confirmed disposition: fixed, or confirmed-standing and recorded in `findings[]` under an id — and skip this write under any condition that would withhold the PR marker's `sha` in the rule below, plus the one local-only condition the marker cannot see: a non-empty `skippedFiles` in the capture (skipped content is in no diff and no hash).** At the time of writing those conditions are: `cannotTellCriticals` (a verifier that returned CANNOT-TELL, or a deadline stop or timed-out batch that never returned one), an Uncoverable chunk, the context-unavailable state, `scopeUnproven` (a chunk nobody read, an idle or blind agent), a finding still marked `— [unverified]`, the deterministic gates, and any `unreviewedDimensions` entry other than a depth-only build-and-test one (a whiffed lens withholds the marker's `sha`, so it withholds this write). The examples are the set as written, not the gate: the gate is the marker paragraph's withholding set — if it changes, this write changes with it, because a second hand-copied list here is how they drifted once already. Anything else withholds the candidate and says so. The reason is one reason, and it is why the rule is stated as a rule: the anchor's whole claim is "the next round may skip this", and a claim nobody ruled on is exactly what the next round must not skip — the round after it stops decided over a Critical that was never verified: skipped content is in no diff and no hash, so a candidate promoted over it would anchor the next round's "no changes" past work this round could not read. A run that ended with unreviewed or undecided scope skips this write and says so, because the candidate would anchor the next round's skip past scope nobody reviewed. (A capture that detected a mid-capture tree change — or a tracked path carrying a visibility bit, or an enumeration of them that failed — withholds the candidate itself and says so; then there is nothing to promote.) Low and medium local reviews must NOT write it, for the PR cache's exact reason.
|
|
@@ -103,28 +103,45 @@ Read `.qwen/tmp/qwen-review-{target}-presubmit.json`. Schema:
|
|
|
103
103
|
existingComments: {
|
|
104
104
|
total: number;
|
|
105
105
|
byBucket: { stale, resolved, overlap, repost, noConflict: number };
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
106
|
+
// a top-level re-post target is ALSO an
|
|
107
|
+
// overlap and is counted in both; the
|
|
108
|
+
// pipeline's own carry-REPLY inside a
|
|
109
|
+
// replied-to thread appears in repost ONLY
|
|
110
|
+
// (an exemption carrier, never an overlap)
|
|
109
111
|
// Comment = { id, path, line, commit_id,
|
|
110
112
|
// body — an 80-char excerpt,
|
|
111
113
|
// user? — the author login when known }
|
|
112
114
|
overlap: Comment[]; // BLOCK on submit — except a finding whose
|
|
113
|
-
// id
|
|
114
|
-
//
|
|
115
|
+
// id appears in matchedIds of ANY repost
|
|
116
|
+
// entry, wherever that entry sits (see
|
|
117
|
+
// repost below)
|
|
115
118
|
repost: (Comment & { matchedIds: string[] })[];
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
119
|
+
// a ROOT leg's matchedIds are the ids of
|
|
120
|
+
// findings at that entry's own location; a
|
|
121
|
+
// carry-reply leg's are id-joined, and its
|
|
122
|
+
// path/line are the reply's own anchor
|
|
123
|
+
// (`original_line` when GitHub unmapped it,
|
|
124
|
+
// else 0) — never null
|
|
125
|
+
// re-post targets: overlap comments matched
|
|
126
|
+
// by a carried-id prefix in the claim line,
|
|
127
|
+
// or (when unambiguous) a truly id-less
|
|
128
|
+
// own-account original, at the finding's
|
|
129
|
+
// location; PLUS the pipeline's own carry-
|
|
130
|
+
// reply carrying a wanted id, at ANY
|
|
131
|
+
// location (in repost only) — exempt those
|
|
132
|
+
// findings from the drop (see below)
|
|
121
133
|
stale: Comment[]; // log "Skipped N stale ..."
|
|
122
134
|
resolved: Comment[]; // log "Skipped N replied-to ..."
|
|
123
135
|
noConflict: Comment[]; // log "Found N prior with no overlap ..."
|
|
124
136
|
};
|
|
125
137
|
downgradeApprove: boolean; // submit COMMENT instead of APPROVE
|
|
126
138
|
downgradeRequestChanges: boolean; // submit COMMENT instead of REQUEST_CHANGES (self-PR only)
|
|
127
|
-
downgradeReasons: string[]; // human-readable;
|
|
139
|
+
downgradeReasons: string[]; // human-readable; copy them into the
|
|
140
|
+
// compose state — `compose-review` caps
|
|
141
|
+
// each at 400 code points (a longer one
|
|
142
|
+
// is cut and ends in `…`), drops the
|
|
143
|
+
// ones past a 2000-point total, and
|
|
144
|
+
// joins and escapes what is left
|
|
128
145
|
blockOnExistingComments: boolean; // one or more overlaps — drop those findings
|
|
129
146
|
// (except carried-id re-posts, see below)
|
|
130
147
|
findingsFileInvalid: boolean; // the --new-findings file was unreadable:
|
|
@@ -150,9 +167,9 @@ Read `.qwen/tmp/qwen-review-{target}-presubmit.json`. Schema:
|
|
|
150
167
|
|
|
151
168
|
**Apply the report:**
|
|
152
169
|
|
|
153
|
-
- `blockOnExistingComments=true` → **an overlap is a duplicate; the disposal is deterministic — do not ask the user.** Drop each finding whose `(path, line)` appears in `existingComments.overlap` from your `comments` array — **except a finding whose `id` appears in `matchedIds` of
|
|
170
|
+
- `blockOnExistingComments=true` → **an overlap is a duplicate; the disposal is deterministic — do not ask the user.** Drop each finding whose `(path, line)` appears in `existingComments.overlap` from your `comments` array — **except a finding whose `id` appears in `matchedIds` of ANY `existingComments.repost` entry** — a root leg matches at the finding's `(path, line)`, while a carry-reply leg (the pipeline's own reply inside a replied-to thread) matches on the id alone and its own `path`/`line` are the REPLY's — `original_line` when GitHub unmapped the anchor, else `0`, never null — which is routinely not where the finding sits, so never re-check the location: that is a Step 6 ledger re-post, and re-posting under the original id is exactly how the id survives into the next round's marker. Keep it in the array — on GitHub, `submit` posts it as a **reply in that original thread** rather than a new inline comment (the Create Review API opens a new thread per comment; only the replies endpoint joins one), so the finding keeps one thread across rounds instead of accumulating one per round (GitHub only: an Aone target has no review-thread graph, and the re-post stays inline there). Whenever the posting pass cannot reach an unresolved thread this account opened under the id — a resolved or gone original, a foreign or id-less root, a `(fix-induced)` re-report, or a draft that finds every live thread under the id already answered this round — the re-post goes inline and opens a fresh thread; the exemption is what lets it through to do either. The inline counts follow automatically, because `submit` counts the comments you actually attach, so a dropped Critical is simply no longer there to count (and a dropped Critical that was already on the PR does not belong in `state.bodyCriticals` either). List each dropped finding in the terminal summary as "already reported at <path>:<line> — comment <id> (by <user>): <excerpt>", taking `<id>`, `<user>` (omit the `(by <user>)` slot when the entry carries no `user`), and the 80-char `<excerpt>` from the overlapping comment (`existingComments.overlap` entries carry all three), and submit the remainder without pausing. Naming the author is what makes an authorship-refused re-post exemption self-explanatory: the drop line then shows a DIFFERENT author next to the matching id. Name the comment on EVERY drop — that is what makes a same-line false positive visible to the operator instead of a bare location. This decision point has been improvised as an interactive question, which stalls a headless run forever (measured; DESIGN.md — The interactive overlap question); the Exclusion Criteria already forbid re-reporting discussed issues, so there is nothing to ask. (If dropping overlaps leaves zero findings, that is still not a question: submit with an empty `comments` array like any other run — `submit` composes the body from `state`, and a run with nothing to add posts whatever that computes. A recap like "all already reported, N resolved by `<sha>`, two still standing" goes in the **terminal summary**, not the PR: `compose-review` has no free-text body field to carry it (see Step 7 — you do not author PR-facing prose), and it is never a `gh pr comment` — a hand-posted issue comment bypasses the authorisation gate, the downgrade semantics, and the `posted` contract all at once.)
|
|
154
171
|
- `downgradeApprove` / `downgradeRequestChanges` / `downgradeReasons` → **do not apply these by hand.** Copy them into the `presubmit` field of the `compose-review` input (listed with the state fields in Step 6's Verdict section); the subcommand owns the semantics its tests pin — a downgrade fires only when the verdict it names is the one on the table (a Suggestion-only review is already Comment, so nothing is downgraded and no "Downgraded" sentence is emitted), the downgrade sentence carries the reasons, and a downgraded Request changes keeps its body Criticals after the sentence so the self-PR downgrade never erases the only copy of a blocker.
|
|
155
|
-
- `headDrift.drifted=true` → **commits nobody reviewed are on the PR; the verdict can no longer certify the pull request as it stands.** The Approve cap has already fired through the downgrade machinery (the reason names both SHAs — it rides into the body with the other reasons; never hand-apply). What happens to the _submission_ is decided by **`headDrift.anchorsAtRisk`, which presubmit computes — do not re-derive it by hand**: pass `--new-findings` so it has your anchors, and it rules fail-safe on every hole a hand intersection falls into (a truncated `filesTouched` list (measured; DESIGN.md — The 283-file drift cap), the compare API's own 300-file ceiling, a `diverged` force-push, an unavailable compare, or a missing findings list). **`--new-findings` must carry EVERY finding's file, not only the inline-anchored ones** — a body-only Critical (one that could not be mapped to a diff line) still names a file, and if that file is omitted a drift touching it reads as `anchorsAtRisk=false`; include one `{path, line}` per body Critical (any placeholder `line`, e.g. `1`, and NO `id` — the drift intersection keys on `path` only, but the carried-id re-post exemption
|
|
172
|
+
- `headDrift.drifted=true` → **commits nobody reviewed are on the PR; the verdict can no longer certify the pull request as it stands.** The Approve cap has already fired through the downgrade machinery (the reason names both SHAs — it rides into the body with the other reasons; never hand-apply). What happens to the _submission_ is decided by **`headDrift.anchorsAtRisk`, which presubmit computes — do not re-derive it by hand**: pass `--new-findings` so it has your anchors, and it rules fail-safe on every hole a hand intersection falls into (a truncated `filesTouched` list (measured; DESIGN.md — The 283-file drift cap), the compare API's own 300-file ceiling, a `diverged` force-push, an unavailable compare, or a missing findings list). **`--new-findings` must carry EVERY finding's file, not only the inline-anchored ones** — a body-only Critical (one that could not be mapped to a diff line) still names a file, and if that file is omitted a drift touching it reads as `anchorsAtRisk=false`; include one `{path, line}` per body Critical (any placeholder `line`, e.g. `1`, and NO `id` — the drift intersection keys on `path` only, but the carried-id re-post exemption joins on the id — a root leg at the finding's `(path, line)`, the pipeline's own carry-reply leg on the id alone at ANY location — so a placeholder entry carrying an id would match that id's thread from anywhere and corrupt the exemption; a body-only Critical is never posted inline and must never present as a re-post target). **`anchorsAtRisk=true`**: the anchors themselves are at risk and the findings may already be fixed — apply the 422-recovery rule _proactively_: abandon this submission, say so, and restart at the new SHA from Step 1's `fetch-pr`. **One exception — the CI salvage contract:** when the environment carries `QWEN_REVIEW_SALVAGE_POST=1` **and** the file named by `QWEN_CI_REVIEW_SALVAGE_OK_FILE` exists with content equal to `headDrift.reviewedSha`, the workflow's supersede watcher has already ruled this run salvage-eligible and a queued replacement run owns the new head — do **not** restart: submit as planned exactly as in the `anchorsAtRisk=false` branch (the review is of `fetchedSha`, the downgrade sentence names the drift, and the workflow's gh guard admits the post against that pinned head), and this consumes no restart. Either half missing — an explicit run exports no signal, and a marker alone is forgeable — and the rule above stands. **`anchorsAtRisk=false`**: submit as planned — the review is of `fetchedSha` (`submit` posts that very SHA as `commit_id`), the body's downgrade sentence says so, and if GitHub still answers 422 the recovery path below takes over. Name the drift in the terminal summary either way.
|
|
156
173
|
|
|
157
174
|
> **The restart bound is per-review and covers BOTH restart paths — this proactive drift restart AND the reactive 422 recovery below.** Track it as one fact: a review restarts **at most once** for head movement, whichever path triggers it. If a run that already restarted once reaches a drift restart _or_ a 422 again, do NOT restart a second time — submit at that run's reviewed SHA with the drift named (the Approve cap holds either way). A live PR that keeps moving must not be able to starve the review in an unbounded restart loop; one clean re-read is the review, a second is the PR outrunning it. One slice of this fact survives a resume: a `fetch-pr --resume` refused for `head-moved` records the restart beside the prompt records, and a later continuation reads it back as `restartsSpent` in the `resumed: true` line (Step 1) — arriving with `restartsSpent >= 1` means the bound is already spent. On a run that itself resumed, THIS restart's re-entry is such a refusal — Step 1's resume branch appends `--resume` to every Step 1 `fetch-pr`, so the re-entry sees the moved head, records the restart, and falls through to the fresh fetch the restart wants anyway. Only a never-resumed run's re-entry records nothing (a plain fresh `fetch-pr` rewrites the plan, which re-fences the marker) — within such a run the bound stays tracked here, in this transcript, exactly as before. Be aware of the one seam that leaves: a restart spent that way is invisible to a LATER attempt that resumes, which arrives with `restartsSpent: 0`. A fresh resuming process cannot know the earlier attempt restarted, so do not pretend it can — the on-disk bound is per-attempt, the per-REVIEW invariant is carried by the workflow's own MAX_ATTEMPTS ceiling, and the honest reading of `restartsSpent: 0` on a continuation is "no RECORDED restart", not "no restart".
|
|
158
175
|
|
|
@@ -168,7 +185,7 @@ Read `.qwen/tmp/qwen-review-{target}-presubmit.json`. Schema:
|
|
|
168
185
|
|
|
169
186
|
- **Self-PR**: GitHub rejects both `APPROVE` and `REQUEST_CHANGES` on your own PR (HTTP 422); `COMMENT` is the only accepted event. Critical and Suggestion findings still appear as inline `comments` regardless, so substantive feedback is preserved.
|
|
170
187
|
- **CI failure / pending**: the LLM review reads code statically and cannot see runtime test failures. Approving on red CI is misleading; pending CI means the verdict is premature.
|
|
171
|
-
- **Overlap with existing comments**: posting on the same `(path, line)` as an existing Qwen comment produces visual duplicates, so overlapping findings are dropped rather than re-posted — with one exception by construction: a carried-id re-post belongs in the original thread (
|
|
188
|
+
- **Overlap with existing comments**: posting on the same `(path, line)` as an existing Qwen comment produces visual duplicates, so overlapping findings are dropped rather than re-posted — with one exception by construction: a carried-id re-post belongs in the original thread, and `submit` puts it there (replying into the thread its ledger id names rather than opening a new one — same-line re-posts do NOT stack on their own, which is how one finding used to accumulate a thread per round), so a finding whose ledger id matches an own existing comment — a root at the finding's location, or the pipeline's own carry-reply in that id's thread, wherever its anchor now sits — is exempted via `existingComments.repost`, and every drop names the overlapping comment so a same-line false positive stays visible. The match reads the id as the claim-line PREFIX (mirroring how the ledger marker reads it back), and a truly id-less OWN-account original is still matched when the target is unambiguous — exactly one own-account comment at the location and exactly one carried finding there (round-1 originals carry no id token; without this fallback their re-post would read as a plain overlap and be dropped). **Known limitation — the residue is the AMBIGUOUS case only**: an id-less original at a location with several own-account comments, or several carried ids at the location, or an id-less original whose body still mentions ANY ledger-id-shaped token (even a cross-reference — any token marks the comment as belonging to a specific finding's thread, so the fallback stays off), cannot be matched as a re-post target; the re-post of such a finding reads as a plain location overlap and is dropped — visibly, the drop log names the comment. A same-SHA re-run after an already-posted re-post posts a second copy — under the reply mechanism, as a second reply in the same thread (the replied-to original is bucketed `resolved` and skipped by the overlap check, and the pipeline's own carry-reply inside that thread still carries the id as a `repost` exemption — so the re-post is not dropped even when another own comment overlaps the location); the thread stays one thread either way. A replied-to original still counts toward the ambiguity decision but is itself bucketed `resolved`, never a target. Stale-commit and replied-to comments are skipped silently — they're false-positive overlap from line-based matching.
|
|
172
189
|
|
|
173
190
|
⚠️ **Severity routing — high-confidence Critical AND Suggestion findings both go inline, pinned to the exact code line.** They are distinguished by the `**[Critical]**` / `**[Suggestion]**` prefix in the comment body, not by where they are posted.
|
|
174
191
|
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: workflow-authoring
|
|
3
|
+
description: Reference for writing a Workflow tool script (script API and gotchas, agent() options, pipeline() vs parallel(), verification and convergence patterns, resume, worked example). Load before authoring a script for a workflow the user already opted into; it does not itself authorize running one.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow authoring reference
|
|
7
|
+
|
|
8
|
+
Everything below is about _writing_ the script. Whether a workflow may run at
|
|
9
|
+
all is decided by the Workflow tool's own opt-in rule — this reference does
|
|
10
|
+
not authorize a run.
|
|
11
|
+
|
|
12
|
+
Reach for one to be comprehensive (decompose the work and cover every part in
|
|
13
|
+
parallel), to be confident (independent perspectives and adversarial checks
|
|
14
|
+
before an answer is committed to), or to take on scale a single context cannot
|
|
15
|
+
hold — migrations, audits, broad sweeps. The script is where that structure is
|
|
16
|
+
encoded: what fans out, what verifies, what synthesizes. Parallelism on its own
|
|
17
|
+
is not a reason; work that is already one short sequence of edits belongs in
|
|
18
|
+
the main loop.
|
|
19
|
+
|
|
20
|
+
## Scout first, then orchestrate
|
|
21
|
+
|
|
22
|
+
The strongest pattern is hybrid: discover the work list in the main loop (list
|
|
23
|
+
the files, scope the diff, read the failing test), then hand that list to a
|
|
24
|
+
workflow. You do not need to know the shape of the work before the task — only
|
|
25
|
+
before the orchestration step. When the work has distinct phases, run several
|
|
26
|
+
small workflows across turns and read each result before choosing the next,
|
|
27
|
+
rather than authoring one large script that runs unattended.
|
|
28
|
+
|
|
29
|
+
Common single-phase shapes: understand (parallel readers over subsystems,
|
|
30
|
+
merged into one map), design (independent approaches, judged, then
|
|
31
|
+
synthesized), review (dimensions, find, verify each finding), research (broad
|
|
32
|
+
sweep, deep read, synthesis), migrate (discover sites, transform each under
|
|
33
|
+
`isolation: 'worktree'`, verify).
|
|
34
|
+
|
|
35
|
+
## Script contract
|
|
36
|
+
|
|
37
|
+
The source is wrapped as an async IIFE, so top-level `await` and a top-level
|
|
38
|
+
`return` are both legal — and a trailing expression is _not_ a return value.
|
|
39
|
+
End every successful path with an explicit `return`.
|
|
40
|
+
|
|
41
|
+
It is plain JavaScript, not TypeScript, and it cannot `import` anything.
|
|
42
|
+
|
|
43
|
+
The script may start with a literal `export const meta = {...}` declaration
|
|
44
|
+
with `name`, `description`, and optionally `whenToUse` and
|
|
45
|
+
`phases: [{ title, detail? }]`. It must be a pure literal — no variables,
|
|
46
|
+
calls, or interpolation — and it is stripped before execution, so nothing in
|
|
47
|
+
the script body can read it. Fields outside that list are dropped. The
|
|
48
|
+
approval dialog prints the name, the description, and each phase title with
|
|
49
|
+
its `detail` as a one-line explanation beside it: give every phase a `detail`,
|
|
50
|
+
because for a run that may dispatch hundreds of agents it is what the user
|
|
51
|
+
reads before approving.
|
|
52
|
+
|
|
53
|
+
Injected globals, and nothing else:
|
|
54
|
+
|
|
55
|
+
- `phase(title)` — open a phase. Everything dispatched afterwards is attributed
|
|
56
|
+
to it in the live phase tree, until the next phase opens.
|
|
57
|
+
- `log(msg)` — one line into the run log the user watches.
|
|
58
|
+
- `agent(prompt, opts?)` — dispatch one subagent. See **agent() options**.
|
|
59
|
+
- `parallel(thunks)` — run thunks through the shared concurrency window,
|
|
60
|
+
resolving to a position-aligned array. `parallel()` itself rejects on
|
|
61
|
+
invalid arguments.
|
|
62
|
+
- `pipeline(items, ...stages)` — run each item through the stages
|
|
63
|
+
independently. See **Default to `pipeline()`**.
|
|
64
|
+
- `workflow(nameOrRef, args?)` — run a saved workflow inline. See **Saved
|
|
65
|
+
workflows and workflow()**.
|
|
66
|
+
- `args` — the structured value the caller passed, or `undefined`.
|
|
67
|
+
- `budget` — `budget.total` (`null` = uncapped) and `budget.spent()`.
|
|
68
|
+
|
|
69
|
+
Pass THUNKS to `parallel()`, not eager calls: `parallel([() => agent(...)])`,
|
|
70
|
+
not `parallel([agent(...)])`. The eager form is refused outright: a
|
|
71
|
+
non-function element rejects the whole batch, and by then every `agent()` in it
|
|
72
|
+
has already been admitted, counted against the caps, and spent — with its
|
|
73
|
+
result discarded.
|
|
74
|
+
|
|
75
|
+
A script must be deterministic so a resume replays the same call sequence.
|
|
76
|
+
`Math.random()` throws, and so does all of `Date` — `new Date()`,
|
|
77
|
+
`Date.now()`, `Date.parse()` and `Date.UTC()` alike. Pass timestamps in via
|
|
78
|
+
`args`, or stamp the result after the workflow returns.
|
|
79
|
+
|
|
80
|
+
Scripts run in a `node:vm` sandbox with no filesystem, shell, network, or
|
|
81
|
+
environment access. All I/O happens through the prompts you give the agents, so
|
|
82
|
+
say explicitly what each one should read and whether it may edit files.
|
|
83
|
+
|
|
84
|
+
## agent() options
|
|
85
|
+
|
|
86
|
+
`agent(prompt, { label?, phase?, schema?, model?, agentType?, isolation?, workingDir?, stallMs? })`
|
|
87
|
+
|
|
88
|
+
- `label` (string) — the name shown in the run views and the failures list.
|
|
89
|
+
Make it unique per dispatch: a failure line carries only the label and the
|
|
90
|
+
error, so two failed dispatches that share a label cannot be told apart.
|
|
91
|
+
- `phase` (string) — opens a named phase at this call, exactly as `phase(title)`
|
|
92
|
+
would: this dispatch and every dispatch issued after it are attributed to that
|
|
93
|
+
phase. It is not scoped to the one call, so in a fan-out open phases with
|
|
94
|
+
`phase()` between groups rather than per dispatch.
|
|
95
|
+
- `schema` (JSON Schema object) — the subagent must deliver its result by
|
|
96
|
+
calling `structured_output` with arguments matching the schema; agent()
|
|
97
|
+
resolves to the validated object. After two in-conversation nudges without a
|
|
98
|
+
valid result, it resolves to null and the failure is recorded as "subagent
|
|
99
|
+
completed without calling StructuredOutput (after 2 in-conversation nudges)";
|
|
100
|
+
check for null.
|
|
101
|
+
- `agentType` (string) — resolves against the declarative-agents registry
|
|
102
|
+
(`.qwen/agents/<name>.md`, project then user then built-in). Unresolved names
|
|
103
|
+
make the admitted agent() resolve to null and record "agent({agentType}):
|
|
104
|
+
agent type 'X' not found"; check for null.
|
|
105
|
+
- `model` (string) — per-call model override; routes provider correctly via the
|
|
106
|
+
subagent runtime view.
|
|
107
|
+
- `isolation` — `'worktree'` provisions a fresh git worktree under
|
|
108
|
+
`<projectRoot>/.qwen/worktrees/agent-<7hex>`; the worktree is auto-removed if
|
|
109
|
+
no changes, otherwise the path and branch are returned alongside the result.
|
|
110
|
+
`'remote'` makes the admitted agent() resolve to null and records
|
|
111
|
+
"agent({isolation:'remote'}) is not available in this build". A `'worktree'`
|
|
112
|
+
dispatch is also refused — it resolves to null with the reason recorded —
|
|
113
|
+
when the session is already inside a worktree (nested isolation worktrees are
|
|
114
|
+
not supported; to run agents in that worktree, pass it as `workingDir`), when
|
|
115
|
+
git is not available or the directory is not a git repository, when the
|
|
116
|
+
parent working tree has uncommitted changes (the subagent would see a stale
|
|
117
|
+
HEAD), or when the worktree cannot be created. The nested case refuses every
|
|
118
|
+
dispatch, so rule it out before a large `isolation: 'worktree'` fan-out.
|
|
119
|
+
- `workingDir` (string) — pin the subagent to an EXISTING git worktree of this
|
|
120
|
+
repository that the caller owns; nothing is created and nothing is removed.
|
|
121
|
+
Use it when the directory the agent must work in already exists and its
|
|
122
|
+
uncommitted state is the point (a review worktree, a checkout a previous step
|
|
123
|
+
provisioned) — exactly the case isolation cannot serve. Mutually exclusive
|
|
124
|
+
with `isolation`. The path must be a linked worktree of this repository
|
|
125
|
+
registered via `git worktree add` (it may live anywhere on disk) — the main
|
|
126
|
+
checkout is not eligible.
|
|
127
|
+
- `stallMs` (number, ms) — a no-progress stall watchdog, not a wall-clock cap.
|
|
128
|
+
The dispatch is aborted and retried (up to 3 attempts total) after this many
|
|
129
|
+
milliseconds with no observable subagent progress — including before the
|
|
130
|
+
first response arrives; the timer is suspended while a tool is in flight, so
|
|
131
|
+
a legitimately slow tool is not a stall. Default 180000 (override via
|
|
132
|
+
`QWEN_CODE_WORKFLOW_STALL_SECONDS`, whole seconds); `0` disables the
|
|
133
|
+
watchdog. Wall time per attempt is bounded separately.
|
|
134
|
+
|
|
135
|
+
Workflow subagents can never use AskUserQuestion, SendMessage, Monitor,
|
|
136
|
+
EnterPlanMode, ExitPlanMode, or the Agent tool, whatever their `agentType`. A
|
|
137
|
+
subagent therefore cannot fan out further and cannot ask anyone anything: the
|
|
138
|
+
script owns all fan-out, and every ambiguity has to be resolved in the prompt
|
|
139
|
+
it is given. Never ask a subagent to spawn its own verifiers — dispatch them
|
|
140
|
+
from the script.
|
|
141
|
+
|
|
142
|
+
## What agent() returns
|
|
143
|
+
|
|
144
|
+
A subagent's final text, or the validated object under `schema`.
|
|
145
|
+
|
|
146
|
+
`agent()` resolves to `null` when that admitted agent fails on its own —
|
|
147
|
+
including turn/time caps, model or setup errors, missing structured output, and
|
|
148
|
+
exhausted stall retries — and it does so for a bare `await agent()` exactly as
|
|
149
|
+
it does inside `parallel()`/`pipeline()`, so check for `null` wherever you read
|
|
150
|
+
a result. Call-shape validation failures — such as an empty prompt, an
|
|
151
|
+
unsupported option combination, or an invalid option value — reject a bare
|
|
152
|
+
call; inside `parallel()`/`pipeline()`, the surrounding ordinary thunk or stage
|
|
153
|
+
rejection becomes a position-aligned `null`. Run-level rejections no later call
|
|
154
|
+
could survive — the token budget, the 1000-agent cap, and cancellation — throw
|
|
155
|
+
and end a `parallel()`/`pipeline()` batch. An admitted agent that fails and
|
|
156
|
+
settles to `null` still counts as dispatched and is named, with its error, in
|
|
157
|
+
the run's failures list; a `null` returned by an ordinary thunk or stage is not
|
|
158
|
+
an agent dispatch.
|
|
159
|
+
|
|
160
|
+
A `pipeline()` stage that returns `null` — or throws — drops that item: its
|
|
161
|
+
remaining stages are skipped and its slot in the result is `null`. So a `null`
|
|
162
|
+
check belongs in the stage that dispatched the agent, never in a later stage,
|
|
163
|
+
which will not run for that item.
|
|
164
|
+
|
|
165
|
+
A result must be JSON-serializable to survive the sandbox boundary and the
|
|
166
|
+
resume journal. A thunk that resolves to something that is not becomes `null`
|
|
167
|
+
at its index.
|
|
168
|
+
|
|
169
|
+
## Limits
|
|
170
|
+
|
|
171
|
+
- Concurrency: `max(2, min(16, availableParallelism()-2))` agents in flight per
|
|
172
|
+
run — `availableParallelism()` follows CPU affinity and container CPU limits,
|
|
173
|
+
not the host's core count — override via `QWEN_CODE_MAX_WORKFLOW_CONCURRENCY`
|
|
174
|
+
(clamped to 64).
|
|
175
|
+
- 1000 `agent()` calls per run, override via `QWEN_CODE_MAX_WORKFLOW_AGENTS`
|
|
176
|
+
(clamped to 10000). The call past the cap throws.
|
|
177
|
+
- 30-minute wall-clock cap per run, override via
|
|
178
|
+
`QWEN_CODE_MAX_WORKFLOW_SECONDS` (applied as given). A fan-out near the agent
|
|
179
|
+
cap will not fit inside the default cap.
|
|
180
|
+
- 30 seconds for the script's synchronous code before its first `await`, with
|
|
181
|
+
no override. A synchronous loop that runs longer is aborted.
|
|
182
|
+
- Per subagent attempt: 50 turns (`QWEN_CODE_WORKFLOW_AGENT_MAX_TURNS`, clamped
|
|
183
|
+
to 500) and 10 minutes (`QWEN_CODE_WORKFLOW_AGENT_MAX_MINUTES`, clamped
|
|
184
|
+
to 100). Raise them for legitimately long work rather than letting agents
|
|
185
|
+
come back `null` — but a value above the clamp is silently cut down to it.
|
|
186
|
+
- Stall retries: 3 attempts per `agent()` call; the stall timeout itself
|
|
187
|
+
(`QWEN_CODE_WORKFLOW_STALL_SECONDS`) is applied as given.
|
|
188
|
+
- Tokens: a per-run output-token cap may be in effect — read `budget.total`
|
|
189
|
+
(`null` = uncapped) before committing to a large fan-out, because once the
|
|
190
|
+
cap is reached every further `agent()` call is refused.
|
|
191
|
+
|
|
192
|
+
## Default to `pipeline()`
|
|
193
|
+
|
|
194
|
+
`pipeline()` runs each item through every stage independently — item A can be
|
|
195
|
+
in stage 3 while item B is still in stage 1 — so wall-clock is the slowest
|
|
196
|
+
single chain. `parallel()` is a barrier: it waits for every thunk before
|
|
197
|
+
anything moves on, so it costs the slowest item of every stage.
|
|
198
|
+
|
|
199
|
+
A barrier is right only when a stage genuinely needs cross-item context:
|
|
200
|
+
deduplicating or merging across the full result set before expensive downstream
|
|
201
|
+
work, exiting early when the total count is zero, or a prompt that compares one
|
|
202
|
+
finding against all the others. It is not justified by needing to flatten, map,
|
|
203
|
+
or filter between stages (do that inside a pipeline stage), by two stages being
|
|
204
|
+
conceptually separate, or by the code reading more tidily. Smell test:
|
|
205
|
+
`parallel()` → a pure transform → `parallel()` is a pipeline someone wrote with
|
|
206
|
+
an unnecessary barrier. When in doubt, `pipeline()`.
|
|
207
|
+
|
|
208
|
+
## Verify before believing
|
|
209
|
+
|
|
210
|
+
A subagent's answer is a claim, not a result. For findings that matter, spawn
|
|
211
|
+
independent verifiers prompted to _refute_, and drop what a majority refutes.
|
|
212
|
+
When a claim can be wrong in several different ways, give each verifier a
|
|
213
|
+
distinct lens (correctness, security, performance, does it actually reproduce)
|
|
214
|
+
— diversity catches what repetition cannot. For a wide solution space, generate
|
|
215
|
+
several independent attempts, judge them in parallel, and synthesize from the
|
|
216
|
+
winner while grafting the best ideas from the rest.
|
|
217
|
+
|
|
218
|
+
## Converge deliberately
|
|
219
|
+
|
|
220
|
+
For discovery of unknown size, keep running finders until some number of
|
|
221
|
+
consecutive rounds turn up nothing new; a fixed round count stops partway into
|
|
222
|
+
the tail. Deduplicate each round against everything already seen, never against
|
|
223
|
+
only what survived judging — otherwise rejected findings reappear every round
|
|
224
|
+
and the loop never terminates. A closing pass that asks what is still missing
|
|
225
|
+
(a search angle never run, a claim never verified, a file never read) usually
|
|
226
|
+
produces the next round of real work.
|
|
227
|
+
|
|
228
|
+
## Report honestly
|
|
229
|
+
|
|
230
|
+
Scale the fleet to what was actually asked: a quick check gets a few agents and
|
|
231
|
+
one verification pass; an explicit request to be thorough or exhaustive earns a
|
|
232
|
+
larger pool and a multi-vote adversarial round. Whenever a run bounds its own
|
|
233
|
+
coverage — top-N, sampling, no retry — `log()` what was dropped. Silent
|
|
234
|
+
truncation reads as full coverage, which is worse than a smaller honest result.
|
|
235
|
+
|
|
236
|
+
## Saved workflows and workflow()
|
|
237
|
+
|
|
238
|
+
`workflow(nameOrRef, args?)` runs a saved workflow inline under this run's caps
|
|
239
|
+
and nests one level only — a workflow reached through `workflow()` cannot call
|
|
240
|
+
`workflow()` itself, and doing so throws.
|
|
241
|
+
|
|
242
|
+
It takes one of two forms. `workflow('<name>')` resolves a name against
|
|
243
|
+
`<projectRoot>/.qwen/workflows` (project scope, also surfaced as `/<name>`
|
|
244
|
+
slash commands) and `~/.qwen/workflows` (user scope, lower precedence when both
|
|
245
|
+
define the same name). `workflow({ scriptPath: '<absolute path>' })` loads a
|
|
246
|
+
script file directly from either of those directories or from the
|
|
247
|
+
generated-scripts root (`$QWEN_CODE_PROJECT_DIR/workflows/generated` — the
|
|
248
|
+
per-project runtime dir, not the project tree); a path outside those roots is
|
|
249
|
+
refused. A bare string is always a name: a path passed as a string is rejected
|
|
250
|
+
as an invalid workflow name. At the top level that rejection ends the run;
|
|
251
|
+
inside `parallel()`/`pipeline()` it becomes a position-aligned `null` like any
|
|
252
|
+
other thunk rejection — with no agent dispatched and nothing in the failures
|
|
253
|
+
list — so null-check a `workflow()` result too.
|
|
254
|
+
|
|
255
|
+
To create or edit a saved workflow, use the `workflow-creator` skill — it owns
|
|
256
|
+
the file layout, naming rules, and the save round-trip.
|
|
257
|
+
|
|
258
|
+
## Resume and diagnostics
|
|
259
|
+
|
|
260
|
+
Every run hands back its runId, the script's path on disk, and its journal
|
|
261
|
+
path. An inline script is persisted under the generated-scripts root, so a
|
|
262
|
+
resume edits that file and passes the path back instead of re-sending the whole
|
|
263
|
+
source.
|
|
264
|
+
|
|
265
|
+
`resumeFromRunId` replays a prior run: each `agent()` call's journal key hashes
|
|
266
|
+
its prompt and opts chained in call order, so calls whose rolling prefix-hash
|
|
267
|
+
still matches are served from cache for the longest unchanged prefix, and the
|
|
268
|
+
first changed or missing call onward runs live. Post-processing after the last
|
|
269
|
+
agent can therefore change freely without losing the cache. Pass the same
|
|
270
|
+
`args` — they seed the chain, so different args re-run everything.
|
|
271
|
+
|
|
272
|
+
The journal is one JSON line per event: a `started` line when an agent is
|
|
273
|
+
dispatched, then a `result` line when it returns a value or a `failed` line
|
|
274
|
+
when it settles without one. Only `result` lines feed the resume cache. A
|
|
275
|
+
`started` line with neither after it means the run was interrupted with that
|
|
276
|
+
agent in flight — not that the agent is broken. Read the journal before
|
|
277
|
+
diagnosing an empty or surprising result: a cached result can itself be empty,
|
|
278
|
+
and a `null` slot in the output means an agent failed, not that the work found
|
|
279
|
+
nothing.
|
|
280
|
+
|
|
281
|
+
Runs appear in the background-tasks view and the `/workflows` dialog (live
|
|
282
|
+
phase tree, token usage, cooperative pause/resume, cancel);
|
|
283
|
+
`run_in_background: true` returns a run handle immediately in the interactive
|
|
284
|
+
TUI and delivers completion through the conversation.
|
|
285
|
+
|
|
286
|
+
## Worked example
|
|
287
|
+
|
|
288
|
+
Review a change set across several dimensions, verifying each finding as soon
|
|
289
|
+
as its dimension is done — a pipeline, so a slow dimension never holds up
|
|
290
|
+
verification of a fast one.
|
|
291
|
+
|
|
292
|
+
```js
|
|
293
|
+
export const meta = {
|
|
294
|
+
name: 'Review changes',
|
|
295
|
+
description: 'Review the diff across dimensions and verify every finding',
|
|
296
|
+
phases: [
|
|
297
|
+
{ title: 'Review', detail: 'One reviewer per dimension reads the diff' },
|
|
298
|
+
{
|
|
299
|
+
title: 'Verify',
|
|
300
|
+
detail: 'An independent verifier tries to refute each finding',
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const DIMENSIONS = [
|
|
306
|
+
{
|
|
307
|
+
key: 'correctness',
|
|
308
|
+
lens: 'logic errors, wrong edge cases, broken invariants',
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
key: 'security',
|
|
312
|
+
lens: 'injection, path traversal, secrets, unsafe defaults',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
key: 'performance',
|
|
316
|
+
lens: 'accidental O(n^2), unbounded memory, chatty I/O',
|
|
317
|
+
},
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
const FINDINGS = {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
findings: {
|
|
324
|
+
type: 'array',
|
|
325
|
+
items: {
|
|
326
|
+
type: 'object',
|
|
327
|
+
properties: {
|
|
328
|
+
file: { type: 'string' },
|
|
329
|
+
claim: { type: 'string' },
|
|
330
|
+
},
|
|
331
|
+
required: ['file', 'claim'],
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
required: ['findings'],
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const VERDICT = {
|
|
339
|
+
type: 'object',
|
|
340
|
+
properties: { isReal: { type: 'boolean' }, why: { type: 'string' } },
|
|
341
|
+
required: ['isReal', 'why'],
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const target = args?.target;
|
|
345
|
+
if (!target) {
|
|
346
|
+
throw new Error('args.target is required, e.g. { target: "HEAD~1..HEAD" }');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
phase('Review');
|
|
350
|
+
const reviewed = await pipeline(
|
|
351
|
+
DIMENSIONS,
|
|
352
|
+
// The stage that dispatches an agent is the stage that handles its null:
|
|
353
|
+
// returning null here would drop the dimension and skip the verify stage.
|
|
354
|
+
async (dimension) => {
|
|
355
|
+
const review = await agent(
|
|
356
|
+
`Review the changes in ${target} for ${dimension.lens}. ` +
|
|
357
|
+
`Read the files; do not edit anything.`,
|
|
358
|
+
{ label: `review:${dimension.key}`, schema: FINDINGS },
|
|
359
|
+
);
|
|
360
|
+
if (review === null) {
|
|
361
|
+
log(`review:${dimension.key} came back empty — its findings are missing`);
|
|
362
|
+
return [];
|
|
363
|
+
}
|
|
364
|
+
return review.findings;
|
|
365
|
+
},
|
|
366
|
+
(findings, dimension) => {
|
|
367
|
+
phase('Verify');
|
|
368
|
+
return parallel(
|
|
369
|
+
findings.map((finding, index) => async () => {
|
|
370
|
+
const label = `verify:${dimension.key}:${index + 1}`;
|
|
371
|
+
const verdict = await agent(
|
|
372
|
+
`Adversarially verify this claim about ${finding.file}: ` +
|
|
373
|
+
`"${finding.claim}". Try to REFUTE it. Read the code first.`,
|
|
374
|
+
{ label, schema: VERDICT },
|
|
375
|
+
);
|
|
376
|
+
if (verdict === null) {
|
|
377
|
+
log(`${label} came back empty — "${finding.claim}" is unverified`);
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
return { ...finding, verdict };
|
|
381
|
+
}),
|
|
382
|
+
);
|
|
383
|
+
},
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
// A stage that throws drops its dimension to a null slot. Say which ones
|
|
387
|
+
// before flattening, or the drop reads as a dimension that found nothing.
|
|
388
|
+
reviewed.forEach((entries, index) => {
|
|
389
|
+
if (entries === null) {
|
|
390
|
+
log(
|
|
391
|
+
`${DIMENSIONS[index].key} was dropped before its findings were verified`,
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
const verdicts = reviewed.filter((entries) => entries !== null).flat();
|
|
396
|
+
const confirmed = verdicts.filter(
|
|
397
|
+
(entry) => entry !== null && entry.verdict.isReal,
|
|
398
|
+
);
|
|
399
|
+
const refuted = verdicts.filter(
|
|
400
|
+
(entry) => entry !== null && !entry.verdict.isReal,
|
|
401
|
+
);
|
|
402
|
+
log(`confirmed ${confirmed.length} finding(s), refuted ${refuted.length}`);
|
|
403
|
+
return { confirmed, refuted };
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Note what the example does with failure: it refuses to run without the input
|
|
407
|
+
it needs, handles each `null` in the stage that dispatched the agent, gives
|
|
408
|
+
every verify dispatch its own label, `log()`s every dimension and agent it
|
|
409
|
+
loses, and returns what the verifiers refuted next to what they confirmed — a
|
|
410
|
+
verifier can be wrong too, and nothing is silently omitted.
|
|
@@ -32,7 +32,7 @@ export const meta = {
|
|
|
32
32
|
};
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
- Use the sandbox globals
|
|
35
|
+
- Use the sandbox globals `phase(title)`, `log(message)`, `agent(prompt, options?)`, `parallel(thunks)`, `pipeline(items, ...stages)`, `workflow(nameOrRef, args?)`, `args`, and `budget`. The `workflow-authoring` skill is the full reference for them — load it before writing anything beyond a trivial script.
|
|
36
36
|
- Scripts cannot import modules or access the filesystem, shell, environment, or network directly. Put required reads and actions in explicit agent prompts.
|
|
37
37
|
- Give every agent a complete, scoped prompt and a concise `label`. State whether it may edit files.
|
|
38
38
|
- Express real concurrency as `parallel([() => agent(...), () => agent(...)])`. Do not pass already-started promises to `parallel`.
|