feat(autofix): raise the strict round cap from 5 to 10 - #7412
Conversation
Measured across the last 40 bot-authored PRs: 17 finished at round 0, 12 at 1, 4 at 2, 2 at 3, 1 at 4, and 3 reached the cap of 5. All three that reached it merged AT it rather than stalling — and one of those spent two of its five rounds on the verify-gate ENOENT that #7330 has since fixed. So the ceiling was never the thing that stopped a PR, but it sat close enough to bind on a bad day with no headroom. 10 gives that headroom. The cap exists to stop an unproductive LOOP, not to ration ordinary iteration; a genuinely stuck PR still stops, just later. Deliberately not larger: retries for a transient model or gate failure increment the same counter, so the cap also bounds how much one bad provider window can spend. API_AUTH_MAX_ROUNDS stays at 3 and still short-circuits the errors only a maintainer can fix. Replaces the literal `MAX_ROUNDS: '5'` assertion with the ordering the numbers must satisfy — auth cap < strict cap < takeover cap — so the values stay tunable and a cap that stops binding fails instead.
|
@qwen-code /takeover |
|
🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。移除 |
|
Thanks for the PR! Template looks good ✓ Problem: observed operational issue with solid evidence — 40 bot PRs measured, 3 reached the cap of 5 and all 3 merged at it, one (#7246) on its very last available round after losing two to a since-fixed gate bug. The ceiling has never actually stopped a PR; it just left zero headroom. This is a real binding constraint, not a theoretical one. Direction: aligned — this is autofix infrastructure tuning, squarely within the autofix-reliability line (#7247, #7330, #7350, #7351, #7354, #7392, #7396). No user-facing surface, no public contract change. Size: not applicable — no core module paths touched (CI workflow + test file only). Approach: the scope feels exactly right. One constant change ( Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:已观测到的运维问题,有充分数据支撑——对 40 个 bot PR 实测,3 个触到上限 5 且全部在上限处合入,其中 #7246 在最后一轮可用额度上合入(还有两轮消耗在已修复的门 bug 上)。天花板从未真正拦下过 PR,只是一点余量都不剩。这是真实的约束问题,不是理论性的。 方向:对齐——属于 autofix 基础设施调参,完全在 autofix 可靠性主线内。无用户可见面,无公共契约变更。 规模:不适用——未触及核心模块路径(仅 CI workflow + 测试文件)。 方案:范围恰到好处。一个常量变更( 进入代码审查 🔍 — Qwen Code · qwen3.7-max Reviewed at |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
Code ReviewIndependent proposal: for a round cap that binds with zero headroom, I'd raise the constant to a value that gives meaningful margin while still bounding worst-case cost — 10 is the natural choice (doubles the budget, keeps it well below the takeover cap of 100). For the test, I'd replace the literal-value assertion with an ordering invariant ( Comparison with the diff: the PR does exactly this, and does it cleanly. Two files, no scope creep:
No correctness bugs, no security concerns, no convention violations. The change is minimal and every edit serves the stated goal. TestingThis is a CI workflow config change — no user-facing TUI behavior to drive. Verification is the test suite + mutation testing + YAML validation. Test suite (87/87 pass)Mutation testing (all three claimed mutations verified)MAX_ROUNDS=100 (= TAKEOVER_MAX_ROUNDS → takeover label becomes a no-op) → correctly FAILS: MAX_ROUNDS=3 (= API_AUTH_MAX_ROUNDS → auth sub-cap stops binding) → correctly FAILS: MAX_ROUNDS=20 (different value, ordering still valid) → correctly PASSES (not a change-detector): YAML validation中文说明代码审查独立方案: 对于一个余量为零的轮次上限,我会把常量提到一个有合理余量、同时仍能约束最坏情况成本的值——10 是自然选择(翻倍预算,仍远低于 takeover 上限 100)。测试方面,我会把字面量断言换成大小关系不变式( 与 diff 对比: PR 完全这样做了,且很干净。两个文件,无范围蔓延:
无正确性 bug,无安全问题,无规范违反。改动最小化,每处编辑都服务于既定目标。 测试这是 CI workflow 配置变更——无用户可见 TUI 行为可驱动。验证方式为测试套件 + 变异测试 + YAML 校验。 测试套件 87/87 全过。三个变异全部验证通过:MAX_ROUNDS=100(等于接管上限)→ 正确失败;MAX_ROUNDS=3(等于认证子上限)→ 正确失败;MAX_ROUNDS=20(取值不同但顺序合法)→ 正确通过,证明不是变更检测器。YAML 解析正确,大小关系 3 < 10 < 100 成立。 — Qwen Code · qwen3.7-max Reviewed at |
|
Confidence: 5/5 — clean across every stage; would merge without hesitation. This is exactly the kind of PR I like to see: a real operational problem backed by measured data (40 PRs, 3 at cap, zero headroom), a minimal fix (one constant, one test), and a test that's genuinely better than what it replaces. The old test was a change-detector — it fired on any tuning edit but wouldn't catch the failure that actually matters (a cap that stops binding). The new ordering assertion catches exactly that, and the mutation testing proves it: MAX_ROUNDS=100 and MAX_ROUNDS=3 both correctly fail, while MAX_ROUNDS=20 correctly passes. The expanded comment in the workflow file is the right kind of comment — it documents why the number is 10, so the next person tuning this knob understands the tradeoff space without re-deriving it from scratch. Nothing to cut, nothing missing, nothing unrelated. Ships the change cleanly. 中文说明置信度:5/5 —— 每个阶段都干净,毫不犹豫地合入。 这正是我喜欢看到的 PR:有实测数据支撑的真实运维问题(40 个 PR,3 个触到上限,零余量),最小化的修复(一个常量,一个测试),以及一个真正比原来更好的测试。旧测试是变更检测器——任何调参都让它红,但抓不到真正要紧的失败(上限不再生效)。新的大小关系断言恰好抓住那个失败,变异测试证明了这一点:MAX_ROUNDS=100 和 MAX_ROUNDS=3 都正确失败,MAX_ROUNDS=20 正确通过。 workflow 文件中扩展的注释是正确的那种注释——记录为什么是 10,让下一个调这个旋钮的人不需要从头推导权衡空间。 没有可砍的,没有遗漏,没有无关改动。干净地交付了变更。 — Qwen Code · qwen3.7-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: Review feedback addressedInline comment [rc:3621149209] — [Suggestion] Unanchored regex in round-cap testFeedback: The regex Decision: Implemented. Added a Change: One line in - Number(workflow.match(new RegExp(`${key}: '(\\d+)'`))?.[1]);
+ Number(workflow.match(new RegExp(`\\b${key}: '(\\d+)'`))?.[1]);Conflict notes: No conflicts ( Verification:
中文说明已处理的评审反馈行内评论 [rc:3621149209] — [建议] 轮次上限测试中未锚定的正则表达式反馈: 用于提取轮次上限值的正则表达式 决定: 已实现。在正则表达式中的 key 前添加了 变更: - Number(workflow.match(new RegExp(`${key}: '(\\d+)'`))?.[1]);
+ Number(workflow.match(new RegExp(`\\b${key}: '(\\d+)'`))?.[1]);冲突说明: 无冲突( 验证结果:
Base-conflict check: no conflict with main. Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
— qwen3.7-max via Qwen Code /review
yiliang114
left a comment
There was a problem hiding this comment.
LGTM. Data-backed, minimal, and the ordering invariant is a strictly better test than the literal it replaces.
|
Released in v0.20.1. |
What this PR does
Raises
MAX_ROUNDS— the strict per-PR cap on automated review-address rounds — from 5 to 10, and replaces the test that pinned the literal number with the ordering the round budgets must satisfy.Why it's needed
Measured across the last 40 bot-authored PRs:
The three that reached it:
acted=true; it finished the work on the final round and merged. Rounds 1 and 2 wereCould not address, both spent on the verify-gate ENOENT that fix(autofix): resolve owning package for nested paths; report verify-failed handoffs as not pushed #7330 has since fixed.acted=true, merged.So the ceiling has never actually stopped a PR. What it has done is sit close enough to bind on a bad day with zero headroom — #7246 merged on its last available round, and would not have if two of its rounds had not been refunded by a bug fix.
How
MAX_ROUNDS: '5'→'10'. Nothing else changes.Deliberately not larger. Retries for a transient model or gate failure increment the same counter (that is by design — see #7247 and #7351), so this cap also bounds how much one bad provider window can spend: 10 agent runs and 10 comments instead of 5.
API_AUTH_MAX_ROUNDSstays at 3 and still short-circuits the errors only a maintainer can fix, well below the new ceiling.TAKEOVER_MAX_ROUNDSstays at 100, so the takeover label remains a meaningful escalation.The existing test asserted the literal
MAX_ROUNDS: '5'. That is a change-detector — it fires on any tuning edit, and it would not fire on the failure that matters: a cap that stops binding. It is replaced by the ordering these three numbers must satisfy.Reviewer Test Plan
How to verify
npx vitest run scripts/tests/qwen-autofix-workflow.test.js— 87/87 (one run in three hit the pre-existingeligibility recheck/takeover-command toggleload flakes; see Risk).Mutation-verified, including a case that must pass:
MAX_ROUNDS: 100(=TAKEOVER_MAX_ROUNDS, making the takeover label a no-op)MAX_ROUNDS: 3(=API_AUTH_MAX_ROUNDS, so the auth sub-cap stops binding)MAX_ROUNDS: 20(different value, ordering still valid)Static, run locally with the exact CI toolchain:
js-yamlparses and reportsMAX_ROUNDS=10 API_AUTH_MAX_ROUNDS=3 TAKEOVER_MAX_ROUNDS=100; all 37run:blocks passbash -n; actionlint 1.7.12 clean; prettier clean.Post-merge smoke: the next handoff comment on a non-takeover bot PR reads
attempt N/10.Evidence (Before & After)
Tested on
Risk & Scope
eligibility recheck,takeover-command toggleandclassifies permanent API failuresare subprocess load flakes; an earlier controlled A/B in this repo showed unmodifiedmainfailing the same tests at a comparable rate, and all pass in isolation.Linked Issues
Part of the autofix-reliability line: #7247, #7330, #7350, #7351, #7354, #7392, #7396.
中文说明
本 PR 做了什么
把
MAX_ROUNDS(每个 PR 自动处理评审的严格轮次上限)从 5 提到 10,并把"钉住字面数字"的测试换成这几个轮次预算之间必须成立的大小关系。为什么需要
对最近 40 个 bot 创建的 PR 实测(分布见上方英文表格):17 个在 0 轮结束、12 个 1 轮、4 个 2 轮、2 个 3 轮、1 个 4 轮,只有 3 个触到上限 5,而且三个全部合入。
逐个看:
acted=true,在最后一轮把活干完并合入。而它的第 1、2 轮是Could not address,都消耗在 fix(autofix): resolve owning package for nested paths; report verify-failed handoffs as not pushed #7330 已修复的验证门 ENOENT 上。acted=true,合入。所以这个天花板从未真正拦下过 PR;它的问题是一点余量都不剩 —— #7246 是在最后一轮可用额度上合入的,如果不是有两轮后来被 bug 修复"退款",它就撞上了。
怎么做
MAX_ROUNDS: '5'→'10',其余不变。刻意不调得更大。 传输/门故障的重试会递增同一个计数器(这是 #7247、#7351 的既定设计),因此该上限同时约束着"一次糟糕的服务商窗口最多花掉多少" —— 10 次 agent 运行 + 10 条评论,而非 5 次。
API_AUTH_MAX_ROUNDS保持 3,仍然远低于新上限,继续短路那些只有维护者能修的错误。TAKEOVER_MAX_ROUNDS保持 100,使 takeover 标签仍是有意义的升级手段。既有测试断言的是字面量
MAX_ROUNDS: '5'—— 那是变更检测器:任何调参都让它变红,而真正要紧的失败(某个上限不再生效)它反而抓不到。现改为断言三者的大小关系。评审验证
npx vitest run scripts/tests/qwen-autofix-workflow.test.js—— 87/87(三次中有一次命中既有的负载 flake,见风险段)。MAX_ROUNDS: 100(等于接管上限,使 takeover 标签失效)→ 红;MAX_ROUNDS: 3(等于 auth 子上限,使其不再生效)→ 红;MAX_ROUNDS: 20(取值不同但顺序仍合法)→ 通过,证明它不是数字变更检测器。js-yaml解析并报告MAX_ROUNDS=10 API_AUTH_MAX_ROUNDS=3 TAKEOVER_MAX_ROUNDS=100;37 个run:块全过bash -n;actionlint 1.7.12 clean;prettier clean。attempt N/10。风险与范围
eligibility recheck、takeover-command toggle、classifies permanent API failures是子进程负载 flake;此前在本仓库做过的受控 A/B 显示未修改的main以相当的频率红同样的用例,且单独跑均通过。关联 Issue
属 autofix 可靠性主线:#7247、#7330、#7350、#7351、#7354、#7392、#7396。