fix(autofix): answer every review thread, resolve the ones actually fixed#7758
Conversation
…ixed Two gaps made a handled finding look unhandled on #7731. A finding the bot declined, deferred, or escalated keeps its thread open, but its reason was recorded only in the round summary — a separate comment. The reviewer who opens that thread sees their finding answered by silence. The agent now writes comment-replies.json and the push step posts each reason as a reply on that finding's own thread, leaving the thread open. Replies are neutralised like the summary body, since a reply is model output posted verbatim under the bot identity. Resolution was also keyed on "did I edit a file this round", so a Critical an earlier commit had already fixed stayed open and read as unaddressed. Key it on the finding being resolved in the code, which covers a prior commit's fix the agent re-verified still holds.
|
@qwen-code /takeover |
|
✅ Qwen Triage finished — CI landed green on ✅ Qwen Triage 已完成 —— |
|
🤝 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 ✓ (the body is thorough; "Why" stands in for "Why it's needed" — substance fully present). Problem: this is an observed bug with concrete evidence, not theoretical hardening. The description names the exact threads on #7731 — five open findings ( Direction: aligned. This is internal autofix/review tooling — answering a finding where it was raised, and resolving what is actually fixed, is exactly the hygiene the loop should have. CHANGELOG: not applicable (internal workflow, no product surface). Size: not applicable — no core paths touched ( Approach: the scope feels right and minimal. The reply block mirrors the existing resolve block and reuses the identical Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓(正文详尽;"Why" 代替了 "Why it's needed"——内容完整无缺)。 问题:这是有具体证据的已观测 bug,而非理论性加固。描述点名了 #7731 上的确切线程——五条开着的 finding( 方向:对齐。这是内部 autofix/评审工具——在 finding 被提出的地方答复它、resolve 真正修好的,正是该循环应有的卫生。CHANGELOG:不适用(内部工作流,无产品面)。 规模:不适用——未触及核心路径( 方案:范围合理且最小化。回复块与既有 resolve 块对称,并复用完全相同的 进入代码审查 🔍 — Qwen Code · qwen3.8-max-preview Reviewed at |
Code reviewI worked out my own take before reading the diff: the already-fixed-Critical gap is a guidance bug (resolution keyed on "edited a file this round" instead of "is the finding fixed in the code"), and the silent-thread gap needs the agent to emit a per-finding reply that the workflow posts on that finding's own thread — mirroring the existing resolve loop and reusing the same marker neutralisation. The PR does exactly this, and I didn't find a simpler path. The implementation is clean and consistent with the surrounding code:
No correctness, security, or convention blockers. One non-blocking observation: the reply block requires a bare numeric id (it does not strip an TestingThis is an unattended CI run, so I did not build or run the PR's code — the evidence below is the PR's own CI, read via the API. The unit-test job that covers Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 Real-scenario (tmux): N/A — no user-visible/TUI surface. This is CI workflow + skill guidance + test. The behavioral claim (replies posted on open threads, resolution covering prior-commit fixes) is exercised by the new unit test, which executes the shipped run block extracted from the YAML against a fake not verified: the live reply-posting against the real GitHub API (no execution in this run; deferred to the loop's next round / 中文说明代码审查读 diff 前我先独立给出方案:已修好 Critical 仍开着是引导文案的 bug(resolve 以"本轮改了文件"而非"finding 是否已在代码中修复"为判据);线程沉默则需要 agent 为每条未解决 finding 产出回复、由 workflow 发到该 finding 自己的线程——与既有 resolve 循环对称并复用同样的标记中和。PR 正是这么做的,我没找到更简的路径。 实现干净、与周边代码一致:回复块忠实镜像了上方的 resolve 块——同样的尽力而为姿态( 无正确性、安全性或规范层面的阻塞项。一条非阻塞观察:回复块要求裸数字 id(不像 resolve 块那样剥离 测试这是无人值守的 CI 运行,因此我未构建或运行 PR 代码——以下证据来自 PR 自身 CI(经 API 读取)。覆盖本 PR 扩展的 真实场景(tmux):N/A——无用户可见/TUI 面。这是 CI 工作流 + skill 引导 + 测试。行为性主张(在开着的线程上回复、resolve 涵盖更早提交的修复)由新增单测演练——它对着假 未验证:对真实 GitHub API 的实时回复发送(本次不执行;交由循环下一轮 / — Qwen Code · qwen3.8-max-preview Reviewed at |
|
Confidence: 5/5 — clean across every stage; a small, well-motivated fix that I'd merge without hesitation. Stepping back: the need here is concrete, not argued — five open threads on #7731 answered only in a separate summary comment, and a fixed Critical still reading as unaddressed because resolution was keyed on "did I edit a file this round". Anyone re-reviewing that PR hits exactly the confusion this fixes. The response is proportionate: re-key the resolution test on whether the finding is actually fixed in the code, and answer declined/deferred/escalated findings in their own threads via a reply block that mirrors the existing resolve loop. My independent proposal landed in the same place, and I didn't find a simpler path the PR missed. The code reads like someone who has maintained this workflow: same best-effort posture, same numeric-id validation before the id touches an API path, same marker neutralisation as the summary body, and a malformed-file guard that posts nothing rather than failing a good push. The comments explain the why (a reply is model output under the bot identity; an already-fixed Critical left open reads as unaddressed) without narrating the what. The new unit test executes the shipped block extracted from the YAML rather than a retyped copy, and the author reports it mutation-verified — removing the reply block turns exactly that test red. Every line in the diff earns its place; the escape-site count bump is forced by the new site, not churn. The only thing standing between this and an approval is timing, not judgment: the ubuntu unit-test job is still running on this commit (no failures so far). I'm not going to attest to a result that doesn't exist yet, so approval is deferred until CI lands green on 中文说明置信度:5/5 —— 每个阶段都干净;一个小而动机充分的修复,我会毫不犹豫地合并。 退一步看:这里的需求是具体的,无需争辩——#7731 上五条开着的线程只在另一条总结评论里被答复,外加一个已修好却仍读起来像"未处理"的 Critical,只因为 resolve 以"本轮有没有改文件"为判据。任何重新评审那个 PR 的人都会恰好撞上本 PR 所修复的困惑。回应是相称的:把 resolve 判据改到 finding 是否真的已在代码中修复,并通过一个镜像既有 resolve 循环的回复块,在 declined/deferred/escalated 的 finding 自己的线程里答复它们。我独立得出的方案落在同一处,也没找到 PR 漏掉的更简路径。 代码读起来像出自一位长期维护此工作流的人:同样的尽力而为姿态、id 触及 API 路径前同样的数字校验、与总结正文同样的标记中和、以及一个"畸形文件宁可不发也不拖垮成功推送"的守卫。注释解释了为什么(回复是 bot 身份下的模型输出;已修好的 Critical 若开着会读起来像未处理),而没有复述做了什么。新单测执行的是从 YAML 抽取的随 PR 发布代码块、而非手抄副本,作者称已做变异验证——删除回复块恰好让该测试变红。diff 中每一行都物有所值;escape 位点数的增加是新位点逼出来的,不是搅动。 唯一挡在批准之前的是时机,而非判断:ubuntu 单元测试任务在该提交上仍在运行(目前无失败)。我不会为一个尚不存在的结果背书,因此批准延后到 CI 在 — Qwen Code · qwen3.8-max-preview 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. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
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: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Autofix review round summaryAddressed the single suggestion from the automated reviewer on PR #7758. Feedback points
Conflict notes
Verification
中文说明Autofix 审查轮次总结处理了 PR #7758 上自动审查器提出的唯一一条建议。 反馈点
冲突说明
验证
Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。 🧠 Handled by Qwen Code · model/模型 |
Review —
|
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
#7758) Address the maintainer review on the in-thread reply mechanism: - Map each reply to its thread's top-level comment before posting. The feedback step lists every review comment, replies included, so an rc:<id> can be a reply id; GitHub rejects a reply aimed at another reply, which would have left escalated findings answered by silence. Hoist the threads GraphQL fetch above both the resolve and reply blocks so a reply-only round still has it, and fall back to the id as given past the page cap. - Skip any id already present in resolved-comments.txt so a finding is never both resolved and replied to; the match tolerates the rc: prefix and a trailing CR like the resolve block's own parsing. - Mutation-verify the previously untested ^[0-9]+$ id guard (the boundary between a model-authored id and an arbitrary API path), the -f body= field name, the type=="array" skip, and the new cross-check.
|
🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下: Thanks for the deep review — the reply-to-reply rejection (#1) and the untested id guard (#3) were both real. Fixed those plus the test-strength gaps (#4) and the cross-file check (#5). One item (#2) is a scope call I'm leaving for a maintainer. Point by point: #1 — fixed (reply-to-reply rejection). The reply block now maps each id to its thread's top-level comment before posting, using the same #3 — fixed (untested #4 — fixed both surviving mutants.
#5 — cross-check fixed; three sub-items declined.
#2 — needs a maintainer's decision (left open). Whether a
My recommendation is (b): a No conflict with Verification
中文说明感谢这份深入的评审 —— reply-to-reply 被拒绝(#1)和 id 守卫未测试(#3)都是真实问题。这两项连同测试强度缺口(#4)、跨文件校验(#5)一并修复。剩下一项(#2)是需要维护者拍板的范围问题,我留作未决。逐点如下: #1 —— 已修复(reply-to-reply 被拒绝)。 回复块在发帖前,先把每个 id 映射到其所在线程的顶层评论,复用 resolve 块所用的同一份 #3 —— 已修复( #4 —— 两个存活变异均已修复。
#5 —— 跨文件校验已修;三个子项已拒绝。
#2 —— 需维护者决定(留作未决)。
我的建议是 (b): 本轮与 验证(Verification)
Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
中文说明
未发现问题。LGTM!✅
— qwen3.7-max via Qwen Code /review
doudouOUC
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
— qwen3.7-max via Qwen Code /review
Review —
|
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix Review Response — PR #7758No changes made. The latest review is an APPROVE with 0 Critical and 0 Suggestion findings. There are no inline comments, no failed checks, and no still-red checks to address. 中文说明Autofix 审查回应 — PR #7758未做任何更改。 最新审查结果为 APPROVE(批准),0 个 Critical(严重)和 0 个 Suggestion(建议)发现。没有行内评论、没有失败的检查、也没有持续红色的检查需要处理。 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
What this PR does
Makes every review thread carry its own answer: the bot now replies in the thread to findings it did not implement, and resolves a thread whose finding is fixed — including one an earlier commit fixed.
Why
On #7731 a reviewer could not tell handled findings from ignored ones. Two distinct gaps:
1. Declined / deferred / escalated findings were answered nowhere the reviewer looks. Their reasons were recorded only in the round summary — a separate comment further down the PR. Five threads sat open on #7731 (
rc:3651450554,…555,…557,…558,rc:3651608470), each with a real recorded reason under a "Deferred (recorded reasons — follow-up)" heading, and not one word in the thread itself. Opening the thread, you see your finding answered by silence.2. An already-fixed Critical stayed open.
resolved-comments.txtwas keyed on "did I edit a file this round", sorc:3651450543— a Critical the report itself filed under "Already fixed (prior commit, verified this round)" — was never listed, and its thread still reads as an unaddressed Critical.(For contrast, the mechanism is otherwise healthy: 13 of 19 threads on that PR are correctly resolved, and the most recent batch is correctly not resolved because that round's commit failed verification and was discarded — resolving it would have been a lie.)
How
resolved-comments.txtis now keyed on the finding being resolved in the code, not on editing a file this round: a fix from an earlier commit that the agent re-verified still holds belongs there too.comment-replies.json([{"id", "body"}]) with one entry per inline finding it did not resolve — the disposition plus the reason, and for an escalation the question it needs answered. Bilingual per the repo convention.<!--token-breaking as the summary body: a reply is model output posted verbatim under the bot identity and could otherwise smuggle a forged control marker. Best-effort throughout — a reply failure never fails a good push.Deferred findings are not re-processed across rounds (the watermark bounds each round to new feedback), so this does not re-reply every round — verified on #7731: each deferred
rc:appears in exactly one round report.Reviewer Test Plan
npx vitest run scripts/tests/qwen-autofix-workflow.test.js— 101/101 (base 100 → +1; two consecutive clean runs).ghand asserts the recorded calls:pulls/7731/comments/{222,444}/replies, multi-line and non-ASCII bodies intact;<!-- autofix-eval acted=true -->in a reply comes out as<!\-\-— injection neutralised;idorbodyare skipped;Risk & Scope
comment-replies.jsonis added to the run artifacts, so a round that failed to reply is still diagnosable.Linked Issues
Both gaps observed on #7731.
中文说明
本 PR 做了什么
让每条评审线程都能在它自己那里看到答复:未实现的 finding 由 bot 在该线程内回复理由;已在代码中解决的(包括更早提交修好的)则 resolve。
为什么
在 #7731 上,评审者无法区分"已处理"与"被无视"。两个不同的缺口:
1. declined / deferred / escalated 的 finding,在评审者会看的地方没有任何答复。 理由只记录在轮次总结里 —— 那是 PR 下方另一条评论。#7731 上有五条线程开着(
rc:3651450554、…555、…557、…558、rc:3651608470),每条在 "Deferred (recorded reasons — follow-up)" 小节里都有真实理由,而线程内一个字都没有。打开线程,只看到自己的意见被沉默以对。2. 已修好的 Critical 仍然开着。
resolved-comments.txt以"本轮有没有改文件"为判据,于是rc:3651450543—— 一条被报告自己归入 "Already fixed (prior commit, verified this round)" 的 Critical —— 从未被列入,其线程至今读起来像"未处理的 Critical"。(对照说明机制本身是健康的:该 PR 19 条线程中 13 条已正确 resolve;最新一批正确地没有 resolve,因为那轮提交未过验证门禁并被丢弃 —— 若 resolve 就是撒谎。)
怎么做
resolved-comments.txt改以该 finding 是否已在代码中解决为判据,而非"本轮是否改了文件":更早提交的修复、经本轮重新验证仍成立的,同样应列入。comment-replies.json([{"id","body"}]),为每条未解决的 inline finding 各一条:处置与理由;若为 escalate,则附上需要人回答的问题。按仓库约定双语。<!--中和:回复是以 bot 身份逐字发出的模型输出,否则可夹带伪造的控制标记。全程尽力而为 —— 回复失败绝不拖垮一次成功推送。deferred 的 finding 不会跨轮重复处理(watermark 把每轮限定在新反馈),因此不会每轮重复回复 —— 已在 #7731 验证:每条 deferred
rc:恰好只出现在一条轮次报告中。评审验证
npx vitest run scripts/tests/qwen-autofix-workflow.test.js—— 101/101(基线 100 → +1;连续两次干净)。gh跑,断言记录到的调用:两条 → 分别回复pulls/7731/comments/{222,444}/replies,多行与非 ASCII 正文完好;回复中伪造的<!-- autofix-eval acted=true -->输出为<!\-\-,注入被中和;缺id或body的条目被跳过;损坏(非数组)文件不发任何请求且不使步骤失败。风险与范围
comment-replies.json已加入运行产物,便于诊断"回复失败"的轮次。关联 Issue
两个缺口均在 #7731 上观察到。