ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Qwen Code Autofix 增长制动器重构:从“越界即停“到“越界即审计“(Growth Audit)设计深度解析

Qwen Code Autofix 增长制动器重构:从“越界即停“到“越界即审计“(Growth Audit)设计深度解析 Qwen Code Autofix 增长制动器重构从越界即停到越界即审计Growth Audit设计深度解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code本文围绕 Qwen Code 开源仓库终端内 AI 编码 Agent中 Autofix 自主修复循环的一份核心设计文档展开剖析其如何把diff 增长预算越界这一尺寸信号从直接停机的执行器改造成触发审计判断的触发器。读者将掌握该循环的轮次/增长双制动器机制、growth-audit.json判决文件的格式与校验门、sound/drift/conflict三种判决的路由语义以及审计轨迹与 re-arm 重武装机制背后的源码实现可直接对照仓库定位全部相关文件。背景一次被制动器误杀的接管 PRQwen Code 的 Autofix 循环在接管takeover一个 PR 后会以多轮扫描 → 读反馈 → 修复 → 验证 → 推送的方式迭代直至收敛。为了阻止失控膨胀循环设有两类制动器轮次制动CRITICAL_ONLY_AFTER_ROUND达到 5 轮后仅处理 Critical 反馈与增长制动每个计数窗口内源码/测试净增行数分别超过预算 400/400 后仅处理 Critical。设计文档 autofix-growth-audit.md 描述的正是增长制动器的一次重构。触发这次重构的案例是 PR #9213修复静默反向审计退役失败标签autofix/takeover它在第 5 轮停摆。当时测量窗口内源码净增 286 行、测试净增 948 行均超过 400/400 预算且此前已有两轮超预算且未见缩减于是循环设置GROWTH_DIVERGED并把该轮变成defer-to-human交接——没有代码变更、没有提交、没有解决任何评论线程只留下维护者问题这个 PR 怎么落地而诚实的答案只有合并现有内容或重新武装让循环继续这两件事循环本可自己决定。文档将其归结为三个结构性问题尺寸信号接在停机执行器上。超预算 → 仅 Critical多轮仍超预算 → 完全停止。循环在自由打补丁与停机之间没有中间模式即使剩余工作量仍能满足预算预算越界也会终止接管。被惩罚的增长是协议强制的。地址协议要求每个修复必须有钉死的回归测试#9213 修复的行为回执解析、退役语义只能通过测试观察。循环因为遵守自身规则而被停止——窗口 948 行中大部分是钉住该 PR 问题的两个测试块。停机状态反复空转。GROWTH_DIVERGED只由 feedback.md 文本强制执行刻意不作为步骤输出因此每次扫描看到超过水位线的新反馈仍会启动一次 Agent 运行重新推导出仍被阻塞并可再次发布交接而新反馈不断到来评审机器人CHANGES_REQUESTED状态始终通过仅 Critical 过滤器更新分支合并会在每个新 head 上重新生成评审。接管标签一直挂着运行不断消耗直到有人类介入。值得强调的是制动器的历史合理性是真实的#8853 在四个机器人轮次中净增 315 → 1393 行单轮 609#8276 在托管下净增约 2700 行——问题不在测量而在执行器。设计原则尺寸信号触发判断而非约束或停止重构围绕三条原则展开解决问题是首要的增长控制是次要的——接管存在的意义是落地修复而不是监督行数。尺寸信号触发的是判断JUDGMENT绝不是约束或停机——超预算意味着审计方法而非不许加行更不是停机。终止态只有两种完成或真正需要人类裁决——完成 所有可负担的问题已解决其余记录在后续 issue人类裁决 两个可辩护方向冲突。尺寸两者都不是。变更 A预算越界触发审计轮次qwen-autofix.yml设计的第一步是替换分歧阶梯divergence ladder。在 qwen-autofix.yml 中prepare 步骤原先在窗口增长超过任一预算时设置CRITICAL_ONLY_GROWTHtrue新设计在此基础上让该轮同时成为增长审计轮KISS_AUDITtrue步骤输出喂给 feedback.md 与判决门。原先的GROWTH_DIVERGENCE_ROUNDS升级机制连续 N 轮超预算且不缩减 → 交接连同其仓库变量一并退役。预算变量本身保持不变且支持通过 GitHub Actionsvars覆盖GROWTH_BUDGET_SRC_LINES: ${{ vars.QWEN_AUTOFIX_GROWTH_BUDGET_SRC_LINES || 400 }} GROWTH_BUDGET_TEST_LINES: ${{ vars.QWEN_AUTOFIX_GROWTH_BUDGET_TEST_LINES || 400 }}工作流在读取处会对预算做防御性校验非纯行数格式非0|[1-9][0-9]{0,6}时回退到 400 并发出::warning::见 qwen-autofix.yml。关键的行为差异在于审计时机审计发生在首次越界时而不是再等两轮超预算去证明不收敛这省去了分歧阶梯原本用来证明不收敛所花费的轮次——#9213 会在第 3 轮就进入审计而不是第 5 轮停机。同时审计只在增长可测量时触发NET_MEASUREDtrue即存在可信合并基线 origin/main...HEAD 可计算git diff --numstat判决需要数字才能判断。不可测量的建议路径不报告增长、无制动器保持不变。从源码看prepare 步骤在NET_MEASUREDfalse时把增长归零GROWTH_SRC0; GROWTH_TEST0而KISS_AUDIT仅在NET_MEASUREDtrue且CRITICAL_ONLY_GROWTHtrue时置真随后写入步骤输出kiss_audit${KISS_AUDIT}供下游消费见 qwen-autofix.yml。值得注意的是Critical-only 参与方式本身不变——审计是叠加在 Critical-only 之上的并不替代它CRITICAL_ONLY_GROWTH仍然照常生效对应 feedback.md 中的Deferred non-Critical feedback段。变更 Bautofix skill 中的审计模式SKILL.md当一轮被标记为审计轮时feedback.md 会新增一个Growth audit required段替代原先的Needs a maintainers decision — this PR is not converging段携带增长数字、此前超预算轮数以及任何先前的审计判决标记。SKILL.md 中的 address-review 模式对 Agent 的指令核心是解决当前问题优先、增长控制次要尺寸信号触发判断而非停机在任何其他工作或编辑之前Agent 必须先在两个轴上完成审计然后写出growth-audit.json。双轴审计与举证责任反转默认假设是该 PR 过度工程化了Agent 必须证伪这个假设。两个轴分别是KISS结构是否存在结构上更简单的方案能达成同样目标Agent 必须指明更简单的替代方案讲形状不讲散文或论证每个累积的片段对某个具体 finding/失败模式是承重的。Minimal change足迹每个被修改的文件/hunk 必须能追溯到 (a) PR 的原始问题、(b) 已被接受的评审 finding、(c) 修复某个失败检查。审计产出一张可追溯性表无法追溯的 hunk 是删除候选。这一轴几乎是机械性的这正是审计保持诚实的原因——sound判决要求每块增长都有可交代的来源。两个轴相互独立一个修复可能结构简单但足迹很宽也可能足迹紧凑但堆满防护。任一轴失败即为drift且判决必须指明是哪一轴。growth-audit.json 判决文件审计轮中任何编辑之前Agent 必须写入${WORKDIR}/growth-audit.json先判决后编辑是协议要求下面的门会强制其存在与形状{ verdict: sound | drift | conflict, kiss: { result: pass | fail, simpler_alternative: … | null }, minimal_change: { result: pass | fail, untraceable_hunks: […] }, rationale: … }同轮判决路由sound——方法合理正常继续处理反馈剩余的 Critical 等。drift——先实现指明的更简单替代方案和/或删除列表通常净负增长然后继续处理反馈。conflict——两个可辩护方向且选择权不在 AgentSTOPBLOCKED并携带审计推理交接。这是唯一通向人类的增长相关路径且人类收到的是带证据的收窄问题而不是diff 太大了。SKILL 明确将交接写入workdir/handoff.md纯英文、无 details 块然后停止不再写任何其他内容不提交、不写 address-summary.md / no-action.md / failure.md。SKILL 同时强调同一窗口内先前已有审计feedback 段列出先前审计时重复判决必须带来新证据。变更 C判决门run-autofix-review-verification.sh在 run-autofix-review-verification.sh 中被标记为KISS_AUDIT的轮次若growth-audit.json缺失或畸形验证将非可重试地失败该轮报告失败下一次扫描重新执行审计。畸形判决是 Agent 行为错误而非构建问题因此修复通道repair pass不能修复它、也不得被调用。这从缺席侧堵住了橡皮图章漏洞跳过审计的审计轮不可能推送。该标记以 verify 步骤环境变量的形式到达门与FOOTPRINT_ENFORCE相同的模式形状校验使用jq本就是工作流依赖。门执行的具体校验见 run-autofix-review-verification.sh单文档校验拒绝多文档判决文件jq 的first语义——形如first(.[] | select(...))的组合天然只接受首个文档多文档会被视为畸形。分类学强制sound要求两轴均为passdrift要求至少一轴failconflict不受约束。conflict 路由强制conflict判决的轮次若未以交接停止则非可重试失败——conflict 必须 STOP BLOCKED绝不能推送对应reject_fix growth-audit verdict is conflict but the round did not stop with a handoff; conflict must STOP BLOCKED (no push)。门把它已验证的判决作为步骤输出audit_verdict记录——last-writer binding验证过的判决内联记录写变量而非备份文件被拒绝的判决缺失/畸形/路由违规永远不会浮出水面。verify 步骤运行在always()上且检查必须位于门脚本的 no-commit/failure.md 早退之前这样它同样适用于无操作审计轮判决为sound且无剩余可修项仍需要审计产物以及 conflict 轮其 BLOCKED 停止经由 failure.md 退出判决必须先被验证并浮出否则轨迹标记永不发布、park 永不生效。残余信任域与防伪造模型设计明确承认一个残余信任域判决文件在 Agent 步骤中写入分支代码运行在可预测的 WORKDIR门的首次读取必然在其之后——门能验证形状、分类学与路由但永远无法证明文件来源例如植入一个形状合法的sound替换诚实的drift/conflict。爆炸半径被限制为控制面伪造并靠结构性不变量而非枚举通道列表约束逐入口枚举的方式每个评审轮都会长出新的入口推送要求outcomefixed|noop而 Finalize verification 只接受结论为 success 的 pass的这两个 outcome门走到它们时退出码为 0门在检查中途被杀则结论为 failure因此伪造的outcomefixedverified_head追加到其已发现的输出文件上会在那里被丢弃按崩溃门读取、重试永远到不了推送条件。每个存活出口还会在检查之后写入自己的 outcome因此即使不杀进程中途追加也会失去 last-write-wins。门通过工作流的env -i干净子进程模式启动并带步骤级BASH_ENV/SHELLOPTS固定bash 在进程启动时、任何 body 侧 unset 运行之前就会 source 植入的BASH_ENV因此固定 白名单子进程关闭的是整个类别而非枚举它。Runner 的$GITHUB_ENV/$GITHUB_PATH/$GITHUB_STEP_SUMMARY后备文件在$RUNNER_TEMP/_runner_file_commands/下变量剥离后仍可发现在该步骤生命周期内被锁定为只读因此没有任何检查能向后续携带 PAT 的步骤追加环境植入。目录本身保持可写runner 在步骤开始时在那里创建下一步的后备文件锁定会让作业后续每一步都停滞——这留下一个重命名覆盖残余新建文件再 rename 到被锁文件上比开放追加更窄且是有意定价的。控制位随门自身的受防护输出走kiss_audit在任何分支代码运行前记录并在每次出口以与判决相同的 last-writer 纪律重新追加后续步骤如同audit_verdict经由 finalize 链消费它绝不直接读 steps.prepare 的原始副本——除非作为死于记录前的 pass 的崩溃回退。同样被明确陈述而非声称关闭的残余$GITHUB_OUTPUT后备文件本身保持可写门必须写它因此分支代码派生的、比门长寿的并发分离写入者仍可能竞争最后一次追加——outcome 翻转被上述结论门挡住而失败轮上的伪造轨迹标记无法 re-arm失败路径从不 re-armsteps.prepare 的kiss_audit副本仅在无门记录该位无推送的崩溃路径时作为回退被消费。变更 D判决路由与审计轨迹报告步骤报告步骤从不重读growth-audit.json每个门把它验证过的判决记录为步骤输出audit_verdictFinalize verification 浮出被选中结果的 pass的判决修复 pass 合法地重新审计——其反馈重建保留审计段SKILL 强制审计优先——因此该 pass 门验证过的判决才是该轮代码被评判的依据验证了空值的修复回退到首 pass 的已验证判决。两个报告步骤只消费这一个输出。门验证过的判决是唯一可进入轨迹标记和 re-arm 的判决。机器可读轨迹标记每个审计轮在轮次报告评论中发布带机器可读标记的判决!-- autofix-growth-audit verdictV winWINDOW_KEY --后续轮次的审计可以读取轨迹——同一窗口内先前sound后的第二次审计会看到前任已认可该方法重复判决必须带来新证据。轨迹及其新证据义务是按窗口的反馈读取器按活跃窗口键过滤而一个完成的sound判决会 re-arm把键移动到标记之后——因此sound→ re-arm 链在其中的每一轮内部都不可见人类可 grep 的评论流是唯一的跨窗口约束。标记的win必须是steps.prepare.outputs.growth_base_win基线被读取时所用的键与 growth-now 标记使用它的理由相同conflict 轮豁免于 supersede 丢弃可在 re-arm 后以过期窗口运行若标记写在死键下每次后续读取都不可见。sound 判决自动 re-arm当verdictsound且轮次完成时报告步骤额外发布 re-arm 标记评论!-- autofix-rearm --。这完全复用现有LIVE_REARM_KEY机制窗口键 最新的takeover-ack engaged或autofix-rearm标记水位线释放、排队中的旧窗口作业自我 supersede、下一轮在当前尺寸处重新锚定增长基线——剩余工作获得全新预算仅限完成轮的报告路径失败的轮只记录判决从不 re-arm。这实际上是一次自动的、审计门控的/retry。设计明确决定re-arm 具有完整的/retry语义——每窗口轮次计数器和建议阀也随之重置。继续解决问题包含建议若重新生成的建议复现膨胀制动器在又一整段预算增长后重新触发并在轨迹可见的情况下重新审计。TAKEOVER_MAX_ROUNDS单独约束每个窗口soundre-arm 链只受公开审计轨迹与里程碑提示约束不受任何全局上限约束。而verdictdrift时没有re-arm简化预期会缩减 diff制动器下轮自然重新测量。变更 E通过 #9189 队列的预算延期依赖 #9189PR #9189截至文档写作时未合并为地址评审增加第四个处置项Defer to follow-up——一个 VERIFIED 的 finding其修复落在 PR 足迹/主线之外时记录在deferred-findings.json并 upsert 进一个合并后仍存活的按 PR 跟踪 issue。本设计为该原因分类学扩展一个预算类一个足迹内、已验证但放不进窗口剩余增长预算的 finding通过同一管道延期单 issue upsert、rc-id 去重、token 中和、线程回复、保持打开。现有的延期要求 VERIFIED约束不变——这正是防止预算延期变成倾倒场的机制。在 #9189 落地之前A–D 与 F 各节可独立成立负担不起的尾巴届时仅由 Critical-only 保持延期无损失无结构化队列。工作流与 SKILL 中已能看到延期管道的基础设施.qwen/skills/autofix/SKILL.md规定验证过的越界 finding 写入workdir/deferred-findings.json数组元素{id, source, path, reason}工作流的产物清单中同样列有deferred-findings.json、deferred-findings.carry.json、deferred-findings.unmerged.json见 qwen-autofix.yml。变更 Fdefer-to-human 收窄且幂等增长只经由conflict判决变更 B到达人类skill 中现有的非增长 defer-to-human 类别产品/范围选择、矛盾评审不变。conflict 交接幂等一旦该窗口的 conflict 交接已发布在无新唤醒的情况下扫描不发布任何内容、也不启动 Agent。唤醒集合是循环自身无法产生的反馈可信人类的评审或评论或循环舰队之外的失败检查。检查分支中整体排除Qwen Autofix 工作流自身的检查运行地址通道包括在内——park 状态下没有地址轮能合法运行因此任何晚于标记的评审-地址检查都是 conflict 轮自身的失败检查计它会允许循环自身输出解除自己来源轮的 park以及循环的兄弟机制——评审工作流被循环自身 base-update 合并创建的每个 head 重新触发、CI 失败巡逻cron 在不变 head 上重跑、fork 桥/信号通道。所有这些都会在两个 park 时钟后无人类输入地完成而浪费的失败轮会喂给连续失败上限把人类正在裁决的那个 PR 推向终局锁死。双保险配合名称排除交接悬置期间循环不移动 head——扫描的过期 base 自动更新和 conflict 轮自身的过期 base 重试都跳过 park 中的 PR因此任何晚于两个时钟的检查都是在人类移动过的 head 上运行的。/retry把窗口键移到标记之后是被认可的解除方式。这修复了问题 3 中唯一剩余停止路径上的交接空转非停止路径构造上就不空转。状态机改造前后对比改造前normal → critical-only → (2 轮超预算不缩减) → STOP, defer-to-human改造后normal → critical-only ( 首次预算越界即审计轮) ├─ verdict sound → 继续在当前尺寸 re-arm 窗口 ├─ verdict drift → 先简化净负增长再继续 └─ verdict conflict → 一次幂等交接携带审计证据 可负担工作耗尽 → 终止成功核心落地 尾巴进入按 PR 延期 issue标签释放WalkthroughPR #9213 在本设计下的走向第 3 轮首次越界审计轮。KISS 轴——累积的加固行级极性防护、单回执形式认证等每个都追溯到某个 finding没有更简单的具名替代。Minimal 轴——562 行 repro 块与 671 行退役测试追溯到 PR 的原始问题和已接受的 finding。判决sound→ re-arm → 窗口基线在当前尺寸重新锚定。第 4 轮起剩余两个 Critical小修复在一个全新 400/400 预算内轻松落地评审者的边际尾巴由 Critical-only 延期#9189 之后其验证过的离主线项进入跟踪 issue 队列。PR 收敛标签释放零人类轮次。失败模式与边界审计错误放行真实 drift有界——同一窗口内下一次越界会带着先前判决标记重新审计跨soundre-arm 标记位于旧窗口键下——跨窗口边界是公开评论流而对单调增长 diff 的重复sound判决是维护者可 grep 的公开模式。审计错误谴责合理设计代价是额外一轮简化删除列表由可追溯性推导并公开坏列表在下轮重新推导前可见。失败模式是浪费一轮绝不是停机。橡皮图章举证责任反转默认假设过度工程化、要求可追溯性表、判决门拒绝缺失/畸形判决、轨迹公开。成本每个预算越界一轮审计——一次 Agent 运行替代本就会运行的交接轮。现有制动器不动基于轮次的 Critical-only、每窗口人类反馈预算、失败检查处理与TAKEOVER_MAX_ROUNDS全部保持不变源码中这些变量依旧见 qwen-autofix.yml。测试影响从升级交接到审计路由的钉死scripts/tests/qwen-autofix-workflow.test.js 钉死当前行为必须随变更重写整个it(escalates to a maintainer-decision handoff …)用例约 L6742–7378被替换它钉死GROWTH_DIVERGENCE_ROUNDS变量从autofix-growth-now标记的 fixture 历史按run去重、按measured排序、按可比性截止过滤提取并执行分歧块钉死畸形轮次 sanitize 回退然后执行 feedback.md 交接守卫块并断言## Needs a maintainers decision、defer-to-human与 SKILL 文本this PR is not converging。上述全部由审计触发、判决路由与新 SKILL 文本取代。fixture 标记辅助函数本身存活——审计读取的是分歧阶梯曾读取的同一autofix-growth-now历史。新钉死的断言仓库测试中已可见其落地痕迹首次越界触发审计而非无越界的基于轮次 Critical-only判决门拒绝缺少/畸形growth-audit.json的 KISS_AUDIT 轮reject_fix growth-audit round missing a valid growth-audit.json verdict (audit skipped or malformed)见 qwen-autofix-workflow.test.js报告中!-- autofix-growth-audit … --轨迹标记!-- autofix-rearm --仅当判决为完成轮上的sound时发布失败路径记录判决但从不 re-armconflict 交接幂等。测试同样断言 SKILL 新文本存在且旧文本this PR is not converging消失qwen-autofix-workflow.test.js。发布与依赖变更 A–D 与 F 相互独立可先行落地。变更 E 依赖 #9189 合并先落地 #9189 以保证恰好一条延期管道。#9213 本身不等待本设计qwen-code /retry是今天sound出口的手动等价物按原样合并加后续 issue 是延期出口的手动等价物。非目标机器人从不自行合并终止成功仍以人类评审/合并收尾。评审侧 finding 生成在此不做预算感知评审者继续产出 finding审计 延期吸收它们。让评审管道感知预算状态是后续杠杆。无拓扑缩放预算。审计使精确预算值远不那么承重除非证据表明需要否则暂缓缩放。结语在仓库中定位这套机制这套设计在仓库中已形成完整的闭环实现。若要继续深入可沿以下路径逐一核对增长预算与KISS_AUDIT触发逻辑在 .github/workflows/qwen-autofix.yml预算声明 L132-L133、触发 L4611-L4644、feedback 注入 L4999-L5006、轨迹与 re-arm 标记 L6125-L6130、growth-now 标记 L6751Agent 侧的审计模式指令在 .qwen/skills/autofix/SKILL.md 的Growth audit required一节判决形状与路由强制在 .github/scripts/run-autofix-review-verification.shverdict gate L170-L232行为钉死在 scripts/tests/qwen-autofix-workflow.test.js 的审计相关用例中。这份设计文档的核心主张——尺寸信号触发判断绝不停机人类只接收收窄的、带证据的问题——正是这套机制区别于普通行数警察的关键所在。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进