feat(review): promote language-pitfall and wrapper/proxy checks out of Agent 1a - #9805
Conversation
…f Agent 1a (QwenLM#9788) Split the two checks folded into Agent 1a's line-by-line brief into dedicated Step 3A roles at high effort: Agent 1d (language-pitfall scan, always) and Agent 1e (wrapper/proxy routing, rostered when the plan's wrapperSignal is true — a capture-time vocabulary heuristic that fails safe: only an explicit false keeps it out, so version-skewed plans still owe the check). The roster, check-coverage and agent-prompt all read the gate from the plan, so a run that skips either agent is named. Briefs, SKILL.md, and the user-facing code-review doc updated; 1a keeps its walk minus the two clauses.
E2E test reportRoster behaviour, against the bundled CLI (
Full-pipeline dogfood — ran the local Suites: |
|
Re-run after round 5 of the autofix loop — gate re-checked at the new head. The round-5 increment is fourteen added and four removed lines in a single test file, so the gate findings carry over unchanged; the detail below is re-verified, not copied. Template looks good ✓ — every section present, bilingual body included. Problem: real and properly sourced. Linked issue #9788 (P1) frames it well: a checklist pattern-match and a structural routing expectation are different attention modes from line-by-line scanning, and folded into Agent 1a's walk they get diluted by its rhythm. That is not a hypothesis — it is the same shape this skill already measured and acted on elsewhere (the quality split into 3a/3b/3c, the invariant split), and the low tier already separates exactly these two as angles C and D. Direction: aligned. The higher tiers never getting the split the low tier already has is an inconsistency in the skill's own philosophy, and high effort already launches 14 agents, so one always-on plus one conditional agent does not change the cost class. Claude Code's CHANGELOG carries no direct reference to these specific angles (its "wrapper" entries are process-launcher mechanics, unrelated), but effort-levelled multi-agent review is squarely the active direction there. Size: touches a core path ( Approach: the scope feels right and the mechanics sit exactly where the architecture wants them: the signal is computed in Risk: no elevated-risk signals — none of the changed files match the revert-correlated paths (checked deterministically). Moving on to code review. 🔍 中文说明autofix 循环第 5 轮后的重跑——在新 head 上复查门禁。第 5 轮增量仅为单个测试文件的 +14/-4 行,门禁结论不变;以下细节为重新核实,而非照抄。 模板完整 ✓ —— 各节齐全,含中文双语正文。 问题: 真实且有据。关联 issue #9788(P1)表述清楚:清单式模式匹配与结构性路由预期是两种不同于逐行扫描的注意力模式,折叠在 Agent 1a 的走查里会被其节奏冲淡。这不是假设——本技能在别处已经实测并处理过同样的形态(质量维度拆成 3a/3b/3c、不变量检查三分),而且低档内联审查早已把这两项拆成角度 C 和 D。 方向: 对齐。高档一直没有低档已有的拆分,是本技能自身理念里的不一致;high 档本来就启动 14 个 agent,多一个常驻加一个条件角色不改变成本量级。Claude Code 的 CHANGELOG 没有直接提到这两个具体角度(其中的 "wrapper" 条目是进程启动器机制,与此无关),但分档的多 agent 审查正是其活跃方向。 规模: 触及核心路径( 方案: 范围合理,机制落点也正是架构期望的位置:信号在 风险: 无升级风险信号——改动文件均未命中与回滚相关的高风险路径(已确定性检查)。 进入代码审查。🔍 — Qwen Code · qwen3.8-max Reviewed at |
|
Re-run: full code review at the round-5 head. The increment since the last triage is one test file (+14/−4): the semantics pins for the 1d checklist now bind each cue adjacent to its entry label — the My independent proposal for this problem was essentially what the PR does — two new Load-bearing claims, re-verified against the tree this pass rather than taken on faith:
No Critical findings. What remains open is the one item the review loop deferred under its round-6 convergence posture, and it is a test-tightness follow-up, not a product defect: the 1d/1e semantics-pin surface is still under-pinned as a class — 1e's brief has no semantics test of its own (the shared "every agent" test pins only the welded diff reads and the common finding-format boilerplate, so 1e's routing steps delete green), asymmetric with the semantics pin 1d now has. Worth a follow-up; not a reason to hold this. Testing evidence — the PR's own CI, read via the APIUnattended run: no PR code is built or executed here. This is what the PR's own CI reports for the reviewed commit:
The ubuntu unit job is the authoritative suite for this change and it is green on the reviewed commit; Security Checks passed at the workflow level. The skipped jobs are the gated lanes for fork PRs (macOS/Windows unit and the no-sandbox integration lane), not failures. The check list also carries a batch of Not verified: the live pipeline fan-out — the author's dogfood report (15 agents including 1d and 1e, coverage 5/5, exit 0) is the author's claim, consistent with the code but not re-run here; the macOS-tested-only claim likewise rests on the author. What the green suite does substantiate is exactly the behaviour this PR changes: the roster contract is pinned literally ( Sandboxed verification: the maintainer-triggered 中文说明重跑:在第 5 轮后的 head 上做完整代码审查。上次审查以来的增量是一个测试文件(+14/−4):1d 清单的语义钉扎现在把每条线索与其条目标签相邻绑定—— 我对此问题的独立方案基本就是 PR 的做法——两个新 关键论断本轮均已对照代码树重新核实,而非照单全收:
无 Critical 发现。仍然开放的只有审查循环第 6 轮收敛姿态下延后的那一条,且属测试紧密度后续事项、不是产品缺陷:1d/1e 的语义钉扎面作为一类仍欠钉扎——1e 的 brief 没有自己的语义测试(共享的"every agent"测试只钉焊接的 diff 读取与公共发现格式样板,因此删除 1e 的路由步骤仍全绿),与 1d 现在拥有的语义测试不对称。值得后续补上,不足以扣留本 PR。 测试证据——PR 自身 CI,经 API 读取无人值守运行:此处不构建、不执行 PR 代码。以上是 PR 自身 CI 对被审提交的报告。 ubuntu 单元任务是本改动的权威套件,在被审提交上为绿;Security Checks 在工作流层面通过。被跳过的任务是 fork PR 的门控通道(macOS/Windows 单元与无沙箱集成通道),不是失败。检查列表里还有一批 未验证:真实流水线的 fan-out——作者的 dogfood 报告(15 个 agent 含 1d/1e、覆盖 5/5、退出码 0)是作者声明,与代码行为一致但未在此复现;"仅在 macOS 测试过"同样依赖作者声明。绿色套件所证实的恰是本 PR 改变的行为:roster 契约被逐字钉住(含 沙箱验证:维护者触发的 — Qwen Code · qwen3.8-max Reviewed at |
|
@qwen-code /takeover |
|
Confidence: 4/5 — clean static review, green CI on the reviewed commit, tests that pin exactly the behaviour the PR changes, and a sandboxed A/B + mutation pass on production-identical code; the deduction is documented trade-offs plus one deferred test-pinning follow-up (1e's brief semantics delete green), none blocking. Stepping back: this is the kind of change this skill is built to attract. A properly filed P1 issue, a design doc that resolves its own open questions before coding, and an implementation that uses existing machinery instead of adding new machinery — the signal is computed where the diff already walks, the gate reads one plan field everywhere, and the roster / prompt builder / coverage gate cannot disagree because they derive from the same source. My independent proposal for this problem was essentially what the PR does; the PR additionally thought through the gate's asymmetry under version skew and the refined-path signal timing, which I had not. The five autofix rounds landed well: the Go/Kotlin checklist semantics came back corrected and pinned per language, the falsy-zero shape stayed in Agent 1a so medium and non-JS highs don't lose it, the triplicated effort-option describe became one shared definition, and round 5 made the Java/Kotlin cue pins swap-resistant by binding them adjacent to their entry labels — the exact gap the prior pass flagged. My remaining reservations are documented trade-offs and follow-ups, not defects: medium tier genuinely loses both checks (named honestly in the docs, consistent with how the personas are tiered, and the surviving falsy-zero shape is pinned); 1e's vocabulary gate has imperfect recall for wrappers that spell no vocabulary word (disclosed, accepted by the issue, fail-safe wherever the signal is absent or ambiguous); and the one item the review loop deferred — 1e's brief carries no semantics test of its own, so its routing steps delete green — is a test-tightness follow-up, not a reason to hold this. CI is settled on the reviewed commit: the ubuntu unit suite, both desktop shells, the web-shell smoke, Classify PR and Security Checks are green; the macOS/Windows unit and no-sandbox integration lanes are skipped (the fork-PR gated lanes, not failures), and the 中文说明信心:4/5 —— 静态审查干净,被审提交上 CI 为绿,测试恰好钉住 PR 所改变的行为,且沙箱 A/B 与变异测试已在生产代码逐字节相同的版本上通过;扣分项是已写明的权衡与一条延后的测试钉扎后续事项(1e 的 brief 语义删除后仍全绿),均不阻断。 退一步看:这正是本技能应当吸引来的改动。规范提交的 P1 issue、编码前自行消解了所有开放问题的设计文档、复用现有机制而非新增机制的实现——信号在 diff 本来就要流过的地方计算,门在所有地方只读同一个计划字段,roster、prompt 构建器与覆盖门禁因同源推导而不可能相互矛盾。我对此问题的独立方案基本就是 PR 的做法;PR 还多想到了版本偏差下门的不对称性与精炼后路径的信号时机,这两点我没想到。五轮 autofix 落点都好:Go/Kotlin 清单语义已纠正并按语言钉住;falsy-zero 形态保留在 Agent 1a,medium 与非 JS 的 high 不至于失去它;三份重复的 effort 选项描述合并为一份共享定义;第 5 轮把 Java/Kotlin 线索钉扎改为与条目标签相邻绑定、抗短语互换——正是上次审查指出的缺口。 我保留的意见都是已写明的权衡与后续事项,不是缺陷:medium 档确实失去这两项检查(文档如实写明,与人设的档位处理一致,且保留下来的 falsy-zero 形态已有钉住);1e 的词汇门对名字与改动行均不含词汇的包装类型召回不足(已披露、issue 已接受,信号缺失或含糊时 fail-safe);审查循环延后的那一条——1e 的 brief 没有自己的语义测试,删除其路由步骤仍全绿——属测试紧密度后续事项,不足以扣留本 PR。 被审提交上 CI 已定局:ubuntu 单元套件、两个桌面 shell、web-shell 冒烟、Classify PR 与 Security Checks 为绿;macOS/Windows 单元与无沙箱集成通道为跳过(fork PR 的门控通道,不是失败);此 head 上的 — Qwen Code · qwen3.8-max Reviewed at |
|
🤝 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. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 |
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.
Test Plan (not a blocker): 4781 passed — this review observed 20954, 1685, 1653, 495, 4159, 599 passed; 32 passed — this review observed 20954, 1685, 1653, 495, 4159, 599 passed.
中文说明
已审查——无阻断问题。 建议见行内评论。
Test Plan(非阻断):4781 passed — this review observed 20954, 1685, 1653, 495, 4159, 599 passed; 32 passed — this review observed 20954, 1685, 1653, 495, 4159, 599 passed。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| `agent-prompt`, `check-coverage` and `compose-review` need no code change: | ||
| they are BRIEFS- and `requiredAgents(plan)`-driven. |
There was a problem hiding this comment.
[Suggestion] The claim below ("agent-prompt, check-coverage and compose-review need no code change") is contradicted by this PR's own diff: agent-prompt.ts IS modified — 1e is added to the diff-only precision-degradation clause (role === '1b' || role === '1c' || role === '1e') — and "Files affected" above also omits agent-prompt.test.ts, SKILL.test.ts, and docs/users/features/code-review.md. Design docs in this repo are the committed decision record: a maintainer tracing why Agent 1e receives the lightweight-mode precision clause finds the record stating agent-prompt needed no change, so that clause reads as an unexplained accretion (or gets cleaned up as out-of-scope). Scope the sentence to rostering and list the files — for example:
| `agent-prompt`, `check-coverage` and `compose-review` need no code change: | |
| they are BRIEFS- and `requiredAgents(plan)`-driven. | |
| `check-coverage` and `compose-review` need no code change: they are BRIEFS- and | |
| `requiredAgents(plan)`-driven. (`agent-prompt` only extends the existing | |
| diff-only degradation clause to 1e — see "Files affected".) |
中文说明
下面的论断("agent-prompt、check-coverage 和 compose-review 无需代码改动")与本 PR 自身的 diff 矛盾:agent-prompt.ts 确实被修改了——1e 被加入了 diff-only 精确性降级子句(role === '1b' || role === '1c' || role === '1e')——且上方 "Files affected" 还遗漏了 agent-prompt.test.ts、SKILL.test.ts 和 docs/users/features/code-review.md。本仓库的设计文档是已提交的决策记录:未来维护者追溯 Agent 1e 为何获得轻量模式精确性子句时,会发现记录声称 agent-prompt 无需改动,该子句因此显得像是无来由的附加(甚至可能被当作越界改动清理掉)。建议把这句话限定到 roster 层面并补全文件列表,例如上方的 suggestion。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| | Sharded verification (Step 4) | ceil(F/8) | F = findings; at most 8 per verification agent, launched together | | ||
| | Iterative reverse audit (Step 5) | 2-10 (3A); rounds × chunks (3B) | Two consecutive dry rounds to stop; the cap follows the topology — 10 on a small diff, 5 on a chunked one, 3 on a huge one when the run has a deadline. 3B fans out one auditor per chunk per round | | ||
| | **Total** | **~17-28 (~15-27)** | 3A same-repo: ~17-28 (typical ~17-19); cross-repo or local/file: ~15-27; 3B scales with chunks (see DESIGN.md) | | ||
| | **Total** | **~19-30 (~17-29)** | 3A same-repo: ~19-30 (typical ~19-21); cross-repo or local/file: ~17-29; one fewer when Agent 1e is not rostered; 3B scales with chunks (see DESIGN.md) | |
There was a problem hiding this comment.
[Suggestion] This row now totals ~19-30 for 3A same-repo, but the round-cap rationale in SKILL.md:241 still cites the pre-split figure — "Ten on 3A because the marginal round there is a single agent against a whole review of 17-28 calls". That sentence is present-tense policy rationale (unlike the adjacent "(measured; DESIGN.md)" historical note, which correctly stays), and every other roster-derived count in SKILL.md was bumped by this PR (thirteen→fifteen diff-reading agents, twelve→fourteen lenses, Launch 14→16, crossover 3 600→4 400). The same skill file now asserts both ~19-30 and the 14-agent-era 17-28; the next edit to the cap argument will correct one of them from a wrong premise. Suggested fix: update SKILL.md:241 to "a whole review of 19-30 calls".
中文说明
本行的 3A 同仓库总数已更新为 ~19-30,但 SKILL.md:241 的轮次上限论证仍引用拆分前的数字——"Ten on 3A because the marginal round there is a single agent against a whole review of 17-28 calls"。该句是现在时的政策论证(不同于相邻标注了 "(measured; DESIGN.md)" 的历史记录——后者正确保留),且 SKILL.md 中其他所有 roster 派生数字都被本 PR 更新(13→15 个读 diff 的 agent、12→14 个 lens、Launch 14→16、交叉点 3 600→4 400)。同一份技能文件现在同时断言 ~19-30 与 14-agent 时代的 17-28;下次修改上限论证时会基于错误前提二选一。建议把 SKILL.md:241 更新为 "a whole review of 19-30 calls"。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| expect(keys(PR)).toContain('1e'); | ||
| expect(keys({ ...PR, wrapperSignal: true })).toContain('1e'); | ||
| expect(keys({ ...PR, wrapperSignal: 'nope' })).toContain('1e'); | ||
| expect(keys({ ...PR, wrapperSignal: false })).not.toContain('1e'); |
There was a problem hiding this comment.
[Suggestion] No test pins that Agent 1d stays rostered when wrapperSignal: false — this assertion only checks 1e's absence. Verified by mutant probe: nesting add('1d') inside if (hasWrapperTypes(plan)) in roster.ts passes all 442 tests across the roster/agent-prompt/check-coverage suites, because every other fixture omits wrapperSignal (so hasWrapperTypes returns true there anyway). If a future refactor ships that nesting, then on most diffs — which record an explicit wrapperSignal: false — the language-pitfall agent silently leaves the roster and check-coverage stops demanding it, with no red test anywhere. The pin below kills the mutant (re-verified: AssertionError: expected [ '0', '1a', '2', '3a', '3b', …(8) ] to include '1d').
| expect(keys({ ...PR, wrapperSignal: false })).not.toContain('1e'); | |
| expect(keys({ ...PR, wrapperSignal: false })).not.toContain('1e'); | |
| expect(keys({ ...PR, wrapperSignal: false })).toContain('1d'); |
中文说明
没有测试钉住"当 wrapperSignal: false 时 Agent 1d 仍在 roster"——此断言只检查了 1e 的缺席。突变体验证:把 roster.ts 中的 add('1d') 嵌套进 if (hasWrapperTypes(plan)) 后,roster/agent-prompt/check-coverage 三个套件全部 442 个测试依然全绿(其他 fixture 都不带 wrapperSignal,hasWrapperTypes 反正返回 true)。若未来重构带上这种嵌套,那么在大多数记录显式 wrapperSignal: false 的 diff 上,语言陷阱 agent 会悄悄离开 roster,check-coverage 也不再要求它,且没有任何测试变红。下方新增的断言可杀死该突变体(已复验:AssertionError: expected [ '0', '1a', '2', '3a', '3b', …(8) ] to include '1d')。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| // header. A wrapping type usually lives in a file named after it, and | ||
| // the path catches a MODIFIED wrapper whose changed lines never spell | ||
| // the name. | ||
| if (WRAPPER_SIGNAL_RE.test(cur.path)) cur.wrapperSignal = true; |
There was a problem hiding this comment.
[Suggestion] Nothing pins WHEN this check runs. The comment's claim — "The path is only final here", after +++/rename to refinement — is a correctness claim no test enforces: moving the test to the raw diff --git header survives all 46 tests in diff-plan.test.ts (verified by mutant probe — every path-signal fixture spells the vocabulary identically in the header and the refined path). The timings diverge where splitHeaderPaths guesses wrong and only the rename to header carries the true path (e.g. a rename whose new path embeds b/ after a space): the current code still signals via the refined path, the mutant computes wrapperSignal: false, and Agent 1e is silently not rostered. The trigger is exotic, but a fixture where the header path and the refined path diverge — and only the refined one matches the vocabulary — pins the timing (the mutant fails it with expected false to be true; the original passes 47/47):
it('signals on the refined path when the header guess diverges', () => {
const diff = [
'diff --git a/src/old.ts b/src/wrapper b/plain.ts',
'--- a/src/old.ts',
'+++ b/src/wrapper b/plain.ts',
'rename to src/wrapper b/plain.ts',
'@@ -1,1 +1,1 @@',
'+const x = 1;',
].join('\n');
expect(buildDiffPlan(diff, 400).wrapperSignal).toBe(true);
});中文说明
没有测试钉住这个检查"何时"运行。注释的论断——"路径只有在这里才最终确定"(即 +++/rename to 精化之后)——是一个没有任何测试强制的正确性论断:把该检查移到原始 diff --git 头后,diff-plan.test.ts 全部 46 个测试依然通过(突变体验证——所有路径信号 fixture 在头部与精化路径里的词汇完全相同)。两种时机的分歧出现在 splitHeaderPaths 猜错、只有 rename to 头才带真实路径时(例如新路径在空格后嵌入 b/ 的重命名):现有代码仍可通过精化路径发出信号,突变体却算出 wrapperSignal: false,Agent 1e 就此悄悄不入 roster。触发场景确实罕见,但一个"头部路径与精化路径分歧、且只有精化路径命中词汇"的 fixture 能钉住该时机(突变体在该 fixture 下 expected false to be true,原始实现 47/47 通过),见上方代码。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| */ | ||
| wrapperSignal?: unknown; | ||
| /** | ||
| * The review's effort, as the capturing command recorded it (`--effort`). |
There was a problem hiding this comment.
[Suggestion] Pattern: seven enumerations of what medium drops (and what high adds over medium) were not updated for the 1d/1e split this PR makes — this doc comment is one of them. Since this PR, medium drops the personas AND the two specialists (add('1d')/add('1e') sit inside the effort !== 'medium' gate at roster.ts:252-262), but:
- this
RosterPlan.effortcomment still says medium "drops the adversarial personas" only; - the
--effortdescribe strings on all three capture commands say the same (fetch-pr.ts:1893, capture-local.ts:190, plan-diff.ts:201); - SKILL.md:335 (Step 3 overview) enumerates only "the adversarial personas 6a/6b/6c and the Agent 8 diff-specialists";
- SKILL.md:443 describes the balanced set as "(no 6a/6b/6c)";
- SKILL.md:982's medium follow-up tip says
--effort high"adds the reverse audit, the adversarial personas, and Agent 8".
The PR updated every sibling enumeration (SKILL.md:79, SKILL.md:345, code-review.md:44, roster.ts) and missed these. An operator choosing --effort medium from --help for a wrapper-heavy PR reads that medium gives up only the personas — getting a review where the language-pitfall and wrapper/proxy checks run nowhere; and after every medium review the SKILL.md:982 tip tells the user high adds only the reverse audit, personas and Agent 8. Nothing mechanical breaks (roster and coverage gate are requiredAgents-driven); the cost is stale, self-contradicting documentation of the very semantics this PR changed. Suggested wording: medium "drops the adversarial personas (6a/6b/6c) and the language-pitfall and wrapper/proxy specialists (1d/1e)".
中文说明
模式问题:有七处关于"medium 丢弃什么(high 比 medium 多什么)"的列举未随本 PR 的 1d/1e 拆分更新——本注释即其中之一。本 PR 之后,medium 同时丢弃 personas 与两个专项 agent(add('1d')/add('1e') 位于 roster.ts:252-262 的 effort !== 'medium' 门内),但:本 RosterPlan.effort 注释仍称 medium 只"丢弃对抗性 personas";三个捕获命令的 --effort 描述文案同样如此(fetch-pr.ts:1893、capture-local.ts:190、plan-diff.ts:201);SKILL.md:335(Step 3 概览)只列了 "the adversarial personas 6a/6b/6c and the Agent 8 diff-specialists";SKILL.md:443 把平衡集合描述为 "(no 6a/6b/6c)";SKILL.md:982 的 medium 后续提示说 --effort high 只 "adds the reverse audit, the adversarial personas, and Agent 8"。本 PR 更新了所有兄弟列举(SKILL.md:79、SKILL.md:345、code-review.md:44、roster.ts)却漏了这些。若操作者依据 --help 为包装类代码密集的 PR 选择 --effort medium,会读到 medium 只放弃 personas——实际得到的审查里语言陷阱与包装/代理路由检查哪儿都没跑;且每次 medium 审查结束后 SKILL.md:982 的提示都告诉用户 high 只多反向审计、personas 和 Agent 8。机械层面不会出错(roster 与覆盖门禁都由 requiredAgents 驱动);代价是本 PR 所变更的语义在文档里过时且自相矛盾。建议措辞:medium "drops the adversarial personas (6a/6b/6c) and the language-pitfall and wrapper/proxy specialists (1d/1e)"。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| - **low** — quick pass. You read the diff yourself, walking it once per **angle** — `plan.budget.inlineAngles` directed angles (3-6, scaled by diff size) plus a gap sweep when the budget asks for one, all in this context — and report up to 10 unverified findings (Step 3C). No subagents, no build/test, no verification, no reverse audit, no PR posting, no incremental cache, no project rules. The angle rotation is what makes a subagent-free tier worth running: one undirected read converges on the most visibly suspicious hunk and leaves the rest of the diff unexamined, and that is the pass this replaces. | ||
| - **medium** — **balanced**: the high pipeline with its most expensive passes removed. It runs the parallel review agents (Step 3A/3B) over a **reduced dimension set** — issue fidelity (Agent 0, PR targets only), correctness (Agents 1a/1b/1c), **security (Agent 2)**, quality (Agents 3a/3b/3c), performance (Agent 4), **test coverage (Agent 5)**, and **build & test (Agent 7)** — followed by a **single verification pass** (Step 4). It loads and enforces project rules (Step 2) and runs `comment-status` like high. It **skips** the adversarial-persona agents (6a/6b/6c), the diff-specialist finders (Agent 8), the **reverse audit** (Step 5), the incremental cache, and PR posting (`--comment` still forces high). Findings are **verified** (Step 4 ran — they are not "unverified" the way low's are), but without the reverse-audit second pass. Reach for it when high is too slow/expensive but a real bug-catching review is still needed: it keeps the two things that reliably catch bugs cheaply — the finder fan-out and `build-test` (which mechanically catches compile/test failures) — and drops the depth passes with the lowest marginal yield. Measured against high on the same PR it lands at roughly **one-third to one-half** the time and tokens. It reliably catches mechanical defects (compile errors, failing tests) and obvious correctness bugs, but is **not an exhaustive correctness audit** — a subtle Critical that only the reverse audit or the adversarial personas would surface can slip; for a security-sensitive or pre-release review, use `--effort high`. | ||
| - **high** — the full pipeline: parallel review agents (Step 3A/3B — the full dimension set including security, test-coverage, the adversarial personas 6a/6b/6c, and Agent 8), verification (Step 4), iterative reverse audit (Step 5), PR submission (Step 7), incremental cache (Step 8). | ||
| - **medium** — **balanced**: the high pipeline with its most expensive passes removed. It runs the parallel review agents (Step 3A/3B) over a **reduced dimension set** — issue fidelity (Agent 0, PR targets only), correctness (Agents 1a/1b/1c), **security (Agent 2)**, quality (Agents 3a/3b/3c), performance (Agent 4), **test coverage (Agent 5)**, and **build & test (Agent 7)** — followed by a **single verification pass** (Step 4). It loads and enforces project rules (Step 2) and runs `comment-status` like high. It **skips** the adversarial-persona agents (6a/6b/6c), the language-pitfall and wrapper/proxy specialists (Agents 1d/1e), the diff-specialist finders (Agent 8), the **reverse audit** (Step 5), the incremental cache, and PR posting (`--comment` still forces high). Findings are **verified** (Step 4 ran — they are not "unverified" the way low's are), but without the reverse-audit second pass. Reach for it when high is too slow/expensive but a real bug-catching review is still needed: it keeps the two things that reliably catch bugs cheaply — the finder fan-out and `build-test` (which mechanically catches compile/test failures) — and drops the depth passes with the lowest marginal yield. Measured against high on the same PR it lands at roughly **one-third to one-half** the time and tokens. It reliably catches mechanical defects (compile errors, failing tests) and obvious correctness bugs, but is **not an exhaustive correctness audit** — a subtle Critical that only the reverse audit or the adversarial personas would surface can slip; for a security-sensitive or pre-release review, use `--effort high`. |
There was a problem hiding this comment.
[Suggestion] Same pattern as the roster.ts thread, SKILL.md side: this enumeration WAS updated for the 1d/1e split, but three sibling enumerations in this same file were not — line 335 (Step 3 overview: "skip the adversarial personas 6a/6b/6c and the Agent 8 diff-specialists"), line 443 (the balanced set is "(no 6a/6b/6c)"), and line 982 (the medium follow-up tip: high "adds the reverse audit, the adversarial personas, and Agent 8"). Also stale: the three capture commands' --effort help strings and the RosterPlan.effort comment (see the roster.ts thread). Line 982 is rendered verbatim after every medium review, so a user weighing a high re-review never learns it also adds the two correctness specialists this PR creates. Suggested: at :335 "(skip the adversarial personas 6a/6b/6c, the language-pitfall and wrapper/proxy specialists 1d/1e, and the Agent 8 diff-specialists)"; at :443 "(no 6a/6b/6c, no 1d/1e)"; at :982 "(adds the reverse audit, the language-pitfall and wrapper/proxy specialists, the adversarial personas, and Agent 8 — and can certify Approve)".
中文说明
与 roster.ts 的评论线程同一模式,这里是 SKILL.md 侧:本处列举已随 1d/1e 拆分更新,但同一文件里还有三处兄弟列举未更新——第 335 行(Step 3 概览:"skip the adversarial personas 6a/6b/6c and the Agent 8 diff-specialists")、第 443 行(平衡集合为 "(no 6a/6b/6c)")、第 982 行(medium 后续提示:high "adds the reverse audit, the adversarial personas, and Agent 8")。三个捕获命令的 --effort 帮助文案与 RosterPlan.effort 注释同样过时(见 roster.ts 的评论线程)。第 982 行在每次 medium 审查后原样渲染,用户在权衡是否做 high 复审时不会得知 high 还多两个本 PR 新设的正确性专项 agent。建议改为::335 "(skip the adversarial personas 6a/6b/6c, the language-pitfall and wrapper/proxy specialists 1d/1e, and the Agent 8 diff-specialists)";:443 "(no 6a/6b/6c, no 1d/1e)";:982 "(adds the reverse audit, the language-pitfall and wrapper/proxy specialists, the adversarial personas, and Agent 8 — and can certify Approve)"。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| Walk **every hunk, line by line**. For each hunk, read the **enclosing function or method** in the worktree (paging if \`isTruncated\`) so the hunk is judged in its real context and not from three lines of diff context. For every changed line ask: what input, state, timing, or platform makes this line wrong? | ||
|
|
||
| - Inverted or wrong conditions; off-by-one and fence-post errors; null/undefined dereference; a missing \`await\`; falsy-zero checks (\`if (x)\` where \`0\` or \`''\` is a valid value); wrong-variable copy-paste; an error swallowed by a \`catch\` that should propagate; unescaped regex metacharacters | ||
| - Inverted or wrong conditions; off-by-one and fence-post errors; null/undefined dereference; a missing \`await\`; wrong-variable copy-paste; an error swallowed by a \`catch\` that should propagate; unescaped regex metacharacters |
There was a problem hiding this comment.
[Suggestion] This line drops the language-agnostic falsy-zero item from Agent 1a's general correctness list, but its replacement only exists at high effort: 1d/1e are gated behind plan.effort !== 'medium', and medium is the DEFAULT effort for local and file reviews. Before this PR, medium ran all three checks (falsy-zero included) inside 1a's brief; after it, no medium agent is prompted toward any of the three shapes. The design doc's persona analogy does not cover this — the personas never ran at medium, while these checks did, and the doc's no-regression analysis is scoped to 3B only. One aggravating detail: 1d re-files falsy-value bugs only under its JS/TS section, so Python/Go diffs lose the language-agnostic falsy-zero prompt even at high. Concretely: a medium local review of if (timeoutMs) { … } where 0 is valid, or of a cache wrapper whose delegate resolves back through a session registry, has no agent prompted toward either shape.
| - Inverted or wrong conditions; off-by-one and fence-post errors; null/undefined dereference; a missing \`await\`; wrong-variable copy-paste; an error swallowed by a \`catch\` that should propagate; unescaped regex metacharacters | |
| - Inverted or wrong conditions; off-by-one and fence-post errors; null/undefined dereference; a missing \`await\`; falsy-zero checks (\`if (x)\` where \`0\` or \`''\` is a valid value); wrong-variable copy-paste; an error swallowed by a \`catch\` that should propagate; unescaped regex metacharacters |
(restoring the language-agnostic item keeps medium parity and non-JS high coverage; alternatively, state the medium loss in the design doc as a deliberate cost decision.)
中文说明
本行把语言无关的 falsy-zero 条目从 Agent 1a 的通用正确性清单中删除了,但其替代只在 high 档存在:1d/1e 被 plan.effort !== 'medium' 门控,而 medium 是本地与文件审查的默认档。本 PR 之前,medium 通过 1a 的 brief 运行全部三项检查(含 falsy-zero);之后 medium 没有任何 agent 被引导关注这三种形态。设计文档的 personas 类比不成立——personas 从未在 medium 运行过,这些检查却运行过,且文档的"无回归"分析只针对 3B。一个加重细节:1d 只在 JS/TS 小节重新收录了 falsy 值陷阱,因此 Python/Go 的 diff 即使在 high 档也失去了语言无关的 falsy-zero 提示。具体而言:对 0 合法的 if (timeoutMs) { … },或 delegate 绕回 session 注册表自解析的缓存包装器,medium 本地审查没有任何 agent 被引向这两种形态。上方 suggestion 恢复语言无关条目(保住 medium 对等与非 JS 的 high 覆盖);或者在设计文档中把 medium 的损失明确记为有意的成本决策。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| '1b', | ||
| '1d', | ||
| '1e', |
There was a problem hiding this comment.
[Suggestion] This roster-contract pin was extended for 1d/1e — but the two other hand-maintained per-role it.each pins in this file were not: 'welds the diff and every chunk read into role %s' (~line 2596, under "buildRoleBrief — every agent, not just the territory ones") still lists 13 roles without 1d/1e, and 'reaches the code-reviewing dimension %s' (~line 3730) still lists 11. Both new briefs set readsDiff: true/reviewsCode: true and receive exactly those wirings at runtime (diffReadingBlock keyed on brief.readsDiff; path rules keyed on brief.reviewsCode). Nothing is broken today — the wiring is generic — but a future refactor replacing either generic gate with an explicit role list launches 1d/1e with no diff reads (or without the path-scoped workflow checklist) and the whole suite stays green; the weld test's own title claims "every agent", which is now false by two. Verified in a scratch tree: adding '1d'/'1e' to both lists passes green (weld: 13→15 rows; path-rules: 11→13 rows).
中文说明
本处的 roster 契约钉已为 1d/1e 扩展——但本文件另外两处手工维护的按角色 it.each 钉没有扩展:'welds the diff and every chunk read into role %s'(约 2596 行,位于 "buildRoleBrief — every agent, not just the territory ones" 下)仍列 13 个角色、缺 1d/1e;'reaches the code-reviewing dimension %s'(约 3730 行)仍列 11 个。两个新 brief 都设置了 readsDiff: true/reviewsCode: true,运行时也确实获得这两路接线(diffReadingBlock 以 brief.readsDiff 为键;路径规则以 brief.reviewsCode 为键)。当前没有坏——接线是泛型的——但未来若有重构把任一泛型门换成显式角色清单,1d/1e 将在没有 diff 读取(或没有路径规则清单)的情况下被启动,而整套测试依然绿;weld 测试自己的标题声称 "every agent",现在少了两个。已在临时树验证:把 '1d'/'1e' 加入两个清单后测试全绿(weld:13→15 行;path-rules:11→13 行)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #9805 (review feedback round 1)Branch Feedback dispositionsAll 8 inline findings are [Suggestion] from the automated reviewer (round 1, COMMENTED — no blockers). Every one was verified against the code first, then implemented. Nothing was declined, deferred, or escalated.
Mutation probes (witness verification)
Verification
中文说明轮次总结 — PR #9805(审查反馈第 1 轮)分支 反馈处理结果全部 8 条行内发现均为自动审查者的 [Suggestion](第 1 轮,COMMENTED — 无阻断问题)。每一条都先对照代码核实,然后实现。没有拒绝、延后或升级任何条目。
突变探针(见证验证)
验证
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.
Reviewed. Suggestions are inline.
Test Plan (not a blocker): 4781 passed — this review observed 23509, 20954, 1685, 1653, 495, 4159, 599 passed; 32 passed — this review observed 23509, 20954, 1685, 1653, 495, 4159, 599 passed.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/core/src/skills/bundled/review/SKILL.md:517 — [review] SKILL.md states Agent 1e is rostered "only when wrapperSignal is true" — inverse of the implemented fail-safe gate (roster.ts !== false) — and SKILL.test.ts pins the inverse wo…
中文说明
已审查。 建议见行内评论。
Test Plan(非阻断):4781 passed — this review observed 23509, 20954, 1685, 1653, 495, 4159, 599 passed; 32 passed — this review observed 23509, 20954, 1685, 1653, 495, 4159, 599 passed。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| 'personas (6a/6b/6c) and the language-pitfall and wrapper/proxy ' + | ||
| 'specialists (1d/1e) from the required roster; recorded in the plan ' + |
There was a problem hiding this comment.
[Suggestion] This --effort describe (with the 1d/1e roster wording this round adds) exists as three byte-identical copies — fetch-pr.ts:1891-1898, capture-local.ts:186-195, and plan-diff.ts:199-206 — and this change hand-applied the same roster-wording edit to all three, while a shared source already exists in the neighbourhood: EFFORT_LEVELS in parse-args.ts:143, already consumed by run.ts, save-artifact.ts, lib/effort.ts, and lib/resume.ts. The cost is exactly what this diff demonstrates: any future roster change must make the identical edit in three files, and a partial update silently diverges the user-facing --help of the three capture commands about what medium drops — no test asserts help text against the roster, so the drift ships. Define the option once next to EFFORT_LEVELS (e.g. export const EFFORT_OPTION = { type: 'string', choices: [...EFFORT_LEVELS], describe: '…' } as const;) and use .option('effort', EFFORT_OPTION) in the three capture commands. (run.ts's describe is deliberately different — per-target defaults — so only these three unify.)
中文说明
[建议] 这个 --effort describe(含本轮新增的 1d/1e roster 措辞)以三份逐字节相同的副本存在——fetch-pr.ts:1891-1898、capture-local.ts:186-195、plan-diff.ts:199-206——本轮改动把同一处 roster 措辞手工应用到全部三处。而附近已有共享源:parse-args.ts:143 的 EFFORT_LEVELS 已被 run.ts、save-artifact.ts、lib/effort.ts、lib/resume.ts 使用。成本正是本 diff 演示的:未来任何 roster 变更都必须在三个文件做完全相同的编辑,部分更新会让三个捕获命令面向用户的 --help 在「medium 去掉什么」上悄悄分叉——没有测试对照 roster 断言帮助文本,所以这种漂移会直接带病上线。建议在 EFFORT_LEVELS 旁定义一次选项(例如 export const EFFORT_OPTION = { type: 'string', choices: [...EFFORT_LEVELS], describe: '…' } as const;),并在三个捕获命令中使用 .option('effort', EFFORT_OPTION)。(run.ts 的 describe 是有意不同的——默认值按目标而异——所以只统一这三处。)
— qwen3.8-max via Qwen Code /review (v0.22.0)
| ); | ||
| }); | ||
|
|
||
| it('keeps the language-agnostic falsy-zero shape in the Agent 1a brief', () => { |
There was a problem hiding this comment.
[Suggestion] The removal of the language-pitfall and wrapper/proxy bullets from BRIEFS['1a'] — the core deletion this split makes — is pinned by no test: the keep-side is pinned here (the falsy-zero shape stays in 1a), and SKILL.test.ts negatively pins SKILL.md's digest row, but the brief agents actually read has no assertion that the moved clauses are absent from it. A future edit that re-adds either bullet to 1a's brief (a merge resolution, or a "restore pitfall coverage for medium reviews" attempt aimed at the wrong role) keeps every suite green — at high effort 1a's walk and Agents 1d/1e then double-flag the same ground, re-diluting the checklist inside the walk rhythm, the exact problem the linked issue's split removes. Add a sibling negative pin beside this test, mirroring the negative pin SKILL.test.ts applies to the digest row:
it('keeps the moved checklists out of the Agent 1a brief', () => {
const brief = buildRoleBrief(PLAN, '1a');
expect(brief).not.toContain('language-pitfall checklist for this diff');
expect(brief).not.toContain('**Wrapper/proxy routing.**');
});中文说明
[建议] 从 BRIEFS['1a'] 中移除语言陷阱与包装/代理两个子弹点——本次拆分最核心的删除——没有任何测试钉住:保留侧在这里被钉住(falsy-zero 形态留在 1a),SKILL.test.ts 也负向钉住了 SKILL.md 的角色表行,但 agent 实际读取的 brief 却没有断言被移走的子句不在其中。未来某个编辑把任一子弹点加回 1a 的 brief(合并冲突消解,或一次瞄准错角色的「为 medium 恢复陷阱覆盖」尝试)时,所有测试套件仍会是绿的——high 档下 1a 的逐行走查与 Agent 1d/1e 将对同一片代码重复标记,清单再次被走查节奏冲淡,这正是关联 issue 拆分要消除的问题。建议在本测试旁新增一个对称的负向钉住,与 SKILL.test.ts 对角色表行的负向钉住呼应(代码见英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下: Autofix round summary — PR #9805 (round 2)Both inline Suggestions from the automated reviewer are addressed; the review body's deferred item was left alone as the reviewer requested. Commit: Feedback points and dispositions[rc:3839266200] [Suggestion] [rc:3839266201] [Suggestion] the core deletion (moved checklists out of [rv:5003073602] review body (COMMENTED) — no action beyond its inline suggestions. Failed checks (all CANCELLED) — no code action. Conflict notesNone — VerificationCommands actually run this round:
中文说明Autofix 本轮总结 — PR #9805(第 2 轮)自动审查者的两条行内 Suggestion 均已处理;审查正文中的延后项按审查者要求未做改动。提交: 反馈点与处置[rc:3839266200] [Suggestion] [rc:3839266201] [Suggestion] 核心删除(把清单移出 [rv:5003073602] 审查正文(COMMENTED)— 除其行内建议外不做其他动作。 失败检查(全部 CANCELLED)— 无需代码动作。 冲突说明无 — 验证本轮实际运行的命令:
🦷 Gate advisory — this round's changed tests all pass on the pre-round tree (machine-measured, not agent-authored). Expected for a refactor or coverage addition; if this round was meant to FIX a defect, that defect did not reproduce. · 本轮改动的测试在轮前树上全部通过(门自动测量,非 agent 文本)。对重构或补充覆盖属正常;若本轮意在修复缺陷,则该缺陷未能复现。 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.8-max via Qwen Code /review (v0.22.0)
| - **JS/TS:** \`==\` where \`===\` is owed; falsy-value bugs (\`if (x)\` or \`x || def\` where \`0\`, \`''\` or \`false\` is a legitimate value); a closure capturing a loop variable; floating (un-awaited) promises and unhandled rejections; mutation of an array/object shared across a boundary; \`parseInt\` without a radix. | ||
| - **Python:** mutable default arguments; late-binding closures in loops; in-place mutation of a shared/default collection; a bare \`except:\` swallowing \`KeyboardInterrupt\`/\`SystemExit\`; integer division where float is intended. | ||
| - **Go:** writes to a nil map; range-variable capture in a closure or goroutine (when the module targets the per-iteration semantics or below); an error assigned to \`_\`; \`defer\` inside a loop pinning a resource until function exit. | ||
| - **Java/Kotlin:** \`==\` where \`.equals\` is owed (boxed types, \`String\`); \`Optional.get\` without \`isPresent\`; mutating a collection during iteration over it; an \`AutoCloseable\` never closed. |
There was a problem hiding this comment.
[Suggestion] These two checklist entries invert the language semantics they are meant to enforce. In Go, range-variable capture is the pre-1.22/per-loop footgun; modules using Go 1.22+ per-iteration variables are specifically no longer vulnerable (Go 1.22 release notes). In Kotlin, == is already structural equality and translates to equals; === is referential (Kotlin equality docs). As written, Agent 1d can report correct Go 1.22 and Kotlin code as a bug. Please split Java from Kotlin and phrase the Go item as "only under pre-1.22/per-loop semantics", then pin those distinctions in the brief test.
|
🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下: Round 3 — address-review summary (PR #9805)Outcome: changed. One commit on Feedback points and decisions
Nothing was declined, deferred, or escalated this round. No test was deleted or weakened. Mutation probes (witness check)
Verification
中文说明第 3 轮 — address-review 总结(PR #9805)结果:有改动。 在 反馈点与决定
本轮没有拒绝、推迟或升级任何反馈点。没有删除或削弱任何测试。 变异探针(见证检查)
验证
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.
Reviewed — no blockers. Suggestions are inline.
Test Plan (not a blocker): 4781 passed — this review observed 23508 passed; 32 passed — this review observed 23508 passed.
Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/lib/agent-briefs.ts:327 — [probe] JS/TS loop-variable-capture checklist item unscoped — let/const for-head captures are safe since ES2015
中文说明
已审查——无阻断问题。 建议见行内评论。
Test Plan(非阻断):4781 passed — this review observed 23508 passed; 32 passed — this review observed 23508 passed。
收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| expect(brief).toContain('**Java:**'); | ||
| expect(brief).toContain('`===` where `==` is owed'); |
There was a problem hiding this comment.
[Suggestion] This new semantics test pins the corrected operator direction for Go and Kotlin, but the Java entry's direction is left unpinned — only the **Java:** label is asserted, even though the Java line was rewritten by this same diff and the test's stated purpose is "so a re-inversion ships red". A mutation probe settled it: with the Java entry inverted to `.equals` where `==` is owed the entire review suite still passes (Test Files 101 passed (101), Tests 4786 passed | 4 skipped — the mutant survives), while adding the assertion below flips the probe red and stays green against the correct code. If such an inversion ever ships, Agent 1d's checklist tells the reviewer the Java pitfall is using .equals where == is owed, prompting false findings against correct Java equality comparisons — the exact failure the test's own comment describes.
| expect(brief).toContain('**Java:**'); | |
| expect(brief).toContain('`===` where `==` is owed'); | |
| expect(brief).toContain('**Java:**'); | |
| expect(brief).toContain('`==` where `.equals` is owed'); | |
| expect(brief).toContain('`===` where `==` is owed'); |
中文说明
[Suggestion] 新增的语义测试固定了 Go 与 Kotlin 条目的运算符方向修正,但 Java 条目的方向没有被固定——尽管 Java 行正是本 diff 重写的,且测试注释声明其目的是"让再次反转直接红",这里却只断言了 **Java:** 标签。变异探针验证:把 Java 条目反转为 `.equals` where `==` is owed 后,整个 review 测试套件仍然全绿(Test Files 101 passed (101), Tests 4786 passed | 4 skipped——变异体存活);加上下面的断言后探针立即变红,且对正确代码保持绿色。若此类反转将来真的进入代码,Agent 1d 的清单会告诉审查者 Java 的陷阱是"在应该用 == 的地方用了 .equals",从而对正确的 Java 相等比较产生误报——正是测试注释所描述的那种失败。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
|
||
| - **JS/TS:** \`==\` where \`===\` is owed; falsy-value bugs (\`if (x)\` or \`x || def\` where \`0\`, \`''\` or \`false\` is a legitimate value); a closure capturing a loop variable; floating (un-awaited) promises and unhandled rejections; mutation of an array/object shared across a boundary; \`parseInt\` without a radix. | ||
| - **Python:** mutable default arguments; late-binding closures in loops; in-place mutation of a shared/default collection; a bare \`except:\` swallowing \`KeyboardInterrupt\`/\`SystemExit\`; integer division where float is intended. | ||
| - **Go:** writes to a nil map; range-variable capture in a closure or goroutine (a footgun only under the pre-1.22 per-loop semantics — Go 1.22+ allocates the loop variable per iteration, so the capture is safe); an error assigned to \`_\`; \`defer\` inside a loop pinning a resource until function exit. |
There was a problem hiding this comment.
[Suggestion] The corrected Go entry's safe-case cue no longer names what actually gates the semantics. The pre-fix wording bound the safe case to the module target; the rewrite leaves "Go 1.22+" ambiguous between the installed toolchain and the module's go directive — and per-iteration loop semantics are gated by the go.mod go directive, not the toolchain version. Measured with go1.23.4 in a scratch tree, identical closure-capture code, toolchain held constant: a go 1.21 module prints 4 4 4 (shared loop variable — the capture bug fires), a go 1.22 module prints 1 2 3 (per-iteration — safe). So in a repo pinning an older directive while CI runs Go 1.22+, Agent 1d's cheapest check (go version → 1.23) plus the current unbound cue concludes the capture is safe, and the bug ships unflagged by the agent created to catch it — the false-negative mirror image of the false-positive inversion this commit fixed. Re-binding the safe case to the directive keeps both pinned substrings (only under the pre-1.22 per-loop semantics, Go 1.22+), so the new test stays green; backticks in the replacement need the file's template-literal escaping, as on the surrounding lines:
- … so the capture is safe …
→ - … — check the module's `go` directive in go.mod, not the installed toolchain: a module targeting Go 1.22+ allocates the loop variable per iteration, so the capture is safe …
中文说明
[Suggestion] 修正后的 Go 条目的"安全情形"提示没有再点明真正决定语义的开关。旧措辞把安全情形绑定到模块目标版本;重写后 "Go 1.22+" 在所装工具链与模块 go 指令之间含糊不清——而逐迭代循环变量语义由 go.mod 的 go 指令决定,与工具链版本无关。在 scratch tree 中用 go1.23.4 实测(闭包捕获代码完全相同、工具链保持恒定):go 1.21 模块输出 4 4 4(共享循环变量——捕获缺陷触发),go 1.22 模块输出 1 2 3(逐迭代——安全)。因此在一个锁定旧指令、CI 却跑 Go 1.22+ 的仓库里,Agent 1d 最廉价的检查(go version → 1.23)加上当前未绑定的提示会得出"捕获是安全的"结论,缺陷就会在专为捕获它而生的 agent 眼皮底下溜走——正是本次提交修复的那类"误报正确代码"缺陷的反向镜像(漏报)。把安全情形重新绑定到模块指令可以保留两个被测试固定的子串(only under the pre-1.22 per-loop semantics、Go 1.22+),新测试保持绿色;替换文本中的反引号需要按本文件模板字符串的转义方式书写(与相邻行一致)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
🤖 Addressed the latest review feedback (round 4/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 4/100 轮)。改动内容与我反驳保留之处如下: Round 4 summary — PR #9805 (1d/1e split)Commit: Feedback points and decisions1. [rc:3840488671] 2. [rc:3840488678] 3. [rv:5004308139] recorded deferred item — the JS/TS loop-capture checklist item is unscoped → IMPLEMENTED (verified true). 4. [rv:5004308139] Test Plan count observation ( Changes
Deferred / declined / escalatedNone declined without evidence, none deferred to the follow-up queue, none escalated for a maintainer decision. Item 3 above was addressed despite the reviewer's deferral; the reason is recorded here. VerificationCommands actually run this round (from the repository root unless noted):
中文说明第 4 轮总结 — PR #9805(1d/1e 拆分)提交: 反馈点与处理决定1. [rc:3840488671] 2. [rc:3840488678] 3. [rv:5004308139] 记录在案的延后项 — JS/TS 循环捕获清单项未限定作用域 → 已实现(已验证为真)。 4. [rv:5004308139] Test Plan 计数观察( 变更内容
延后 / 拒绝 / 升级无"无证据拒绝"项,无"延后至跟进队列"项,无"升级待维护者决策"项。上述第 3 项在审查者已延后的情况下仍被处理,原因已在此记录。 验证本轮实际运行的命令(除注明外在仓库根目录执行):
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.
Partially reviewed — gaps disclosed. Suggestions are inline.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R5-2 position-free Java/Kotlin phrase-swap survives the semantics test's pins — already reported at packages/cli/src/commands/review/agent-prompt.test.ts:2703 (comment 3840488671)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Deferred under the convergence posture (round 5, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/agent-prompt.test.ts:3865 — [probe] 1e's precision-clause phrase the callers a wrapper does not forward is unpinned in the lightweight-mode test (deletes green)packages/cli/src/commands/review/lib/agent-briefs.ts:337 — [probe] Agent 1e's brief has zero content pins — its forwarding-fidelity step deletes green across all 1171 tests (asymmetric with 1d's semantics test)
Convergence: round 5 posted 1 inline comment(s), 1 of them reported for the first time; the previous round posted 2 (2 new). Findings keep coming back to the same files: packages/cli/src/commands/review/agent-prompt.test.ts (findings in round 4; 1 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. No Critical finding is open on this round, so merging and moving the remaining Suggestion threads to a follow-up issue is available as an ending — a merged pull request cannot diverge further. (Observation only — nothing was withheld from this review because of this observation.)
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
收敛姿态下延后(第 5 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
收敛情况:第 5 轮发布了 1 条行内评论,其中 1 条是首次提出;上一轮发布了 2 条(其中 2 条首次提出)。发现反复回到同一批文件:packages/cli/src/commands/review/agent-prompt.test.ts(第 4 轮已出过发现,本轮又有 1 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。本轮没有未决的 Critical,因此"合入后把剩余 Suggestion 线程转到后续 issue"是一个可选的结束方式——已合入的 PR 不会继续发散。(仅为观察——本轮评审未因此扣留任何内容。)
— qwen3.8-max via Qwen Code /review (v0.22.0)
| expect(brief).toContain('only under the pre-1.22 per-loop semantics'); | ||
| expect(brief).toContain("module's `go` directive in go.mod"); | ||
| expect(brief).toContain('Go 1.22+'); |
There was a problem hiding this comment.
[Suggestion] R5-1: This test pins the checklist cue phrases but leaves five load-bearing protection clauses unpinned, so each one deletes or inverts while the suite stays green — defeating the test's own stated purpose ("Pin the corrected wording, per language, so a re-inversion ships red").
Unpinned fragments: (1) not the installed toolchain (Go item, agent-briefs.ts:329, written this round); (2) the for-head reassurance (let/const for-heads bind per iteration, so those captures are safe) (JS/TS item, agent-briefs.ts:327, written this round); (3) the Go conclusion clause allocates the loop variable per iteration, so the capture is safe (agent-briefs.ts:329, written this round); (4) Java's scope limiter (boxed types, String) (agent-briefs.ts:330); (5) Kotlin's semantics tail — Kotlin ==is already structural equality (it callsequals), === is identity (agent-briefs.ts:331).
Each was mutation-probed at this commit: inverting (3) to "still allocates the loop variable per function, so the capture is unsafe" ships green — this suite 297/297 and all six other brief-consuming suites 874/874 — re-opening exactly the round-4 false positive (correct Go 1.22 code flagged as a bug); deleting (4) ships green and leaves the Java cue unqualified, so Agent 1d pattern-matches any == — including if (x == null) and primitive/enum comparisons where == is correct — and files false Criticals; inverting (5) ships green and makes 1d report correct Kotlin == structural comparisons as bugs; deleting (1) or (2) each ships green (1004/1005 across the five importing suites). Every pin suggested below flips its mutation red and passes on HEAD. Subsumes the same-class gaps reported separately during this review (Go conclusion clause; Java/Kotlin qualifiers).
Suggested fix — add inside this test:
expect(brief).toContain('not the installed toolchain');
expect(brief).toContain('for-heads bind per iteration');
expect(brief).toContain('allocates the loop variable per iteration, so the capture is safe');
expect(brief).toContain('(boxed types, `String`)');
expect(brief).toContain('`===` is identity');中文说明
该测试固定了清单条目的提示短语,但有 5 处承重的保护性子句未被固定——每一处都可以在测试套件全绿的情况下被删除或反转,这与测试自己声明的目的("逐语言固定修正后的措辞,使再次反转会被测试拦下")相悖。
未固定的片段:(1) not the installed toolchain(Go 条目,agent-briefs.ts:329,本轮新写);(2) for 循环头免责说明 (let/const for-heads bind per iteration, so those captures are safe)(JS/TS 条目,agent-briefs.ts:327,本轮新写);(3) Go 结论子句 allocates the loop variable per iteration, so the capture is safe(agent-briefs.ts:329,本轮新写);(4) Java 范围限定 (boxed types, String)(agent-briefs.ts:330);(5) Kotlin 语义尾注 —— Kotlin ==is already structural equality (it callsequals), === is identity(agent-briefs.ts:331)。
每一处都在本提交上做了变异探针验证:把 (3) 反转为 "still allocates the loop variable per function, so the capture is unsafe" 后测试仍全绿——本套件 297/297,其余 6 个消费 brief 的套件 874/874——恰好重新打开第 4 轮的误报(正确的 Go 1.22 代码被当成缺陷);删除 (4) 后全绿,Java 提示失去限定,Agent 1d 会对任意 == 做模式匹配——包括 if (x == null) 以及本应使用 == 的基本类型/枚举比较——从而提交假 Critical;反转 (5) 后全绿,1d 会把正确的 Kotlin == 结构化比较报告为缺陷;删除 (1) 或 (2) 各自全绿(5 个导入套件 1004/1005)。下面建议的每一条固定都能让对应变异变红,且在 HEAD 上通过。本轮单独报告过的同类缺口(Go 结论子句、Java/Kotlin 限定语)已并入本条。
建议修复——在同一测试中补充上述 5 条 expect(brief).toContain(...) 断言(代码见英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 62 passed · 0 failed · 62 total Flakiness gate: ✅ 5 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:62 通过 · 0 失败 · 62 总计 抖动门:✅ 5 changed test file(s) x 5 identical rounds, no divergence Verification reportPR 9805 Deep Verification — feat(review): promote language-pitfall and wrapper/proxy checks out of Agent 1aVerdict: 中文摘要
Central claim and A/B proofCentral claim. At high effort the two checks folded into Agent 1a's walk become dedicated Step 3A roles — 1d always, 1e gated by a capture-time A/B design. Both arms drive the real compiled CLI (
All 38 harness assertions pass; the base arm fails exactly as a pre-PR control must (no 1d/1e anywhere), which is the load-bearing evidence that the split — not pre-existing behaviour — produces the new roster. Doc-count cross-check (witness: CorrectionsNone — no earlier-round or bot claims needed correcting (first verification round). FindingsNo blocking findings. Non-blocking observations, in the open:
Mutation matrix — every guard the PR introduces (witness:
|
| Mutant | Guard attacked | Suite | Result |
|---|---|---|---|
| M0 | unmutated control | roster.test.ts | 45/45 green |
| M1 (positive control) | delete add('1d')/add('1e') |
roster.test.ts | KILLED — 2 red, intended tests |
| M1b | same deletion | agent-prompt.test.ts | KILLED — "builds and records the whole 3A roster" |
| M2 | invert fail-safe to === true |
roster.test.ts | KILLED — the fail-safe test |
| M3 | nest add('1d') inside the wrapper gate |
roster.test.ts | KILLED — "explicit false drops ONLY 1e" |
| M4 | drop cached|caching from the regex |
diff-plan.test.ts | KILLED — 2 red |
| M5 | delete the path-based signal check | diff-plan.test.ts | KILLED — incl. the refined-path-timing test |
| M6 | drop the report carry-through | report.test.ts | KILLED |
| M7 | re-add the wrapper clause to 1a's brief | agent-prompt.test.ts | KILLED — "keeps the moved checklists out" |
| M8 | restore the folded clause in SKILL.md | SKILL.test.ts | KILLED |
| M9 | revert 1e out of the diff-only precision clause | agent-prompt.test.ts | KILLED — "stops 1b, 1c and 1e asserting…" |
10/10 killed, 0 survivors, each by the assertion it was written for (failure names quoted in logs/m*.log); M1 is the positive control proving the harness can go red, and every control ran in the same file as its mutant. The unmutated gates were green (cli review suite 4924 passed / 4 skipped / 0 failed across 102 files; core SKILL.test.ts 40/40), so the kills are meaningful. No layered-guard combination rows were needed: each hazard has one guard per surface, and the serial chain (capture writes → roster reads) is attacked independently at both ends (M4/M5 vs M2/M3).
Targeted gates
| Gate | Result |
|---|---|
cd packages/cli && npx vitest run src/commands/review |
102 files, 4924 passed | 4 skipped, 0 failed (PR claimed 101/4781 — the merge tip runs more; directionally consistent, greener) |
cd packages/core && npx vitest run src/skills/bundled/review/SKILL.test.ts |
40 passed (PR claimed 32) |
npm run typecheck |
exit 0 across all 13 workspaces |
Field-trace: wrapperSignal read sites |
exactly one reader (roster.ts gate) + one writer chain (diff-plan → report); no dead reads |
--role selectors |
derived from Object.keys(BRIEFS) — 1d/1e included automatically, no stale choice list |
Not covered
- Dogfooding claim (full model-driven
/reviewof this PR at high effort, 15 agents, 5/5 chunks): requires model API access this sandbox does not have. The roster/coverage machinery that run exercises is what the A/B and mutation matrix prove; the model-side behaviour of the new briefs is out of scope for any sandbox round. - Behavioural
check-coveragereplay of a run that skipped 1d/1e — verified structurally instead:lib/coverage.ts:500calls the samerequiredAgents(plan)the roster prints, and the prompt records (A/B oracle) are exactly what the gate reads; the full suite includingcheck-coverage.test.tsis green. capture-local/fetch-prE2E:plan-diffwas driven end-to-end; the other two capture commands sharebuildPlanReport+planEffortFieldverbatim (M6 kills the carry-through;EFFORT_OPTIONis now the single shared definition).fetch-pradditionally needs network/gh, absent by design here.- Per-commit review: the checkout is depth 2 — locally reachable commits are the merge, base tip and PR head, while the metadata lists 5 commits (4 review-round fixes).
git rev-parse --is-shallow-repository= true confirms the gap; the aggregateHEAD^1..HEADdiff is what was verified. - The shipped
dist/cli.jsbundle: the CI image's bundle was stale (0×wrapperSignal), so both arms used the per-packagedist/index.jsentry (bin: qwen). An environment note, not a PR defect — the author's bundle-based E2E claim stands uncontradicted, and the bundle is rebuilt bynpm run bundlefrom the same sources the per-package dist used. - Repo-wide test suites beyond the affected workspaces; the 3B chunk-brief lens question (explicitly out of scope by the design doc — chunk agents own the dimensions generically, unchanged).
Methodology
Environment: the CI verify container (node:22-bookworm, node v22.23.2), working tree at refs/pull/9805/merge, npm ci + npm run build pre-run. A/B: base side rebuilt only packages/cli in a scratch worktree at HEAD^1 (npm run build -w packages/cli, ~1 TypeScript error pre-existing in the base control build — an @lydell/node-pty declaration in core's shellExecutionService — which does not touch emit or the review path; disclosed rather than spent on). The base tree wires to the root node_modules; internal workspace links were asserted per the merge-warning: readlink -f node_modules/@qwen-code/qwen-code-core → the head tree's core dist. That is a clean control for this PR because its entire core diff is SKILL.md + its test — assets no review subcommand loads at runtime — and every mutated surface lives in packages/cli. Package-local node_modules (cli, core, channels) were symlinked into the base tree unchanged; the PR touches no lockfile, so dependency state is identical on both arms. Harnesses (ab-roster.mjs, probe2.mjs, mutations.sh, print-matrix.mjs) live in the artifact dir with raw per-mutant vitest logs under logs/; every assertion is a scripted comparison that can fail, and assertions.json counts only executed checks — audit.mjs mechanically re-derives all 62 from the captured artifacts (harness result files, mutant logs with intended-test matching, gate logs/junit) and exits 0. Mutants were applied in place with perl, verified byte-applied on scratch copies first, run against the single suite that owns them, and restored via git checkout -- (git status --porcelain empty after each and at the end). Evidence images were rendered by scripts/verify-capture.mjs from live runs of the harnesses.
Flakiness gate log
rounds=5 files=5 skipped=0
file packages/cli/src/commands/review/agent-prompt.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/agent-prompt.test.ts
file packages/cli/src/commands/review/lib/diff-plan.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/diff-plan.test.ts
file packages/cli/src/commands/review/lib/report.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/report.test.ts
file packages/cli/src/commands/review/lib/roster.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/roster.test.ts
file packages/core/src/skills/bundled/review/SKILL.test.ts: (cd packages/core) npx --no-install vitest run ./src/skills/bundled/review/SKILL.test.ts
per-file results (P=pass F=fail I=infra-exit, one letter per run):
packages/cli/src/commands/review/agent-prompt.test.ts: PPPPP
packages/cli/src/commands/review/lib/diff-plan.test.ts: PPPPP
packages/cli/src/commands/review/lib/report.test.ts: PPPPP
packages/cli/src/commands/review/lib/roster.test.ts: PPPPP
packages/core/src/skills/bundled/review/SKILL.test.ts: PPPPP
verdict: pass
summary: 5 changed test file(s) x 5 identical rounds, no divergence
--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 1 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 2 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 3 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 4 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 5 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
Evidence images
Harness scripts and raw logs are in the workflow run artifacts (7-day retention).
— Qwen Code · sandboxed verification
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下: Round 5 — address-review summary (PR #9805)One commit this round: Feedback points and dispositions1. rc:3841188819 — R5-1 [Suggestion]: five load-bearing protection clauses unpinned in the semantics test — Acted onThe claim was checkable and was reproduced before any edit: each of the six mutants below was applied to
Fix: added the five suggested pins inside Witness verification: after the fix, every one of the six mutants fails the suite (1 failed | 296 passed each), and the failing test was confirmed to be 2. R5-2 (review body, deduped to comment 3840488671) — position-free Java/Kotlin phrase swap — Acted on (same root cause)The original thread 3840488671 asked for the Java direction pin, which round 4 added. This round's re-detection describes the surviving sibling: swapping the Java and Kotlin cue phrases between the two entries ships green because the pins were position-free ( Fixed at the root cause, subtractively: the three position-free presence pins ( 3. Two items deferred under the convergence posture — Left untouched, recorded
The review explicitly deferred both: "recorded, not requested in this round." No code was changed for them; they remain on record for a later round or the follow-up path the convergence note describes. 4. ic:5391740417 — sandboxed-verification status comment — No action (informational only)5. Disclosed review gap: Integration Tests (CLI, No Sandbox) not run — Not applicable to this changeThe round's change is test-only (no source, config, or behavioral change), and the pinned behavior is exercised directly by the unit suites below; the workflow's CI remains the final gate. Conflict notesNone — VerificationCommands actually run this round (from the repository root unless noted):
中文说明第 5 轮 — address-review 总结(PR #9805)本轮一个提交: 反馈点与处置1. rc:3841188819 —— R5-1 [Suggestion]:语义测试中有 5 处承重的保护性子句未被固定 —— 已处理该主张可检验,且在动手修改前已完成复现:在下表的六个变异体分别应用于
修复:在 见证验证:修复后,六个变异体中的每一个都使套件失败(各为 1 failed | 296 passed),且确认失败的测试就是 2. R5-2(review 正文,按重复归并到评论 3840488671)—— 无位置的 Java/Kotlin 短语互换 —— 已处理(同一根因)原线程 3840488671 要求补上 Java 方向固定,第 4 轮已加上。本轮的再次检出描述的是幸存的兄弟变异:把 Java 与 Kotlin 的提示短语在两个条目之间互换后测试仍全绿,因为原有固定是无位置的(对每个短语独立做 按根因修复,且为缩减式:三条无位置的存在性固定( 3. 收敛姿态下延后的两项 —— 未改动,仅记录
审查方已明确延后这两项:"已记录,本轮不要求修改"。未为其改动任何代码;它们保留在记录中,留待后续轮次或收敛说明中所述的后续跟进路径处理。 4. ic:5391740417 —— 沙箱验证状态评论 —— 无需处理(纯信息性)5. 已披露的审查缺口:Integration Tests (CLI, No Sandbox) 未运行 —— 与本次改动无关本轮改动为纯测试改动(无源码、配置或行为变化),被固定的行为由下文的单元测试套件直接覆盖;工作流的 CI 仍是最终验证关卡。 冲突说明无 —— 验证本轮实际运行的命令(除注明外均在仓库根目录执行):
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.
Not explored to full depth (tool budget reached): "agent 6c": running agent-prompt.test.ts — the shared review worktree has no node_modules , and installing/building workspace deps exceeds what this review should distur…; "agent 1b": running packages/cli vitest for agent-prompt.test.ts (no node_modules/dist in review worktree; assertions verified statically instead); "agent 3c": running agent-prompt.test.ts under vitest** — the worktree has no installed node_modules ( vitest/config unresolved), and installing into the shared review…; "agent 5": running agent-prompt.test.ts in vitest (worktree has no node_modules; npm ci + workspace build exceeded the tool-call budget — all assertions were verified stat….
Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/agent-prompt.test.ts:2684 — [probe] 1d/1e semantics-pin surface under-pinned — close structurally (class finding; supersedes the round's eight probe-confirmed pin-gap siblings)
中文说明
未探索到全部深度(达到工具调用预算):"agent 6c":running agent-prompt.test.ts — the shared review worktree has no node_modules , and installing/building workspace deps exceeds what this review should distur…;"agent 1b":running packages/cli vitest for agent-prompt.test.ts (no node_modules/dist in review worktree; assertions verified statically instead);"agent 3c":running agent-prompt.test.ts under vitest** — the worktree has no installed node_modules ( vitest/config unresolved), and installing into the shared review…;"agent 5":running agent-prompt.test.ts in vitest (worktree has no node_modules; npm ci + workspace build exceeded the tool-call budget — all assertions were verified stat…。
收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 118 passed · 0 failed · 118 total Flakiness gate: ✅ 5 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:118 通过 · 0 失败 · 118 总计 抖动门:✅ 5 changed test file(s) x 5 identical rounds, no divergence Verification report<!-- qwen-triage:verify --> Verdict: 中文摘要
Previous-finding status table (follow-up round)
Central claim and A/B proofCentral claim. At high effort the two checks folded into Agent 1a's walk become dedicated Step 3A roles — 1d always, 1e gated by a capture-time A/B design. Both arms drive the real compiled CLI (
All 53 harness assertions pass; the base arm fails exactly as a pre-PR control must (no 1d/1e anywhere, 1a still carrying both bullets), which is the load-bearing evidence that the split — not pre-existing behaviour — produces the new roster. Doc-count cross-check (within Reviewer Test Plan walkthrough
FindingsNo blocking findings. Non-blocking observations:
Mutation matrix — every guard the PR introduces (witness:
|
| Mutant | Guard attacked | Suite | Result |
|---|---|---|---|
| M0 | unmutated control | roster / diff-plan / report / agent-prompt / SKILL | GREEN — 45/45, 47/47, 14/14, 299/299, 40/40 |
| M1 (positive control) | delete add('1d')/add('1e') |
roster.test.ts | KILLED — 2 red: "requires the language-pitfall scan at high effort…", "requires the wrapper/proxy check unless…" |
| M1b | same deletion | agent-prompt.test.ts | KILLED — "builds and records the whole 3A roster" |
| M2 | invert fail-safe to === true |
roster.test.ts | KILLED — the fail-safe test |
| M3 | nest add('1d') inside the wrapper gate |
roster.test.ts | KILLED — same test (its "explicit false drops ONLY 1e" assertion) |
| M4 | drop cached|caching from the regex |
diff-plan.test.ts | KILLED — 2 red |
| M5 | delete the path-based signal check | diff-plan.test.ts | KILLED — 2 red, incl. the refined-path-timing test |
| M6 | drop the report carry-through | report.test.ts | KILLED — "carries the wrapper signal through…" |
| M7 | re-add the wrapper clause to 1a's brief | agent-prompt.test.ts | KILLED — "keeps the moved checklists out of the Agent 1a brief" |
| M8 | restore the folded clause in SKILL.md | SKILL.test.ts | KILLED — "keeps the language-pitfall and wrapper/proxy checks as dedicated high-effort angles" |
| M9 | revert 1e out of the diff-only precision clause | agent-prompt.test.ts | KILLED — "stops 1b, 1c and 1e asserting what they cannot check" |
10/10 killed, 0 survivors, each by the assertion it was written for (names quoted from logs/m*.log); M1 is the positive control proving the harness can go red, and every suite command has its own landed control (M1/M1b, M4/M5, M6, M7/M9, M8). Worktree clean after every restore (dirty-after-restore=0, final git status --porcelain = 0). No layered-guard combination rows needed: each hazard has one guard per surface, and the serial chain (capture writes → roster reads) is attacked independently at both ends (M4/M5 vs M2/M3/M6).
Targeted gates
| Gate | Result |
|---|---|
cd packages/cli && npx vitest run src/commands/review |
102 files, 4924 passed | 4 skipped, 0 failed |
cd packages/core && npx vitest run src/skills/bundled/review/SKILL.test.ts |
40 passed |
npm run typecheck |
exit 0 |
Field-trace: wrapperSignal sites |
exactly one decision reader (roster.ts:134, !== false), one writer chain (diff-plan → report:186); no dead reads |
check-coverage link |
coverage.ts:500 calls the same requiredAgents(plan) the roster prints — roster and gate cannot disagree |
--role selectors |
derived from Object.keys(BRIEFS) (agent-prompt.ts:1519/2115/3085…) — 1d/1e included automatically, no stale choice list |
Not covered
- Dogfooding claim (model-driven full
/review): requires model API access this sandbox does not have. - Behavioural
check-coveragereplay of a run that skipped 1d/1e — verified structurally (samerequiredAgents, prompt records are the gate's input; full suite green). capture-local/fetch-prE2E:plan-diffdriven end-to-end on both arms; the other two capture commands shareEFFORT_OPTIONandbuildPlanReportverbatim (M6 kills the carry-through).fetch-pradditionally needs network/gh, absent by design here.- Per-commit attribution: the checkout is depth 2 (merge, base tip, PR head reachable; the metadata lists 6 commits). The aggregate
HEAD^1..HEADdiff is what was verified. - Round-4 → round-5 delta: not directly diffable at depth 2. All re-measured values are identical to the previous round's (suite counts 4924/4 and 40/40, the same 10-kill matrix, the same boundary), consistent with a small wording-level delta; the aggregate diff was re-verified in full regardless.
- The shipped
dist/cli.jsbundle: still stale in the CI image (0×wrapperSignal), so both arms used the per-packagedist/index.jsentry (bin:qwen). Environment note, not a PR defect. - Repo-wide suites beyond the affected workspaces; 3B chunk-brief lens attachment (explicitly out of scope by the design doc).
Methodology
Environment: the CI verify container (node:22-bookworm, node v22.23.2), working tree at refs/pull/9805/merge, npm ci + npm run build pre-run at HEAD. A/B: base side rebuilt only packages/cli in a scratch worktree at HEAD^1 (npm run build -w packages/cli, exit 0 after generating the gitignored git-commit.ts and linking the nested per-package node_modules); internal @qwen-code/* links were re-pointed into the base tree this round (previous round left them at the head tree) and realpath-asserted; the PR touches no lockfile, so dependency state is identical on both arms. Harnesses (ab-roster.mjs, boundary-probe.mjs, mutations.sh, print-matrix.mjs) live in the artifact dir with raw per-cell and per-mutant logs under logs/; every assertion is a scripted comparison that can fail, and audit.mjs mechanically re-derives all 118 from the captured artifacts (harness result files, mutant logs, gate logs, source greps) — assertions.json counts only executed checks. Evidence images were rendered by scripts/verify-capture.mjs from live runs of the harnesses. Base worktree removed after the A/B cells were captured.
Flakiness gate log
rounds=5 files=5 skipped=0
file packages/cli/src/commands/review/agent-prompt.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/agent-prompt.test.ts
file packages/cli/src/commands/review/lib/diff-plan.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/diff-plan.test.ts
file packages/cli/src/commands/review/lib/report.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/report.test.ts
file packages/cli/src/commands/review/lib/roster.test.ts: (cd packages/cli) npx --no-install vitest run ./src/commands/review/lib/roster.test.ts
file packages/core/src/skills/bundled/review/SKILL.test.ts: (cd packages/core) npx --no-install vitest run ./src/skills/bundled/review/SKILL.test.ts
per-file results (P=pass F=fail I=infra-exit, one letter per run):
packages/cli/src/commands/review/agent-prompt.test.ts: PPPPP
packages/cli/src/commands/review/lib/diff-plan.test.ts: PPPPP
packages/cli/src/commands/review/lib/report.test.ts: PPPPP
packages/cli/src/commands/review/lib/roster.test.ts: PPPPP
packages/core/src/skills/bundled/review/SKILL.test.ts: PPPPP
verdict: pass
summary: 5 changed test file(s) x 5 identical rounds, no divergence
--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 1 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 1 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 2 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 2 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 3 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 3 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 4 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 4 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/agent-prompt.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/diff-plan.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/report.test.ts: P (exit 0)
round 5 · packages/cli/src/commands/review/lib/roster.test.ts: P (exit 0)
round 5 · packages/core/src/skills/bundled/review/SKILL.test.ts: P (exit 0)
Evidence images
Harness scripts and raw logs are in the workflow run artifacts (7-day retention).
— Qwen Code · sandboxed verification
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix review round: no action taken (PR #9805)This round found nothing to change, so no commit was made.
The branch stays at its current head commit; the next round will pick up any new maintainer or automated feedback when it arrives. 中文说明Autofix 审查轮次:未采取任何操作(PR #9805)本轮没有发现需要修改的内容,因此未创建任何提交。
分支保持在当前头提交;下一轮将在有新的维护者或自动反馈到来时继续处理。 Deferred non-Critical feedbackCritical-only mode is active: 5 change-producing rounds are complete. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (
中文说明已进入仅处理 Critical 的模式:已完成 5 个产生改动的轮次。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
yiliang114
left a comment
There was a problem hiding this comment.
LGTM on the mechanism at head 48ca78b:
- The split is lossless: the two clauses removed from Agent 1a's brief (language-pitfall checklist, wrapper/proxy routing) reappear verbatim in substance as the 1d/1e briefs — no check is dropped, and 1d's scope statement correctly bounds it against 1a/2/3a-3c territory.
- The 1e gate fails safe as designed:
hasWrapperTypesreturns true for everything except an explicitwrapperSignal: false— absent field (older-CLI plan), true, and junk all roster the check, matching the documented version-skew asymmetry (same shape as hasDeletions). - Roster/prompt/coverage derive from the same plan fields: 1d always at high, 1e conditional, medium drops both (documented in the tier note).
- The Go/Kotlin semantics correction raised by doudouOUC's thread is reflected in the later commits (the corrected operator direction is pinned by the semantics test).
CI note at approval time: 15 checks passing; the single "Desktop Shell (${{ matrix.os }}) fail" entry is a stale artifact of run 32702199805, which was CANCELLED whole at 07:35 (the failed job ran zero steps, start==complete same second) and superseded — the same head's Qwen Code CI run is green. The 14 open threads are all Suggestions from rounds predating this head (latest 06:40 vs head 07:25) — doc-enumeration and pin-granularity items for the next bot round, not blockers.
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下: Autofix round: no action needed (PR #9805)This round reviewed the feedback newer than the last evaluation (2026-08-24T10:18:00Z) and found nothing actionable, so no changes were made and nothing was committed. What was reviewed
Critical-only modeCritical-only mode is active (5 change-producing rounds complete). The deferred non-Critical feedback listed in the round input is an audit record and was not acted on, per the workflow rules; those items remain open for human follow-up. ResultNo code changes, no commit, no conflict resolution ( 中文说明Autofix 轮次:无需操作(PR #9805)本轮审阅了上次评估(2026-08-24T10:18:00Z)之后的新反馈,未发现任何可处理的事项,因此未做任何改动,也没有提交任何内容。 审阅内容
仅处理 Critical 模式当前处于仅处理 Critical 的模式(已完成 5 个产生改动的轮次)。本轮输入中列出的被延后非 Critical 反馈属于审计记录,按工作流规则未做处理;这些条目保持开放,留待人工跟进。 结果无代码改动、无提交、无冲突解决( Deferred non-Critical feedbackCritical-only mode is active: 5 change-producing rounds are complete. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (
中文说明已进入仅处理 Critical 的模式:已完成 5 个产生改动的轮次。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧠 Handled by Qwen Code · model/模型 |
wenshao
left a comment
There was a problem hiding this comment.
Not reviewed: reverse audit — reached the configured five-round cap; chunk 5 retired with a final certificate, while the remaining chunks completed round 5 but the loop had no sixth round for further convergence checking.
Not reviewed: test efficacy — inconclusive because isolated changed-test runners lacked green workspace build prerequisites.
Not reviewed: full packages/cli unit suite — timed out after 540 seconds.
Not reviewed: PR Test Plan — two reported test counts differed from the suites observed, and node dist/cli.js was not independently checked.
Test Plan (not a blocker): 4781 passed — this review observed 20952, 1685, 1653, 500, 4159, 599 passed; 32 passed — this review observed 20952, 1685, 1653, 500, 4159, 599 passed.
Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:
docs/users/features/code-review.md:453 — [review] R6 round floor deferral: lower roster counts omit independently conditional Agent 1b. / R6 严重级别门槛延后:lower roster counts 未计入独立条件 Agent 1b。packages/core/src/skills/bundled/review/SKILL.test.ts:105 — [review] R6 round floor deferral: document-wide 1d/1e assertions do not pin selector, role-table, or fail-safe contracts. / R6 严重级别门槛延后:全文 1d/1e 断言未固定 selector、role table 或 fail-sa…packages/core/src/skills/bundled/review/SKILL.md:241 — [review] R6 round floor deferral: active 19–30 call accounting conflicts with maintained 17–28 design/budget rationale. / R6 严重级别门槛延后:active 19–30 calls 与 maintained 17–28 design/budget…docs/users/features/code-review.md:42 — [review] R6 round floor deferral: documented maximum 16 excludes up to two Agent 8 finders. / R6 严重级别门槛延后:文档最大值 16 未计入最多两个 Agent 8 finder。packages/core/src/skills/bundled/review/SKILL.md:343 — [review] R6 round floor deferral: explicit-no-wrapper empty-scope cost wording contradicts the roster. / R6 严重级别门槛延后:explicit-no-wrapper empty-scope 成本描述与 roster 相反。packages/core/src/skills/bundled/review/SKILL.md:303 — [review] R6 round floor deferral: fixed fourteen-lens arithmetic ignores conditional Agents 1b and 1e. / R6 严重级别门槛延后:固定 fourteen-lens 算术忽略 conditional 1b/1e。docs/users/features/code-review.md:126 — [review] R6 round floor deferral: one paragraph says fifteen whole-diff readers while adjacent arithmetic yields fourteen. / R6 严重级别门槛延后:一处写 fifteen whole-diff readers,邻近算术则为 fourteen。packages/cli/src/commands/review/agent-prompt.test.ts:2693 — [review] Existing R5-1 still stands but is deferred by the round-6 Critical-only floor; do not repost. / 既有 R5-1 仍成立,但受第 6 轮仅 Critical 门槛延后,不重复发布。
Mechanism health: this round did not close cleanly, so it withholds the incremental anchor — and the round it recovered had none either, so the next review re-reads the whole diff and will keep doing so until a round's marker carries an anchor again. (Stated, not acted on — this changes nothing about what the round posts.)
[Critical] packages/cli/src/commands/review/lib/diff-plan.ts:377 — renameFrom is stored but ignored when the wrapper signal is finalized. Renaming src/cache-adapter.ts to neutral src/provider.ts with neutral added lines produces wrapperSignal: false and removes Agent 1e; an isolated probe made the signal true when the old path was checked. This location overlaps an existing review comment, so it is reported here instead of reposted inline. (中文:wrapper signal 最终化时保存了 renameFrom 却未检查它。把 src/cache-adapter.ts 重命名为中性 src/provider.ts 且新增行不含关键词时,会产生 wrapperSignal: false 并移除 Agent 1e;隔离 probe 在检查旧路径后 signal 变为 true。该位置与已有评论重叠,因此仅在正文披露,不重复 inline。)
[Critical] packages/cli/src/commands/review/lib/agent-briefs.ts:329 — The Go range-capture guidance checks only the module go directive. A file in a Go 1.21 module guarded by //go:build go1.22 uses Go 1.22 per-iteration semantics, so the brief can file a false blocking Critical. Probe output was 123 with the version constraint and 333 without it. Check the file's effective language version, including applicable versioned build constraints. This finding could not be anchored to an added diff line and is therefore body-only. (中文:Go range-capture 指引只检查 module 的 go directive。Go 1.21 module 中带 //go:build go1.22 的文件使用 Go 1.22 per-iteration semantics,因此该 brief 可能错误提交阻塞性 Critical。probe 在有 constraint 时输出 123,无 constraint 时输出 333。请检查文件的 effective language version,包括适用的 versioned build constraint。该 finding 无法稳定锚定到新增 diff line,因此仅在正文披露。)
中文说明
未审查:reverse audit — reached the configured five-round cap; chunk 5 retired with a final certificate, while the remaining chunks completed round 5 but the loop had no sixth round for further convergence checking。
未审查:test efficacy — inconclusive because isolated changed-test runners lacked green workspace build prerequisites。
未审查:full packages/cli unit suite — timed out after 540 seconds。
未审查:PR Test Plan — two reported test counts differed from the suites observed, and node dist/cli.js was not independently checked。
Test Plan(非阻断):4781 passed — this review observed 20952, 1685, 1653, 500, 4159, 599 passed; 32 passed — this review observed 20952, 1685, 1653, 500, 4159, 599 passed。
收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 8 条(原文未翻译,列表见上方英文部分)。
机制健康:本轮未能干净收尾,因而扣留了增量锚点,而它恢复到的那一轮也没有锚点,因此下一次评审将重读整个 diff——并会一直如此,直到某一轮的标记重新带上锚点。(仅陈述,不据此行动——这不改变本轮发布的任何内容。)
[Critical] packages/cli/src/commands/review/lib/diff-plan.ts:377 — renameFrom is stored but ignored when the wrapper signal is finalized. Renaming src/cache-adapter.ts to neutral src/provider.ts with neutral added lines produces wrapperSignal: false and removes Agent 1e; an isolated probe made the signal true when the old path was checked. This location overlaps an existing review comment, so it is reported here instead of reposted inline. (中文:wrapper signal 最终化时保存了 renameFrom 却未检查它。把 src/cache-adapter.ts 重命名为中性 src/provider.ts 且新增行不含关键词时,会产生 wrapperSignal: false 并移除 Agent 1e;隔离 probe 在检查旧路径后 signal 变为 true。该位置与已有评论重叠,因此仅在正文披露,不重复 inline。)
[Critical] packages/cli/src/commands/review/lib/agent-briefs.ts:329 — The Go range-capture guidance checks only the module go directive. A file in a Go 1.21 module guarded by //go:build go1.22 uses Go 1.22 per-iteration semantics, so the brief can file a false blocking Critical. Probe output was 123 with the version constraint and 333 without it. Check the file's effective language version, including applicable versioned build constraints. This finding could not be anchored to an added diff line and is therefore body-only. (中文:Go range-capture 指引只检查 module 的 go directive。Go 1.21 module 中带 //go:build go1.22 的文件使用 Go 1.22 per-iteration semantics,因此该 brief 可能错误提交阻塞性 Critical。probe 在有 constraint 时输出 123,无 constraint 时输出 333。请检查文件的 effective language version,包括适用的 versioned build constraint。该 finding 无法稳定锚定到新增 diff line,因此仅在正文披露。)
— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)
| readsDiff: true, | ||
| brief: `You are **Agent 1d: the language-pitfall scan**. Your dimension is a CHECKLIST carried against the whole diff, not a line-by-line walk: every language has a short list of classic footguns, and the skill is *pattern-matching* the hunks against the list. That is a different attention mode from judging each line in its context — this check used to ride inside Agent 1a's walk as one bullet, and the walk's rhythm diluted it. You own the instances of these shapes this diff INTRODUCES; general correctness is 1a's, security is 2's, quality is 3a-3c's. | ||
|
|
||
| Name the diff's language and framework first. Then walk every hunk against that language's list: |
There was a problem hiding this comment.
[Critical] Agent 1d starts by asking for the diff language and then applies only that language's checklist. In a polyglot PR, the agent can choose TypeScript and never apply the Go checklist, leaving nil-map writes, loop defer, and range-capture hazards without the specialist coverage this change removed from Agent 1a. Please require enumerating every language in the diff and applying each checklist to its matching hunks.
中文
[严重] Agent 1d 先要求识别“该 diff 的语言”,随后只应用该语言的 checklist。对于 polyglot PR,agent 可能选择 TypeScript 而完全不执行 Go checklist,使 nil-map 写入、循环内 defer、range capture 等问题失去本变更从 Agent 1a 移出的专项覆盖。请要求枚举 diff 中的每种语言,并将各自 checklist 应用于对应 hunks。
— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)
| * wrapping-type shapes (`CachedProvider`, `CachingLayer`). | ||
| */ | ||
| export const WRAPPER_SIGNAL_RE = | ||
| /(wrapper|proxy|decorator|adapter|delegate|facade|cached|caching)/i; |
There was a problem hiding this comment.
[Critical] This vocabulary does not match the common cache-wrapper noun form: neither PersistedSessionListCache nor persisted-session-list-cache.ts contains cached or caching. With neutral changed lines, the plan records wrapperSignal: false, the high-effort roster omits Agent 1e, and Agent 1a no longer owns cache routing. Please recognize cache in declaration/path naming positions while continuing to reject ordinary expressions such as this.cache.set(...); add *Cache and -cache.ts roster fixtures.
中文
[严重] 该词汇表无法匹配常见的 cache-wrapper 名词形式:PersistedSessionListCache 与 persisted-session-list-cache.ts 都不包含 cached 或 caching。当 changed lines 中性时,plan 会得到 wrapperSignal: false,high-effort roster 省略 Agent 1e,而 Agent 1a 已不再负责 cache routing。请仅在 declaration/path 命名位置识别 cache,同时继续排除 this.cache.set(...) 这类普通表达式,并增加 *Cache 与 -cache.ts roster fixture。
— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)
| noteAdded(cur, newCursor); | ||
| newCursor++; | ||
| if (!cur.wrapperSignal) { | ||
| cur.wrapperSignal = WRAPPER_SIGNAL_RE.test(line); |
There was a problem hiding this comment.
[Critical] Wrapper detection ignores unchanged context. When a wrapper in a neutral path changes a forwarding method, its class declaration is commonly context-only and the added line may contain no vocabulary; the plan then emits wrapperSignal: false and drops Agent 1e even though Agent 1a no longer owns wrapper routing. A focused probe reproduced {"wrapperSignal":false,"has1e":false}; matching new-side context made the signal true. Please include context declarations in the signal or retain a reliable fallback owner, and add this modified-wrapper fixture.
中文
[严重] wrapper detection 会忽略未变更的 context。中性路径中的 wrapper 修改 forwarding method 时,class 声明通常只出现在 context,新增行也可能不含任何关键词;此时 plan 会产生 wrapperSignal: false 并移除 Agent 1e,而 Agent 1a 已不再负责 wrapper routing。定向 probe 复现了 {"wrapperSignal":false,"has1e":false};把 new-side context 纳入匹配后 signal 变为 true。请把 context declaration 计入 signal,或保留可靠的 fallback owner,并增加该 modified-wrapper fixture。
— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)
| ## Step 3: Parallel review (high and medium effort) | ||
|
|
||
| **Steps 3A/3B and 4 run at high and medium effort; Step 5 (reverse audit) is high only.** At **low** effort skip 3A/3B/4/5 and run **Step 3C** instead — an inline pass with no subagents, defined after the agent dimensions. **Medium** runs 3A/3B and Step 4 with the reductions the effort table names: a smaller dimension set (skip the adversarial personas 6a/6b/6c and the Agent 8 diff-specialists), a capped territory fan-out on large diffs (Step 3B below), and **no reverse audit** — it stops after Step 4. The incremental cache and PR posting stay high-only at medium too. | ||
| **Steps 3A/3B and 4 run at high and medium effort; Step 5 (reverse audit) is high only.** At **low** effort skip 3A/3B/4/5 and run **Step 3C** instead — an inline pass with no subagents, defined after the agent dimensions. **Medium** runs 3A/3B and Step 4 with the reductions the effort table names: a smaller dimension set (skip the adversarial personas 6a/6b/6c, the language-pitfall and wrapper/proxy specialists 1d/1e, and the Agent 8 diff-specialists), a capped territory fan-out on large diffs (Step 3B below), and **no reverse audit** — it stops after Step 4. The incremental cache and PR posting stay high-only at medium too. |
There was a problem hiding this comment.
[Critical] Medium effort says it skips adversarial personas, but Step 3B's effort-independent chunk brief still assigns the adversarial reading to every territory agent. Thus large medium reviews continue performing and paying for the dimension this contract removes. A focused prompt probe failed expect(medium).not.toContain('the adversarial reading'); an effort-aware candidate fix removed it only for medium while retaining it for high. Please make chunk briefs effort-aware and add medium/high prompt assertions.
中文
[严重] medium effort 声明跳过 adversarial personas,但 Step 3B 的 effort-independent chunk brief 仍向每个 territory agent 分配 the adversarial reading。因此大型 medium review 仍会执行并支付契约声称删除的维度。定向 prompt probe 在 expect(medium).not.toContain('the adversarial reading') 处失败;effort-aware 的候选修复只在 medium 删除该职责,并在 high 保留。请让 chunk brief 感知 effort,并增加 medium/high prompt 断言。
— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)
Two conflicts, both where main's roster additions (#9805: Agents 1d/1e, the language-pitfall scan and wrapper/proxy routing) met this branch's (#9707 proposals 3 and 4: 6d and prose-exec). - roster.ts: both sides added roles inside the `effort !== 'medium'` block. Kept both, 6d beside its persona family and 1d/1e after it. - SKILL.md: the narration layer counts the roster the code computes, and both sides had renumbered it. Re-derived every count from the merged roster instead of taking a side: a same-repo PR review at high now rosters 17 agents (15 lightweight, 15 local, 11/9/10 at medium), 16 of them diff-reading, 15 lenses; 3B's non-chunk base cost is 5, which moves the fan-out crossover to ~4 400 lines. Verified by running requiredAgents over each shape rather than by arithmetic.
|
Released in v0.22.2. |






What this PR does
Splits the two checks folded into Agent 1a's line-by-line brief into dedicated Step 3A roles at high effort. Agent 1d (language-pitfall scan) carries the per-language footgun checklist as a pattern-matching walk over every hunk; Agent 1e (wrapper/proxy routing) carries the structural expectation that every type the diff adds or modifies which wraps another — a cache, proxy, decorator, adapter — routes every method through the wrapped instance (never back through a registry/session/global) and forwards everything its callers actually use. Agent 1a's brief loses the two corresponding clauses and keeps its walk. Agent 1e's rostering is conditional on a cheap capture-time signal (a path or added line matching the wrapper vocabulary, recorded in the plan as
wrapperSignal), and the gate fails safe: only an explicitfalsekeeps the check out, so a plan written by an older CLI still owes it. The roster, the prompt builder, and the coverage gate all derive from the same plan fields, so a run that skips either agent is named. SKILL.md and the user-facing code-review doc are updated to match (counts, role tables, skip lists, selectors).Why it's needed
Both checks are different attention modes from line-by-line scanning: one is a checklist pattern-match, the other a structural routing expectation, and folded into 1a's walk they were diluted by its rhythm — the same shape this skill already measured elsewhere (the quality split into 3a/3b/3c, the invariant split). The low-effort inline pass already separates exactly these two as angles C and D; the higher tiers never got the split. High effort already launches 14 agents, so one more always (1d) plus one conditional (1e) does not change the cost class — a diff with no wrapping type costs one agent that returns an empty-scope receipt.
Reviewer Test Plan
How to verify
cd packages/cli && npx vitest run src/commands/review(101 files, 4781 passed) andcd packages/core && npx vitest run src/skills/bundled/review/SKILL.test.ts(32 passed), plusnpm run build && npm run typecheck.Cached…,…Adapter,Proxy, …) withqwen review capture-local/plan-diff— the plan recordswrapperSignal: trueandagent-prompt --rosterincludes both new blocks; a plain diff recordsfalseand the roster drops 1e while keeping 1d; a plan captured with--effort mediumrosters neither; a plan with no field (version skew) fail-safes 1e in./reviewpipeline on this change itself at high effort — 15 agents including 1d and 1e reviewing their own implementation;check-coveragereported 5/5 chunks reviewed, 15/15 agents did work, exit 0.Evidence (Before & After)
N/A (no TUI changes — review-skill roster/prompt logic and docs).
Tested on
Environment (optional)
Bundled
node dist/cli.jsfor the roster/capture E2E; vitest for the suites.Risk & Scope
wrapperSignaland fail safe toward running 1e.Linked Issues
Closes #9788
中文说明
本 PR 做了什么
把折叠在 Agent 1a 逐行审查 brief 里的两项检查拆成 high 档 Step 3A 的独立角色。Agent 1d(语言陷阱扫描)携带各语言的经典陷阱清单,对每个 hunk 做模式匹配走查;Agent 1e(包装/代理路由)携带结构性预期:diff 新增或修改的任何包装类型(缓存、代理、装饰器、适配器)的每个方法都必须路由到被包装实例(而不是绕回 registry/session/全局),并且转发调用方实际使用的全部方法。Agent 1a 的 brief 移除对应两条子句,保留逐行走查本身。1e 的入 roster 是有条件的:捕获阶段计算一个廉价信号(路径或新增行命中包装类词汇,记入计划的
wrapperSignal),且门是 fail-safe 的——只有显式false才会把该检查移出 roster,旧版 CLI 写出的计划仍然欠这个检查。roster、prompt 构建器、覆盖门禁都从同一份计划字段推导,因此跳过任一角色的运行会被点名。SKILL.md 与面向用户的 code-review 文档同步更新(数量、角色表、跳过列表、选择器)。为什么需要
这两项检查与逐行扫描是两种不同的注意力模式:一个是清单式模式匹配,一个是结构性路由预期;折叠在 1a 的走查里会被其节奏冲淡——这正是本技能在别处已经实测过的形态(质量维度拆成 3a/3b/3c、不变量检查三分)。低档内联审查早已把这两项作为独立角度 C 和 D;高档一直没有拆。high 档本来就启动 14 个 agent,再多一个常驻(1d)加一个条件(1e)不改变成本量级——没有包装类型的 diff 只多花一个返回空范围回执的 agent。
审阅测试计划
如何验证
cd packages/cli && npx vitest run src/commands/review(101 个文件,4781 通过)与cd packages/core && npx vitest run src/skills/bundled/review/SKILL.test.ts(32 通过),另加npm run build && npm run typecheck。qwen review capture-local/plan-diff捕获一个触碰包装类词汇(Cached…、…Adapter、Proxy等)的 diff——计划记录wrapperSignal: true,agent-prompt --roster输出包含两个新角色的块;普通 diff 记录false,roster 去掉 1e 但保留 1d;--effort medium捕获的计划两者都不入 roster;没有该字段的计划(版本偏差)按 fail-safe 把 1e 加入 roster。/review流水线(high 档)——15 个 agent,包括 1d 和 1e 审查它们自己的实现;check-coverage报告 5/5 分块已审查、15/15 agent 有工作、退出码 0。证据(前后对比)
N/A(无 TUI 变化——审查技能的 roster/prompt 逻辑与文档)。
测试环境
运行环境(可选)
roster/捕获 E2E 用打包后的
node dist/cli.js;测试套件用 vitest。风险与范围
wrapperSignal,按 fail-safe 仍会运行 1e。关联 Issue
Closes #9788