docs: add legacy code audit (/audit) design doc - #8397
Conversation
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
@qwen-code /takeover |
|
🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。移除 |
|
Thanks for the PR! Template looks good ✓ — every required heading is present, with a full bilingual body. Problem: this is a design proposal, not a fix, so the usual reproduction bar doesn't apply. The need it addresses — pointing the Direction: aligned. This sits squarely in qwen-code's code-review tooling mission, and the design reuses the existing Size: not applicable — a single documentation file, no production or core code touched. Approach: the scope feels right. One file, no drive-by changes, and the central "new skill rather than a Risk: no elevated risk signals — a docs file matches none of the high-risk code paths. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ —— 所有必需标题齐全,正文中英双语完整。 问题:这是一份设计提案而非 fix,因此常规的复现门槛不适用。它要解决的需求——把 方向:对齐。这完全落在 qwen-code 的代码评审工具使命内,且设计复用现有 规模:不适用——单个文档文件,未触及任何生产或核心代码。 方案:范围合理。单文件、无顺手改动;核心的"新 skill 而非 风险:无升级风险信号——文档文件不匹配任何高风险代码路径。 进入代码审查 🔍 — Qwen Code · qwen3.8-max-preview Reviewed at |
Code reviewFor a design doc the review is about soundness and fidelity, so I checked the document's load-bearing references against the repo rather than reading it at face value. They hold up:
Two non-blocking notes, neither affecting the design itself:
No blockers. No sequence diagram or changed-files table — a single documentation file, neither would add signal. Test evidence (this PR's own CI)Docs-only change, so the platform matrix and integration/E2E lanes skip by design; the lanes that do run are green and there are no failures. The
No behavioural claim to settle here — this is a proposal document, so there is no sandboxed-lane ( 中文说明代码审查设计文档的审查重点在合理性与保真度,因此我对照仓库核实了文档的关键引用,而非照单全收。结果站得住:
两条非阻塞提醒,均不影响设计本身:
无阻塞项。不加时序图或文件清单表——单个文档文件,二者都无增量价值。 测试证据(本 PR 自身 CI)仅文档改动,平台矩阵与集成/E2E 环节按设计跳过;实际运行的环节全绿,无失败。 CI 结论表见上方机器可读区域(由 finalize 流程在 CI 落定后就地更新)。 此处无需 sandboxed 验证通道( — Qwen Code · qwen3.8-max-preview Reviewed at |
|
Confidence: 4/5 — a sound, evidence-backed design doc that clears the bar for Stepping back: this is what a design proposal ought to look like. It measured before it proposed — two A/B rounds with a pre-declared success criterion — then let the measurements shape the design (dedup as a first-class step, tiers cut by marginal yield rather than price, one undirected persona kept as a blind-spot hedge). It draws explicit non-goals, reuses the existing My own independent take on "audit existing code with the review machinery" lands in the same place — re-anchor the briefs, cluster by root cause, verify with runnable probes — and the doc goes further than that baseline, not less. I didn't find a simpler path it missed. The infrastructure it leans on is real (verified The two notes from the review are about evidence fidelity, not the design: the #6457 citation appears to point at the wrong PR, and the experiment records aren't committed (disclosed). Neither blocks merging a proposal document. To be clear about what an approval means here: it says this doc belongs in 中文说明置信度:4/5 —— 一份合理、证据充分的设计文档,达到 退一步看:这是一份设计提案应有的样子。先测量再提案——两轮 A/B、事先声明的判定标准——再让测量结果塑造设计(去重作为一等步骤、按边际收益而非价格分档、保留一个 undirected persona 作为盲点对冲)。非目标明确,复用现有 我自己对"用 review 机制审计存量代码"的独立判断与之殊途同归——重锚 brief、按根因聚类、以可运行 probe 验证——而文档比这个基线走得更远,而非更浅。我没有找到它遗漏的更简路径。它所依赖的基础设施是真实的(已对照代码树核实 审查中的两条提醒针对的是证据保真度,而非设计:#6457 引用似乎指错了 PR,实验档案未入库(已说明)。二者都不阻塞一份提案文档的合入。 需要说明此处"批准"的含义:它表示这份文档属于 — Qwen Code · qwen3.8-max-preview Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
中文说明
已审查——无阻断问题。 建议见行内评论。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| _everything_ is pre-existing, and the exclusion inverts. Two replacement | ||
| disciplines keep precision without an author to consult: |
There was a problem hiding this comment.
[Suggestion] The heading says "Two replacement disciplines" but three co-equal numbered items follow (the failure-scenario bar, severity-by-authority, and the documented-limitation rule). — Failure scenario: an implementer reading "Two" must guess whether item 3 is subordinate; if treated as secondary, the documented-limitation rule (which the doc says Round 2 agents split on) silently drops from the methodology.
| _everything_ is pre-existing, and the exclusion inverts. Two replacement | |
| disciplines keep precision without an author to consult: | |
| _everything_ is pre-existing, and the exclusion inverts. Three replacement | |
| disciplines keep precision without an author to consult: |
中文说明
标题写的是 "Two replacement disciplines"(两条替代性纪律),但后面跟着三条并列的编号项(failure-scenario 门槛、按权威定级、documented-limitation 规则)。— 失败场景:实现者看到 "Two" 时不得不猜测第 3 项是否是次级条目;若把它当作次要内容,文档自己说 Round 2 曾让两个 agent 产生分歧的 documented-limitation 规则就会从方法论中悄悄丢失。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| produced four single-source Criticals at the trust boundary (frontmatter | ||
| hooks bypassing folder trust, a workspace-writable HTTP-hook whitelist, | ||
| env-resolution paths defeating a prior secrets-stripping fix). Full |
There was a problem hiding this comment.
[Suggestion] "produced four single-source Criticals at the trust boundary" but the parenthetical names only three, with no "including"/"e.g." marker to signal a partial list. — Failure scenario: these Criticals are the cited evidence for the security agent's threat-model-first re-anchor (a default-tier roster decision); a reader checking the evidence finds a count (4) and a list (3) that do not reconcile and cannot tell whether the count is inflated or a fourth finding was dropped. Name the fourth, correct the count, or mark the list illustrative.
| produced four single-source Criticals at the trust boundary (frontmatter | |
| hooks bypassing folder trust, a workspace-writable HTTP-hook whitelist, | |
| env-resolution paths defeating a prior secrets-stripping fix). Full | |
| produced four single-source Criticals at the trust boundary (including | |
| frontmatter hooks bypassing folder trust, a workspace-writable HTTP-hook whitelist, | |
| env-resolution paths defeating a prior secrets-stripping fix). Full |
中文说明
"produced four single-source Criticals at the trust boundary"(在信任边界产出四个单源 Critical),但括号里只列了三个,且没有 "including"/"e.g." 之类标记表明是不完全列举。— 失败场景:这些 Critical 是 security agent 采用 threat-model-first 锚点(默认档 roster 决策)所引用的证据;读者核对证据时会发现数量(4)与列表(3)对不上,无法判断是数量夸大了还是漏掉了第四个。建议:列出第四个、更正数量,或明确标注为示例性列举。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| on severity more than once (the naive arm's two grading inversions). | ||
| Humans file; the audit informs. |
There was a problem hiding this comment.
[Suggestion] The "Auto-filing issues" rejection cites "the naive arm's two grading inversions", but the document describes only one naive-arm grading inversion (the most-severe finding filed as a Suggestion). — Failure scenario: a reader confirming the cited evidence finds one inversion with no partial-list marker, so "more than once" / "two" is unsupported within the document's own four corners — the same "claims N, names fewer" defect as the "four Criticals" finding above. Describe the second inversion or correct the count.
中文说明
"Auto-filing issues"(自动建 issue)这一被否决方案引用了 "the naive arm's two grading inversions"(朴素方的两次定级颠倒),但文档只描述了一次朴素方定级颠倒(最严重的发现被报成 Suggestion)。— 失败场景:读者去核对所引证据时只找到一次颠倒、且无不完全列举标记,因此 "more than once"/"two" 在文档自身范围内缺乏支撑——与上面 "四个 Critical" 那条同属 "声称 N 个、只列出更少" 的缺陷。建议描述第二次颠倒,或更正数量。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| env-resolution paths defeating a prior secrets-stripping fix). Full | ||
| record: `.qwen/investigations/legacy-review-ab-2/REPORT.md`. |
There was a problem hiding this comment.
[Suggestion] The design's empirical justification rests on two A/B experiments cited at .qwen/investigations/legacy-review-ab*/ paths that are git-ignored (.gitignore ignores .qwen/*) and absent from the repository, so the committed document does not stand alone. — Failure scenario: a maintainer revisiting any by-measurement decision (why 1c is mandatory, why the gate sits at 5-8k, the 17-vs-2 / 0-FP / 60% / 7x claims) follows "Full record: ..." and finds empty paths; the claims become unverifiable folklore once the author's untracked working directory is gone. Commit the experiment records (or their summary data tables) into docs/ and re-point the citations, or inline enough per-agent findings/cost tables that the claims are checkable from version control alone.
中文说明
本设计的实证依据建立在两轮 A/B 实验上,而其记录被引用在 .qwen/investigations/legacy-review-ab*/ 路径——这些路径被 git 忽略(.gitignore 忽略 .qwen/*)且不在仓库中,因此提交后的文档无法独立成立。— 失败场景:维护者日后复查任何 "靠测量得出" 的决策(为何 1c 必选、为何门限定在 5-8k、17-vs-2 / 0 误报 / 60% / 7x 等结论)时,顺着 "Full record: ..." 只会找到空路径;一旦作者未纳入版本控制的工作目录消失,这些结论就成了无法验证的传闻。建议把实验记录(至少是汇总数据表)提交到 docs/ 并重新指向,或内联足够的逐 agent 发现/成本表,使结论仅凭版本控制即可核对。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - marks heavy files (large, mostly-rewritten equivalents: big stateful | ||
| classes) for the invariant-checklist triple, which the experiment | ||
| confirmed transfers unchanged. |
There was a problem hiding this comment.
[Suggestion] This claims the invariant-checklist triple "which the experiment confirmed transfers unchanged", but neither experimental arm ran it (the fan-out is enumerated as exactly 1a, 1c, 2, 3a/3b/3c, 4, 5) and no effort tier runs it — at the default tier the heavy-file marking has no consumer. — Failure scenario: an implementer either ships the triple on the strength of a validation the doc's own numbers rule out, or cannot tell which tier runs it. In /review the checklist is diff-derived and a legacy audit has no diff, so "unchanged" transfer is exactly the claim requiring proof. Replace with an honest status (untested; transfers by analogy, flagged as extrapolation) and either add invariant a/b/c to a tier or drop the heavy-file marking step.
中文说明
这里声称 invariant-checklist 三元组 "which the experiment confirmed transfers unchanged"(实验已确认其原样迁移),但两轮实验的任何一臂都没有运行过它(fan-out 被明确列举为 1a、1c、2、3a/3b/3c、4、5),也没有任何 effort 档运行它——在默认档下,heavy-file 标记没有任何消费者。— 失败场景:实现者要么凭借一个被文档自身数据否定的验证就上线该三元组,要么无法判断到底哪一档会运行它。在 /review 中该清单依赖 diff,而存量审计没有 diff,因此 "原样迁移" 恰恰是需要证明的论断。建议改为诚实的状态说明(未测试、凭类比迁移、标记为外推),并把 invariant a/b/c 加入某个档,或从 plan-files 中去掉 heavy-file 标记步骤。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| **inter-agent disagreements are settled by execution, never by | ||
| adjudicator judgment** — Round 2 had two (a whitelist-bypass claim one | ||
| agent filed and another explicitly cleared; a severity split) and only a | ||
| probe resolved the first. The verify brief must name this case. |
There was a problem hiding this comment.
[Suggestion] The absolute rule "inter-agent disagreements are settled by execution, never by adjudicator judgment" is contradicted by the document's own evidence: the Round 2 severity split was not probe-resolved ("only a probe resolved the first"), and the severity heuristics (disciplines 2/3) resolve such splits by judgment rules. — Failure scenario: a verify brief implementing the rule literally encounters two agents splitting Critical vs Suggestion on the same confirmed behavior; no probe can output a severity class, so the verifier deadlocks or silently falls back to adjudicator judgment, violating the stated rule. Scope the rule to factual disagreements and state that severity splits are settled by the authority-on-the-failure-path heuristic.
中文说明
这条绝对规则 "inter-agent disagreements are settled by execution, never by adjudicator judgment"(agent 间分歧一律由执行裁决,绝不靠裁决者判断)被文档自身的证据反驳:Round 2 的严重度分歧并未由 probe 解决("only a probe resolved the first"),而严重度启发式(纪律 2/3)恰恰是靠判断规则来解决这类分歧的。— 失败场景:按该规则字面实现的 verify brief 会遇到两个 agent 对同一已确认行为一个报 Critical、一个报 Suggestion;没有任何 probe 能输出严重度类别,于是验证者要么死锁、要么悄悄退回裁决者判断,从而违反所声明的规则。建议把规则限定于事实性分歧,并说明严重度分歧由 "失败路径上的权威" 启发式来解决。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| findings clustered by theme/root cause, each with severity, locations, | ||
| failure scenario, and the evidence tier (end-to-end probe / unit probe / | ||
| code read). |
There was a problem hiding this comment.
[Suggestion] The Output artifact schema ("severity, locations, failure scenario, and the evidence tier") omits the "found independently by N agents" field that the Dedup section mandates and ties to severity ("Round 2's most-confirmed findings ... 3-4 independent discoveries each were also its most severe"). — Failure scenario: an implementer building the report schema from the Output section produces entries lacking the N-agents count, so a reader cannot distinguish a 4-agent-confirmed finding from a single-agent one — silently dropping the severity-correlated signal the design says to surface.
| findings clustered by theme/root cause, each with severity, locations, | |
| failure scenario, and the evidence tier (end-to-end probe / unit probe / | |
| code read). | |
| findings clustered by theme/root cause, each with severity, locations, | |
| failure scenario, evidence tier (end-to-end probe / unit probe / | |
| code read), and the independent-discovery count ("found independently by N agents"). |
中文说明
Output 一节的产物字段表("severity, locations, failure scenario, and the evidence tier")漏掉了 Dedup 一节所要求、且与严重度挂钩的 "found independently by N agents" 字段("Round 2's most-confirmed findings ... 3-4 independent discoveries each were also its most severe")。— 失败场景:实现者若按 Output 一节构建报告字段,产出的条目会缺少 N-agents 计数,读者就无法区分一个经 4 个 agent 确认的发现与仅 1 个 agent 确认的发现——悄悄丢掉了设计要求呈现的、与严重度相关的信号。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - **medium** (default) — the replicated roster: 1a, 1c, 2, 3a/3b/3c, 4, | ||
| 5, **6a** + verification. Rounds 1-2 measured the 8-dimension core; | ||
| 6a is the single-agent blind-spot hedge justified above. |
There was a problem hiding this comment.
[Suggestion] The default tier is labeled "the replicated roster" but the list includes 6a, which the very next sentence admits was never replicated ("Rounds 1-2 measured the 8-dimension core; 6a is the single-agent blind-spot hedge"). The roster table marks 6b/6c as "untested" but pointedly does not mark 6a. — Failure scenario: a reader scanning the Effort tiers carries away that the default 9-agent configuration is fully experiment-backed, when only the 8-core was ever run and 6a rests solely on a qualitative near-miss argument; the label contradicts the sentence beneath it. Relabel to separate the measured core from the hedge (e.g. "the replicated 8-dimension core, plus the 6a blind-spot hedge").
中文说明
默认档被标为 "the replicated roster"(已复现的 roster),但列表里包含 6a,而紧接着一句就承认 6a 从未被复现过("Rounds 1-2 measured the 8-dimension core; 6a is the single-agent blind-spot hedge")。roster 表格把 6b/6c 标为 "untested",却刻意没有这样标 6a。— 失败场景:读者浏览 Effort 分档时,会以为默认 9-agent 配置完全有实验支撑,而实际上只运行过 8 维核心,6a 仅凭一个定性的 "差点漏掉" 论证;标签与其下一句自相矛盾。建议重新措辞,把已测量的核心与对冲席位分开(例如 "the replicated 8-dimension core, plus the 6a blind-spot hedge")。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Review feedback addressedAll 8 suggestions from the automated reviewer (round 1) were implemented. Each was a documentation-accuracy fix in
No conflict resolution needed ( Verification
中文说明已处理的审查反馈自动审查器(第 1 轮)的全部 8 条建议均已实现。每条都是
无需冲突解决( 验证
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.
中文说明
已审查——无阻断问题。 建议见行内评论。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - **medium** (default) — the replicated 8-dimension core plus the 6a | ||
| blind-spot hedge: 1a, 1c, 2, 3a/3b/3c, 4, 5, **6a** + verification. |
There was a problem hiding this comment.
[Suggestion] The invariant-checklist agents (a/b/c) appear in the roster table (invariant a/b/c | heavy files only | unchanged) and the planning step "marks heavy files … for the invariant-checklist triple", but no effort tier includes them — medium enumerates 1a, 1c, 2, 3a/3b/3c, 4, 5, 6a and high adds only 6b/6c + iterative reverse audit. The heavy-file marking is produced but never consumed. — Failure scenario: an implementer following the tier specs as a build checklist implements the heavy-file marking in plan-files but never wires it to agent execution (dead infrastructure — the doc itself names "session-commit dead infrastructure" as a finding class the experiments detected); alternatively they add invariant a/b/c at every tier including the cheap low tier, wasting tokens.
| - **medium** (default) — the replicated 8-dimension core plus the 6a | |
| blind-spot hedge: 1a, 1c, 2, 3a/3b/3c, 4, 5, **6a** + verification. | |
| - **medium** (default) — the replicated 8-dimension core plus the 6a | |
| blind-spot hedge: 1a, 1c, 2, 3a/3b/3c, 4, 5, **6a**, plus invariant a/b/c | |
| on files `plan-files` marks as heavy + verification. |
中文说明
不变量检查清单 agent(a/b/c)出现在 roster 表(invariant a/b/c | heavy files only | unchanged)中,规划步骤也会 "marks heavy files … for the invariant-checklist triple",但没有任何 effort 档位包含它们——medium 枚举为 1a, 1c, 2, 3a/3b/3c, 4, 5, 6a,high 仅追加 6b/6c + iterative reverse audit。heavy-file 标记被生产出来却无档位消费。— 失败场景:实现者把各档规格当作构建清单,会在 plan-files 中实现 heavy-file 标记,却从不把它接到 agent 执行上(死基础设施——文档本身就把 "session-commit dead infrastructure" 列为实验发现的一类缺陷);或者在包括廉价 low 档在内的每一档都加入 invariant a/b/c,浪费 token。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| **Event-coverage walk for event-driven modules (1c, conditional).** When | ||
| the module is an event/lifecycle system, 1c's brief adds: enumerate the |
There was a problem hiding this comment.
[Suggestion] The event-coverage walk is conditional ("When the module is an event/lifecycle system, 1c's brief adds …") but no step evaluates that condition. plan-files names evaluation steps for the topology gate and heavy-file marking, but not event-system detection, so this conditional floats unassigned — unlike every other conditional in the design. — Failure scenario: if an implementer omits detection, the walk never fires and the pipeline drops the exact finding class (two unique Round-2 Criticals) that motivated it; if always activated, 1c (already 16M tokens / ~35% of the arm) burns that budget on non-event modules for zero yield. Suggested fix: add event-system detection to the plan-files bullets — e.g. "detects event/lifecycle modules by emit/dispatch/subscribe call patterns and flags them for the 1c event-coverage brief" — or state that the orchestrator confirms module type before fan-out.
中文说明
事件覆盖遍历是有条件的("When the module is an event/lifecycle system, 1c's brief adds …"),但没有任何步骤负责判定该条件。plan-files 为拓扑门控和 heavy-file 标记都命名了评估步骤,唯独没有事件系统检测,于是这个条件悬空无主——与设计中的其他条件不同。— 失败场景:若实现者省略检测,该遍历永不触发,流水线就会丢掉恰恰是它存在理由的那类发现(第二轮两个独有的 Critical);若始终激活,1c(已 16M token、约占该臂 35%)会在非事件模块上白白烧掉这笔预算。建议修复:在 plan-files 的条目中加入事件系统检测——例如 "通过 emit/dispatch/subscribe 调用模式识别事件/生命周期模块,并为其标记 1c 事件覆盖 brief"——或声明由编排器在 fan-out 前确认模块类型。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| Step 3B — with whole-module agents retained for the walks that are | ||
| meaningless per-chunk (1c cross-file, 3a reuse, 5 test-coverage); |
There was a problem hiding this comment.
[Suggestion] The above-gate execution path defines only per-chunk "dimension briefs" and a closed retained whole-module list (1c cross-file, 3a reuse, 5 test-coverage). The personas (6a/6b/6c) fit neither — they are undirected, not dimension briefs, and are not in the retained list — yet the medium tier explicitly includes 6a and high adds 6b/6c. The design never says how personas deploy above the gate. — Failure scenario: /audit --effort medium on an above-gate module (e.g. the 8,516-line hooks module) tiles into ~21 chunks; the pipeline either silently drops 6a (losing the blind-spot hedge the design justifies with the Round-2 near-miss) or instantiates it per-chunk (21 undirected agents, contradicting "one agent, not three").
| Step 3B — with whole-module agents retained for the walks that are | |
| meaningless per-chunk (1c cross-file, 3a reuse, 5 test-coverage); | |
| Step 3B — with whole-module agents retained for the walks that are | |
| meaningless per-chunk (1c cross-file, 3a reuse, 5 test-coverage, and any | |
| personas the tier includes — these are whole-module by construction); |
中文说明
超过门控的执行路径只定义了两类:逐 chunk 的 "dimension briefs",以及一个闭合的整模块保留清单 (1c cross-file, 3a reuse, 5 test-coverage)。persona(6a/6b/6c)两者都不属于——它们是 undirected,不是 dimension brief,也不在保留清单里——但 medium 档明确包含 6a,high 档追加 6b/6c。设计从未说明 persona 在超门控时如何部署。— 失败场景:对超门控模块(如 8,516 行的 hooks 模块)运行 /audit --effort medium 会切成约 21 个 chunk;流水线要么悄悄丢掉 6a(失去设计用第二轮 near-miss 论证的盲点防御),要么逐 chunk 实例化(21 个 undirected agent,与 "one agent, not three" 矛盾)。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
|
🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下: Round summaryAddressed all three automated-reviewer suggestions. Each identified a real internal inconsistency in the design doc where a concept was introduced but never wired into the pipeline spec that an implementer would follow. Feedback points
Files changed
Verification
No Vitest or integration tests needed (docs-only change, no TypeScript modified). No settings source changed. 中文说明本轮总结处理了自动审查器提出的全部三条建议。每条都指出了设计文档中一个真实的内部不一致:某个概念被引入,但从未接入实现者将要遵循的流水线规格。 反馈要点
变更文件
验证
无需运行 Vitest 或集成测试(仅文档变更,未修改 TypeScript)。未变更设置源。 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/模型 |
| Rounds 1-2 measured the 8-dimension core; 6a rests on the near-miss | ||
| argument above, not on experiment. | ||
| - **high** — medium + the other two personas (6b/6c) + iterative reverse | ||
| audit with the two-consecutive-dry-rounds stop rule. Unmeasured; |
There was a problem hiding this comment.
[Critical] The high tier cites only one clause of /review Step 5's coupled reverse-audit block — "the two-consecutive-dry-rounds stop rule" — and drops the rest of that step's semantics, leaving two gaps. (1) Termination: in Step 5 the two-dry-rounds rule is paired with a whiff≠dry definition (a round containing a twice-whiffed auditor is not dry, so the loop continues) and a 5-round hard cap that bounds it. Naming only the two-dry-rounds clause means: read naively (zero findings = dry), two whiffed rounds end the audit on silence; read with whiff≠dry but no cap, persistent whiffs mean no round is ever dry and the loop never terminates. (2) Findings lifecycle: Step 5 also routes reverse-audit findings through Step 4 verification and merges each round's findings into the cumulative list before the next round (auditors receive the confirmed-only baseline). The Dedup-and-verification section describes a single pass over fan-out findings only, so round findings have no defined verification/dedup and the next round's baseline is unspecified. — Failure scenario: on a large module (where the design itself warns reverse auditors are most context-starved) the high-tier loop either never completes or stops on silence; a round-2 Critical is never verified or clustered, and the dry-round baseline is undefined. Suggested fix: state the full Step 5 semantics — the substantive-return (whiff) check, the evidence-bearing dry definition, two consecutive dry rounds, the 5-round hard cap, reverse-audit findings routed through the same dedup + verification as fan-out findings, each subsequent round receiving the cumulative confirmed list — and disclose outstanding twice-whiffed scopes in the report header, since /audit has no verdict to cap.
中文说明
[Critical] high 档只引用了 /review Step 5 相互耦合的反向审计规则中的一条——"连续两轮 dry 即停止"——丢掉了该步骤的其余语义,留下两处缺口。(1)终止条件: Step 5 中"连续两轮 dry"与 whiff≠dry 定义(含两次 whiff 的审计员所在轮次不算 dry、循环继续)以及兜底的 5 轮硬上限成对出现。只点名这一条意味着:按朴素理解(零发现=dry),两次 whiff 轮会让审计在沉默中结束;若采用 whiff≠dry 却无硬上限,持续 whiff 会使任何一轮都不算 dry、循环永不终止。(2)发现的生命周期: Step 5 还要求反向审计发现走 Step 4 验证,并在下一轮开始前并入累计列表(审计员接收"已确认"基线)。而 Dedup-and-verification 一节只描述了对 fan-out 发现的一次性处理,各轮反向审计发现没有定义验证/去重,下一轮基线也未指明。——失败场景:在大型模块上(设计自己也警告反向审计员在此最缺上下文),high 档循环要么永不结束、要么在沉默中停止;第二轮的 Critical 得不到验证与聚类,dry 轮判定的基线无定义。建议修复:完整写明 Step 5 语义——实质性返回(whiff)检查、带证据的 dry 定义、连续两轮 dry、5 轮硬上限、反向审计发现与 fan-out 发现走同一套去重+验证、每轮接收累计的已确认列表——并在报告头部披露两次 whiff 未完成的范围(/audit 没有可被封顶的 verdict)。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| clustering step over the findings file, with each cluster keeping the | ||
| strongest evidence (an end-to-end probe beats a unit probe beats a |
There was a problem hiding this comment.
[Suggestion] Dedup keeps each cluster's "strongest evidence" but specifies no severity rule, so a cluster can enter verification carrying a lower severity than a member dedup discarded — the exact downgrade /review Step 4 forbids ("never let deduplication downgrade severity"). The dedup paragraph borrows the two adjacent retention rules from Step 4 (keep the most detailed → "strongest evidence"; note which agents → "found independently by N agents") but drops the max-severity rule that sits between them. It also makes the severity-split adjudication unreachable: a severity split is by definition one root cause graded differently by different agents, so root-cause clustering merges both copies before verification, and the "severity splits are settled by the authority-on-the-failure-path heuristic" rule has no input to fire on. — Failure scenario: agent A probes a benign path and files a root cause as a Suggestion with unit-probe evidence; agent B files the same root cause Critical from a code read of the harm path. The stated hierarchy ranks any unit probe above any code read, so dedup keeps A's copy, discards B's Critical, and verification rules on A's milder scenario — a Critical-class defect is reported as a Suggestion. (The doc's own record contains this twice: Round 1's most severe finding filed as a Suggestion by the naive arm, and Round 2's explicit severity split.) Suggested fix: add Step 4's rule to the dedup paragraph — cluster severity is the highest severity any member carried; carry member severities/scenarios onto the cluster so verification's split rule has something to rule on.
中文说明
[Suggestion] 去重只为每个簇保留"最强证据",却没有给出定级规则,因此簇进入验证时可能携带比被丢弃成员更低的严重度——正是 /review Step 4 明令禁止的降级("绝不让去重降低严重度")。去重段落借用了 Step 4 中相邻的两条保留规则(保留最详尽→"最强证据";标注哪些 agent→"被 N 个 agent 独立发现"),却丢掉了夹在其间的"取最高严重度"规则。这也使严重度分歧的裁决无法触发:严重度分歧本就指同一根因被不同 agent 定了不同级,按根因聚类会在验证之前把两份合并,于是"严重度分歧由失败路径上的权威启发式裁决"这条规则失去了可作用的输入。——失败场景:agent A 探测了一条良性路径、以单元 probe 证据把某根因报为 Suggestion;agent B 基于对危害路径的代码阅读把同一根因报为 Critical。按文中证据层级,任何单元 probe 都高于代码阅读,于是去重保留 A、丢弃 B 的 Critical,验证只裁决 A 较轻的场景——一个 Critical 级缺陷被报成 Suggestion。(文档自身记录里已出现两次:Round 1 最严重发现被朴素臂报成 Suggestion,Round 2 有明确的严重度分歧。)建议修复:在去重段落补上 Step 4 的规则——簇的严重度取任一成员携带的最高严重度;把各成员的严重度/场景保留在簇上,使验证的分歧裁决规则有输入可用。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| siblings of a historical fix that had covered only one UI path. **It | ||
| also made 1c the single most expensive agent of either round (16M | ||
| tokens, ~35% of the arm)** — repo-wide path enumeration scales with the | ||
| module's fan-out, so the brief needs a budget rule: deep-read at most N |
There was a problem hiding this comment.
[Suggestion] The 1c budget rule ("deep-read at most N call sites per event and register the rest by name") caps exactly the analysis that is the event-coverage walk's unique value. A fire-miss is only visible by reading a caller's internal early-return/error/abort paths — which is literally how the walk is defined above ("including early-return, error, and abort paths in the callers"). Name-only registration records that a caller exists; it cannot show its error path never fires. And the rule activates precisely when fan-out is high, i.e. exactly when some callers sit outside the N quota. Round 2's two unique-in-the-field Criticals were both fire-misses on error/abort paths — the class this rule now risks missing. — Failure scenario: an event with more than N call sites; the missing-fire defect lives in an error/abort path of a caller beyond the quota; it is name-registered and the walk passes it. This also sits in tension with the doc's own principle "effort tiers must cut by expected marginal yield, not by price" — the measured marginal yield of this walk is exactly the error/abort-path class. Suggested fix: direct the N deep-read slots at callers' early-return/error/abort paths first (happy-path callers are the cheap ones to register by name), and state the residual coverage trade-off so a budgeted run can disclose it.
中文说明
[Suggestion] 1c 的预算规则("每个事件最多深读 N 个调用点,其余只按名字登记")恰恰砍掉了事件覆盖扫描的独特价值所在。漏触发(fire-miss)只有去读调用方内部的早退/错误/中止路径才能发现——这正是上文对该扫描的定义("包括调用方里的早退、错误、中止路径")。只登记名字只能记录调用方存在,无法证明其错误路径从不触发;而该规则恰好在 fan-out 高(也就是必有调用方落在 N 配额外)时生效。Round 2 两个全场唯一 Critical 都是错误/中止路径上的漏触发——正是这条规则如今可能漏掉的类别。——失败场景:某事件调用点超过 N 个,漏触发缺陷位于配额外某调用方的错误/中止路径,被仅登记名字,扫描放行。这也与文档自身原则"按预期边际收益而非价格裁剪"相悖——该扫描被测出的边际收益恰是错误/中止路径这类。建议修复:把 N 个深读名额优先投向调用方的早退/错误/中止路径(幸福路径调用方最便于只登记名字),并写明残余覆盖取舍,以便预算化运行时如实披露。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| meaningless per-chunk (1c cross-file, 3a reuse, 5 test-coverage, and | ||
| any personas the tier includes — these are whole-module by | ||
| construction); | ||
| - marks heavy files (large, mostly-rewritten equivalents: big stateful |
There was a problem hiding this comment.
[Suggestion] plan-files is given no implementable heavy-file predicate, and the medium tier's invariant triple depends on it. The only heaviness machinery in the reused TypeScript layer is classifyHeavy (packages/cli/src/commands/review/lib/heavy.ts), which is defined purely in diff metrics — preLines >= 300 AND (rewriteRatio >= 0.4 OR changedLines >= 800). An audit target is merged, unchanged code, so changedLines = 0, ratio 0, and classifyHeavy marks nothing heavy — if lifted as-is, the invariant triple silently never runs in any audit. If instead "big stateful classes" is a fresh rule, the doc supplies neither a threshold nor a detection signal, and the Verification plan unit-tests plan-files tiling/classification/topology but not heaviness. Related: the medium tier runs the triple unconditionally, but in /review the invariant agents are gated to the territory/topology fan-out (roster.ts: below the gate every dimension agent already reads every file whole, so the triple adds agents but no new view) — the audit's below-gate topology is exactly that case. Suggested fix: specify the legacy heavy predicate concretely (e.g. source files ≥ N lines plus the structural signal standing in for "mostly-rewritten"), note that classifyHeavy's diff metrics do not transfer, add heaviness to the plan-files unit-test list, and state the triple's topology condition.
中文说明
[Suggestion] plan-files 没有得到可实现的"重文件"判定条件,而 medium 档的不变式三连(invariant triple)依赖它。复用的 TypeScript 层里唯一的重文件机制是 classifyHeavy(lib/heavy.ts),它完全由 diff 指标定义——preLines >= 300 且(rewriteRatio >= 0.4 或 changedLines >= 800)。审计对象是已合入、未改动的代码,changedLines = 0、比值为 0,classifyHeavy 永远不会标记任何文件为重文件——若原样搬用,不变式三连在任何审计中都静默不运行。若改用"大型有状态类"这一新规则,文档既未给阈值也未给检测信号,且 Verification 计划只对 plan-files 的分块/分类/拓扑门做单测、不含重文件判定。相关问题:medium 档无条件运行三连,但在 /review 中不变式 agent 被门控在领地/拓扑 fan-out 下(roster.ts:低于门限时每个维度 agent 本就整文件通读,三连只增 agent 不增视角)——审计的低门槛拓扑恰是这种情形。建议修复:给出具体的存量重文件判定(如源文件 ≥ N 行加代替"大比例重写"的结构信号),说明 classifyHeavy 的 diff 指标不可迁移,把重文件判定加入 plan-files 单测清单,并写明三连的拓扑条件。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
|
|
||
| What is reused is the **TypeScript layer**, which is mostly | ||
| target-agnostic: `agent-prompt` roster/brief printing, the findings schema, | ||
| `check-coverage` transcript verification, budget/ledger machinery, and the |
There was a problem hiding this comment.
[Suggestion] The reuse list names "budget/ledger machinery", but the ledger does not lift unchanged. packages/cli/src/commands/review/lib/ledger.ts is the cross-round findings ledger carried IN a posted PR review body (an HTML comment serialized into the review, parsed back by the next round's pr-context). This design removes every anchor the ledger needs: "no PR, no comments, no auto-filed issues in v1", "No verdict … the run ends at the report", and the only feature where a cross-round ledger would have a role — incremental re-audit — is "plausible, unmeasured, not v1". (Budget is genuinely reusable — budget.ts is a plan-derived size→work mapping and plan-files produces the line counts — so this is about "ledger" specifically.) — Failure scenario: an implementer scoping the reuse finds the ledger has nothing to anchor to, so the reuse section overstates what transfers. Suggested fix: drop "ledger" from the v1 reuse list, or reframe it as the model for the deferred incremental re-audit mechanism rather than a v1 reuse.
中文说明
[Suggestion] 复用清单写了"budget/ledger machinery",但 ledger 并不能原样搬用。lib/ledger.ts 是承载于"已张贴的 PR 评审正文"中的跨轮发现台账(序列化为评审里的 HTML 注释、由下一轮的 pr-context 解析回来)。而本设计移除了台账所需的每一个锚点:"no PR, no comments, no auto-filed issues in v1"、"No verdict … the run ends at the report",以及唯一能让跨轮台账发挥作用的增量复审(incremental re-audit)也被标为"plausible, unmeasured, not v1"。(budget 是真正可复用的——budget.ts 是由 plan 推导的规模→工作量映射,plan-files 会产出行数——因此这里单指"ledger"。)——失败场景:实施者评估复用范围时会发现台账无处挂靠,复用一节夸大了可直接搬用的部分。建议修复:从 v1 复用清单中去掉"ledger",或把它改写为延后的增量复审机制的参照,而非 v1 复用项。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| exclusions: no `*.test.*` as _subjects_ — tests are evidence and the | ||
| test-coverage agent's subject), classifies them (source / docs / | ||
| generated) with the same rules `plan-diff` uses; | ||
| - counts source lines and applies the topology gate: below it, dimension |
There was a problem hiding this comment.
[Suggestion] Two under-specifications at the topology gate. (1) The above-gate tiling branch (per-chunk agents, only 1c/3a/5/personas whole-module) was never exercised — both experiments ran the whole-file (below-gate) topology — yet unlike the invariant triple, 6a, and the high tier, it carries no "untested / extrapolation" flag, so a reader infers it is evidence-backed. (2) The gate's only numeric guidance ("good to roughly 5–8k lines") caps at or below the document's own largest validated module — Round 2's hooks module is 8,516 lines and ran whole-file — and the gate value is never pinned. An implementer who pins the gate inside the stated range (e.g. 8,000) routes an 8.5k-line module — the size class the replication just proved works whole-file — into the unexercised tiling branch, discarding the design's one piece of size evidence above ~7.6k. — Failure scenario: the first module audited above the chosen threshold silently receives an unvalidated topology, and the doc's own validated-max evidence is discarded by its routing rule. Suggested fix: flag the above-gate branch as untested extrapolation (as the invariant triple and high tier are), and pin the gate at/above the validated max (e.g. ~9k) or correct the parenthetical to what was actually measured (7.6k and 8.5k both worked whole-file).
中文说明
[Suggestion] 拓扑门限处有两处欠规范。(1)门限之上的分块分支(按 chunk 的 agent,仅 1c/3a/5/personas 保留整模块)从未被演练——两轮实验都跑的是整文件(门限以下)拓扑——但它不像不变式三连、6a、high 档那样带"untested / extrapolation"标记,读者会以为它有证据支撑。(2)门限唯一的数值指引("good to roughly 5–8k lines")上限不高于文档自身验证过的最大模块——Round 2 的 hooks 模块 8,516 行且跑的是整文件——而门限值从未被钉死。实施者若在该区间内取值(如 8,000),就会把一个 8.5k 行模块(正是复制轮刚证明整文件可行的规模)路由进未演练的分块分支,丢掉设计中唯一一条 ~7.6k 以上的规模证据。——失败场景:首个超过所选阈值被审计的模块会静默套用未验证的拓扑,且设计自身"已验证最大规模"的证据被自己的路由规则丢弃。建议修复:给门限之上的分支加"未验证/外推"标记(如同三连与 high 档),并把门限钉在不低于已验证最大值(如 ~9k),或把括注改为实际测得的情况(7.6k 与 8.5k 整文件都可行)。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
|
|
||
| ### Output | ||
|
|
||
| - **The artifact:** a markdown report at `.qwen/audit/<path-slug>-<ts>.md`, |
There was a problem hiding this comment.
[Suggestion] The artifact spec enumerates what a report contains (severity, locations, failure scenario, evidence tier, discovery count) but omits the run/verification metadata a reader needs to trust it — four fields, each with its own failure: (1) walk completion — no record of which planned walks/agents actually completed, so a partially failed run (1c budget-exhausted, security agent errored — the walks the doc's own cost analysis says run closest to limits) is indistinguishable from a full one, and "0 security findings" reads as "safe"; /review solves this with unreviewedDimensions/"Not reviewed". (2) provenance — no commit SHA or dirty/clean state of the audited live checkout, so after fixes a "re-audit" cannot be aligned with the first run (file:line anchors drift with HEAD; "fixed" is indistinguishable from "new finding that predates the fix"); the <ts> records when, not which tree. (3) tier / verification status — nothing marks that a low-tier run's findings are unverified, so they print identically to a medium run's verified findings. (4) per-finding confidence — "verification keeps the /review shape", which ends in confirmed-high/confirmed-low, and the reused findings schema has a required confidence field, yet the artifact records none and never says where confirmed-low findings go (/review renders them terminal-only). Suggested fix: add a run-metadata header (audited commit + dirty flag, effort tier, walks completed/skipped with reason) and a per-finding confidence mark stating how confirmed-low findings are carried.
中文说明
[Suggestion] 产物(artifact)规格列出了报告包含什么(severity、locations、failure scenario、evidence tier、discovery count),却漏掉了读者据以信任该报告所需的运行/验证元数据——四个字段,各有其失败场景:(1)扫描完成度——没有记录计划中的哪些扫描/agent 实际完成,部分失败的运行(1c 预算耗尽、安全 agent 出错——正是文档自身成本分析指出最易触限的扫描)与完整运行无法区分,"0 条安全发现"会被读成"安全";/review 用 unreviewedDimensions/"Not reviewed" 解决了这一点。(2)溯源——未记录被审计的活检出(live checkout)的 commit SHA 或脏/净状态,修复后"复审"无法与首次运行对齐(file:line 锚随 HEAD 漂移,"已修复"与"修复前就存在的新发现"无法区分);<ts> 只记录时间,不记录是哪棵树。(3)档位/验证状态——没有任何标记说明 low 档的发现未经验证,其呈现与 medium 档已验证的发现完全相同。(4)逐条发现的 confidence——"verification keeps the /review shape",而该形状以 confirmed-high/confirmed-low 收尾,复用的 findings schema 也有必填的 confidence 字段,但产物不记录任何 confidence,也未说明 confirmed-low 发现去哪里(/review 把它们只放在终端、不张贴)。建议修复:加一个运行元数据头(被审计的 commit + 脏标记、effort 档位、完成/跳过的扫描及原因),并为每条发现加 confidence 标记、写明 confirmed-low 发现如何呈现。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
|
|
||
| ### Effort tiers | ||
|
|
||
| - **low** — inline read by the orchestrator itself, angle rotation as in |
There was a problem hiding this comment.
[Suggestion] Two issues in the low tier. (1) It was measured in neither experiment (both rounds ran exactly two arms — naive single-agent and 8-agent fan-out), yet unlike every other unmeasured component (6a, the invariant triple, the high tier — all flagged "untested"/"extrapolation") it carries no such flag, while sharing the single-reader, no-fan-out, no-verification shape the doc uses to exclude the naive pass from being a tier ("offering it would launder an inferior audit under the same command name"). The doc's own measurement puts the single-reader shape ~7× behind fan-out on recall. (2) It reuses /review's angle rotation wholesale, but /review's always-walked angle B ("every line the diff deletes or replaces") has no subject in a legacy audit — merged code has no deletions, the exact absence the doc uses to drop agent 1b — so one of the three guaranteed angle slots is spent on a vacuous walk. — Failure scenario: a user runs /audit --effort low trusting the tier gradient; the single inline reader (the shape measured ~1/7 fan-out recall) yields a near-empty report that reads as "this module is not worth a real audit" — the laundering the naive-exclusion paragraph invokes, applied to a tier the same standard was waived for. Suggested fix: flag low as unmeasured like its siblings and state why it survives the naive-exclusion argument; and drop or re-anchor angle B for the audit low tier as the roster does for 1b.
中文说明
[Suggestion] low 档有两个问题。(1)两轮实验都没有测量过它(两轮都只跑了朴素单 agent 与 8-agent fan-out 两臂),但它不像其他每个未测组件(6a、不变式三连、high 档——都标了"untested"/"extrapolation")那样带此标记;同时它又共享了文档用来把朴素单臂排除出 tier 的那种"单读者、无 fan-out、无验证"形态("offering it would launder an inferior audit under the same command name")。而文档自身的测量显示单读者形态在召回上约落后 fan-out 7 倍。(2)它整体复用 /review 的角度轮换,但 /review 必走的角度 B("diff 删除或替换的每一行")在存量审计里没有对象——已合入代码没有删除行,正是文档用来裁掉 agent 1b 的那个缺失——于是三个保底角度槽位有一个耗在空转上。——失败场景:用户信任档位梯度运行 /audit --effort low;单个内联读者(测得召回约为 fan-out 的 1/7 的形态)产出近乎空的报告,被读成"这个模块不值得真正审计"——这正是 naive-exclusion 段落所说的"洗白",却被用在一个被豁免了同一标准的 tier 上。建议修复:像其他 tier 一样给 low 标"未测",并说明它为何能站得住 naive-exclusion 的论证;并像 roster 对待 1b 那样,为审计 low 档裁掉或改写角度 B。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
Review:
|
| Area | Assessment |
|---|---|
| Design soundness | Strong — measure-first, replicated, honest about extrapolation |
| Fidelity to existing code | Several concrete errors (#1, #2, #3, #4, #9) |
| Cost discipline | Unbounded default; needs a stated ceiling (#5) |
| Evidence reproducibility | Not reviewable as shipped (#6, #7) |
| Conventions | Report path (#8), prettier ✅, no index registration needed |
Nothing here blocks the direction. #1 and #2 should be fixed before merge because they misdescribe the code the design builds on, and #5 because a default tier with no ceiling is the kind of thing that gets discovered by a bill.
中文摘要
方向认可,实验设计(预先声明 3× 判据、换模块性格做复现、明确标注哪些档位是外推)是这个 PR 最有价值的部分。主要问题集中在"文档对现有 /review 代码的描述"上:
3a/3b/3c角色不存在 ——RoleId里只有单个'3'(Agent 3: Code quality)。文档把它当作"brief 换锚点"的既有角色使用,而3b/3c从未定义;"8 维核心"这个数字正是靠拆成三席才凑出来的。check-coverage与lib/roster.ts并非 target-agnostic —— 前者的覆盖判据是"agent 打开过 diff 文件",审计场景根本没有 diff;后者requiredAgents()依赖hasDeletions()/prNumber/srcDiffLines,喂plan-files计划会错误地要求 1b 和 7,并把任意大小的模块都判成"非 fan-out"。这削弱了"新 skill 复用 TS 层"这一论证的成本收益。- 拓扑门限没有数字,且与自身证据矛盾 —— 文中说整文件拓扑"约 5–8k 行",但第二轮的模块是 8,516 行且效果最好。
- "~400 行分块"偷换了单位 —— 现有常量是 diff 行;按源码行用,20k 行模块会切出约 50 个 chunk agent,且没有任何上限。
- 默认档 ~46M token 且无预算上限 —— 唯一的预算规则里 N 还是未定值,建议给出总量上限与启动前成本预估。
- 实验记录不在仓库里(
.qwen/*被 gitignore),但 PR 却请评审者挑战实验协议 —— 建议把精简版附录提交到docs/design/assets/。 - "零误报"是自评 —— 39 个中仅 4 个有外部确认(fix(hooks): close four trust-boundary holes in hook execution #8396),建议措辞放软。
- 报告路径与
.qwen/reviews/<YYYY-MM-DD>-<HHMMSS>-*.md约定不一致;文件分类漏了test;SKILL.md 实际 1,031 行而非 ~1,200。
|
🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下: Autofix review round summary — PR #8397 (round 3 feedback)Commit: All 8 findings (1 Critical, 7 Suggestions) were verified against the exact Findings and dispositions
Verification
中文说明Autofix 评审轮次总结 — PR #8397(第 3 轮反馈)提交: 全部 8 条发现(1 条 Critical、7 条 Suggestion)均已对照其引用的确切源码逐条核实,并在代码中解决(所有改动都在 发现与处置
验证
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/模型 |
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
🤖 Addressed the latest review feedback (round 4/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 4/100 轮)。改动内容与我反驳保留之处如下: Round-4 review feedback addressedThis round triages @wenshao's comprehensive design review (issue-level; no inline threads this round). Every code claim in the review was re-verified against Fixed in this round (docs/design/legacy-code-audit.md):
Declined with evidence:
Needs the PR author — open question for a maintainer (no doc change):
No conflicts ( VerificationDocs-only change (one Markdown file under
中文说明第 4 轮评审反馈处理本轮处理 @wenshao 的全面设计评审(issue 级评论;本轮没有行内线程)。评审中对代码的每一项断言都已先对照 本轮已修复(docs/design/legacy-code-audit.md):
带证据拒绝:
需要 PR 作者 —— 留给维护者的开放问题(不改文档):
无冲突( 验证纯文档变更(
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/模型 |
| The findings the fan-out added were not marginal. The single most severe — | ||
| `cat $(rm -rf /tmp/x)` evaluating to `allow` under `deny: ["Bash(rm *)"]`, | ||
| end-to-end — was touched by the naive agent but filed as a Suggestion |
There was a problem hiding this comment.
[Critical] R4-1: The doc publishes the exact exploit payload for a permissions deny-rule bypass that is still live at this commit — no open or merged PR fixes it. Probe-verified against PermissionManager.evaluate(): with deny: ["Bash(rm *)"] plus allow: ["Bash(cat *)"], cat $(rm -rf /tmp/x) → allow end-to-end (the deny rule is never consulted); process substitution (diff <(rm -rf /tmp/x) …) and backticks also → allow, while the && compound and direct rm correctly deny. The repo is public, so merging this hands any reader a working payload class for an unpatched bypass. The wording is also stale: the deny-only scenario now returns ask, not allow. — Failure scenario: a user whose settings deny Bash(rm *) but allow a commonplace outer command (e.g. Bash(cat *)) can have rm executed by a prompt-injected agent with zero confirmation.
Suggested fix: land or track the fix first (or route it through the SECURITY.md disclosure channel) before referencing it, or redact to the abstract class — "a command substitution inside an allow-matched outer command bypasses deny rules end-to-end" — until a fix ships; re-check the "evaluates to allow" wording.
中文说明
[Critical] 文档公开了一个权限 deny 规则绕过的精确利用载荷,而该绕过在本提交上仍然有效——没有已开启或已合入的 PR 修复它。已对 PermissionManager.evaluate() 实测:deny: ["Bash(rm *)"] 加 allow: ["Bash(cat *)"] 时,cat $(rm -rf /tmp/x) 端到端返回 allow(deny 规则根本未被查询);进程替换(diff <(rm -rf /tmp/x) …)与反引号形式同样返回 allow,而 && 复合命令与直接的 rm 正确返回 deny。本仓库是公开的,合入本文档等于向任何读者提供一个未修复绕过的现成载荷。措辞也已过时:仅 deny 的场景现在返回 ask 而非 allow。——失败场景:设置中 deny Bash(rm *) 但 allow 了常见外层命令(如 Bash(cat *))的用户,会被被注入的 agent 在零确认下执行 rm。
建议修复:先落地或立项跟踪修复(或走 SECURITY.md 披露渠道)再引用该载荷;或在修复落地前改写为抽象类别——"allow 匹配的外层命令内部的命令替换会端到端绕过 deny 规则";同时复核 "evaluates to allow" 的表述。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| **Replication (2026-08-03, `packages/core/src/hooks/` — 23 files, 8,516 | ||
| lines, a lifecycle/event-dispatch module, deliberately different in | ||
| character from the parser-heavy permissions module):** the margin | ||
| reproduced and widened. The naive arm was much stronger this time (3 |
There was a problem hiding this comment.
[Suggestion] R4-2: "the margin reproduced and widened" contradicts the doc's own arithmetic: Round 1's ratio is 17/2 = 8.5×; Round 2's "~7× recall margin" is 22/3 ≈ 7.3× — the ratio narrowed as the naive arm strengthened (which the next sentence itself acknowledges). What widened is the absolute added-findings count (15 → 19). The doc's own usage defines "margin" as the ratio (two sentences below; reused in Verification). — Failure scenario: a reader of the permanent record extracts the claim that fan-out's recall advantage grows with each replication, when the doc's own data shows the ratio shrank.
| reproduced and widened. The naive arm was much stronger this time (3 | |
| reproduced (and widened in absolute terms — 19 added findings vs Round 1's 15, though the ratio narrowed from ~8.5× to ~7× as the naive arm strengthened). The naive arm was much stronger this time (3 |
中文说明
[Suggestion] "the margin reproduced and widened" 与文档自身的数据矛盾:第一轮比率为 17/2 = 8.5×;第二轮 "~7× recall margin" 即 22/3 ≈ 7.3×——随着 naive 臂变强(下一句自己也承认),比率是收窄的。扩大的是绝对新增发现数(15 → 19)。文档自身的用法把 "margin" 定义为比率(两句之后;Verification 一节沿用)。——失败场景:永久记录的读者会得出 "fan-out 的召回优势随每次复现增长" 的结论,而文档自己的数据显示比率在缩小。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| resolved PR number — so a diff-free plan misfires through it (it would | ||
| require 1b and 7, which this design drops, and report no territory fan-out | ||
| at any module size); `check-coverage`'s core predicate is "the agent was |
There was a problem hiding this comment.
[Suggestion] R4-3: The parenthetical "(it would require 1b and 7…)" misdescribes the misfire — probe-verified against roster.ts with exactly the plan shape this design specifies (plan-files populates files[], all removedLines zero, no worktree): hasDeletions() returns false (the true-on-empty fail-safe only fires on an empty list), so 1b is not required; and with no worktree/untracked, reviewMode() resolves diff-only — the one mode where requiredAgents() drops both 7 and 1c. Both clauses are false; the actual misfire is the opposite-shaped one: a near-empty roster that silently drops 1c — the agent the roster table calls "mandatory". The territory-fan-out clause is correct. — Failure scenario: an implementer parameterizing the roster for audit plans guards against the documented misfire (spurious 1b/7) while the real behavior — 1c, the walk that "produced the unique Criticals in both rounds", never runs on any audit — ships unflagged.
Suggested fix: replace the parenthetical with the actual diff-free behavior — hasDeletions() is false once plan-files writes per-file entries; reviewMode() reads diff-only; the roster comes back near-empty, dropping the 1c this design keeps as mandatory; keep the territory-fan-out clause.
中文说明
[Suggestion] 括号里 "(it would require 1b and 7…)" 对 misfire 的描述有误——已按本设计自身指定的计划形状(plan-files 填充 files[]、所有 removedLines 为零、无 worktree)对 roster.ts 实测:hasDeletions() 返回 false(空列表才触发的 fail-safe 不会触发),因此不要求 1b;无 worktree/untracked 时 reviewMode() 解析为 diff-only——恰好是唯一会同时丢掉 7 和 1c 的模式。两个子句均不成立;真实的 misfire 形状相反:近乎空的 roster 会悄悄丢掉 1c——roster 表称其为 "mandatory" 的 agent。territory fan-out 子句正确。——失败场景:按文档描述为审计计划参数化 roster 的实现者会去防范不存在的 1b/7 误触发,而真实行为——任何审计都不会运行 "两轮都产出唯一 Critical" 的 1c 扫描——会无人察觉地上线。
建议修复:把括号改为实际的 diff-free 行为——plan-files 写入逐文件条目后 hasDeletions() 为 false;reviewMode() 为 diff-only;roster 近乎为空并丢掉本设计保留为必选的 1c;保留 territory fan-out 子句。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| the triple silently never runs. Legacy heaviness is instead: a source | ||
| file at or above the same 300-line floor that holds long-lived mutable | ||
| state — the checklist's subject: class-level fields, caches, timers, | ||
| registries, error taxonomy. As in `/review`'s roster, the triple runs |
There was a problem hiding this comment.
[Suggestion] R4-4: The legacy heaviness predicate is semantic ("holds long-lived mutable state") but is assigned to the deterministic plan-files subcommand, which cannot decide it — plan-files plays plan-diff's model-free role, and the Verification section even promises the predicate as a unit-testable function. The gloss also lists "error taxonomy" as an instance of long-lived mutable state — a category error heavy.ts's own checklist-subject list makes consequential: taxonomic heaviness is a legitimate subject any syntactic mutable-state heuristic misses. — Failure scenario: (a) a syntactic heuristic misses files whose state lives in uncovered idioms (closures, delegated stores) and taxonomically-heavy files — reproducing on the legacy predicate the exact silent non-run this paragraph warns about for lifted classifyHeavy; or (b) over-marking every ≥300-line file spends 3 invariant agents each — above the gate, chunk agents already consume N/400 of the 40-agent ceiling, so a state-dense module exceeds it and the run refuses: the default tier unusable for its core target.
Suggested fix: match the owner to the predicate — plan-files nominates candidates deterministically (≥300-line source files) and the orchestrator makes the semantic call with the marking disclosed in the report header, or state a syntactic predicate and own its miss rate; in both cases restate the gloss so "error taxonomy" is not an instance of "long-lived mutable state".
中文说明
[Suggestion] 存量"重文件"判定是语义性的("承载长期可变状态"),却被指派给确定性的 plan-files 子命令——它无法做出该判断:plan-files 扮演的是 plan-diff 那种无模型参与的角色,Verification 一节甚至承诺该判定是可单测的纯函数。术语表还把 "error taxonomy" 列为长期可变状态的实例——这是类别错误,且 heavy.ts 自己的清单主题列表使其产生实际后果:分类学意义上的"重"是任何语法级可变状态启发式都会漏掉的合法对象。——失败场景:(a) 语法启发式会漏掉状态存在于未覆盖习语(闭包、委托存储)中的文件和分类学上重的文件——在存量判定上复现本段警告 classifyHeavy 会产生的"三连静默不运行";或 (b) 把每个 ≥300 行文件都标重,每个消耗 3 个不变式 agent——门限之上 chunk agent 已占用 40-agent 上限的 N/400,状态密集的模块会超限导致运行被拒绝:默认档对其核心目标不可用。
建议修复:让判定者与被判定者匹配——plan-files 确定性地提名候选(≥300 行源文件),由 orchestrator 做语义判定并在报告头披露标记;或明写一个语法判定并承认其漏检率;两种情况下都重写术语表,使 "error taxonomy" 不再作为 "长期可变状态" 的实例。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - detects event/lifecycle modules by emit/dispatch/subscribe call | ||
| patterns and flags them for the 1c event-coverage brief. |
There was a problem hiding this comment.
[Suggestion] R4-5: Event-module detection is a syntactic heuristic whose outcome is never disclosed, so a false negative silently withholds the walk this paragraph spends 20 lines establishing: 1c still completes with its plain brief (the addendum is a brief modifier, not a separate walk), so the header's "walks completed or skipped" records 1c as completed and no reader can distinguish "not an event module" from "detection missed". The asymmetry sits within the same bullet list: the adjacent heavy-marking heuristic earns an extrapolation flag; this one gets nothing. — Failure scenario: a lifecycle module whose dispatch idiom falls outside the literal emit/dispatch/subscribe set (custom event bus, callback registry, subject/observer) is not detected; the walk the doc says "produced two Criticals unique in the field" (fire-misses on early-return/error/abort paths) is silently absent from the report.
Suggested fix: record the detection outcome in the report header alongside the other flags (e.g. "event module: detected / not detected (heuristic)"), so a false negative is at least inspectable after the fact.
中文说明
[Suggestion] 事件模块检测是一个语法启发式,其结果从不披露,因此一次漏检就会悄悄取消本段花 20 行建立的扫描:1c 仍会以普通 brief 完成(事件覆盖是 brief 修饰而非独立扫描),头部 "walks completed or skipped" 会把 1c 记为已完成,读者无法区分"不是事件模块"与"检测漏了"。不对称就在同一 bullet 列表内:相邻的重文件标记启发式有外推旗标,这个却没有。——失败场景:分发习语不在字面 emit/dispatch/subscribe 集合内的生命周期模块(自定义事件总线、回调注册表、subject/observer)不会被检测到;文档称"产出全场唯一两个 Critical"的扫描(早退/错误/中止路径上的漏触发)会从报告中静默缺席。
建议修复:把检测结果与其他旗标一并记入报告头(如 "event module: detected / not detected (heuristic)"),使漏检事后至少可查。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| header with the other unexercised-machinery flags. High is | ||
| extrapolation: it prints and confirms the same estimate, but its | ||
| ceiling waits for its first measurement. |
There was a problem hiding this comment.
[Suggestion] R4-9: High "prints and confirms the same estimate" — but the only estimate basis the doc supplies is the single-fan-out measurement, while high is defined as medium plus an iterative reverse audit of up to 5 rounds that each fan out over the module. The confirmation gate therefore covers 1 of up to 6 fan-out-shaped passes, and high has no token ceiling at all ("its ceiling waits"). — Failure scenario: a user confirms ~46M for an 8,516-line module — a number built from one fan-out pass — and the run then executes the initial fan-out plus up to 5 further module-wide rounds with nothing bounding tokens, consuming several times the confirmed figure. The section's cost discipline ("not an open tab"; "the run starts only on user confirmation") is maximally wrong for the most expensive tier.
Suggested fix: state what the high estimate contains — the medium estimate × the round structure, printed as a range from the earliest dry stop (initial pass + 2 rounds) to the 5-round hard cap, with the confirmation naming that range — or give high a provisional total ceiling (a multiple of medium's 60M) until its first measurement, instead of none.
中文说明
[Suggestion] high 档 "prints and confirms the same estimate"——但文档提供的唯一预估基准是单次 fan-out 的测量值,而 high 的定义是 medium 加最多 5 轮、每轮都对整个模块 fan-out 的迭代反向审计。确认门因此只覆盖了至多 6 次 fan-out 形态通行中的 1 次,且 high 没有任何 token 上限("its ceiling waits")。——失败场景:用户为 8,516 行模块确认 ~46M——一个按单次 fan-out 算出的数字——随后运行执行初始 fan-out 外加最多 5 轮全模块扫描,没有任何 token 约束,消耗达到确认值数倍。本节的成本纪律("not an open tab"、"the run starts only on user confirmation")恰在最贵的档位上完全失效。
建议修复:写明 high 预估包含什么——medium 预估 × 轮次结构,以区间形式打印(从最早 dry 停止:初始 + 2 轮,到 5 轮硬上限),确认时指明该区间;或在首次实测前给 high 一个临时总量上限(medium 60M 的倍数),而不是没有。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| header: the audited commit SHA and dirty/clean state of the checkout | ||
| (file:line anchors drift with HEAD, so a re-audit after fixes must be | ||
| alignable with the run it follows), the effort tier, and the walks |
There was a problem hiding this comment.
[Suggestion] R4-10: The header's stated purpose — re-audits "must be alignable with the run it follows" — rests on the audited commit SHA, but a SHA pins audited content only when the checkout is clean. The design permits dirty runs (it records dirty/clean state and refuses nothing), and on those the file:line anchors reference uncommitted content that no git operation can later recover; the "dirty" flag discloses the state without preserving the content. — Failure scenario: a user audits a checkout with uncommitted changes; findings anchor to lines of the dirty content. The user fixes, commits, re-audits, and opens the earlier report to align: the SHA predates the fixes, and the exact lines the anchors pointed at were never committed and have since been modified — nothing in git reconstructs the audited tree, so the stated alignability property fails in a case the design explicitly allows.
Suggested fix: condition the promise — alignment holds where the checkout was clean — and either require a clean checkout before running, or snapshot the dirty delta with the report (e.g. write the git diff of the dirty state into .qwen/audits/ alongside it) so anchors remain resolvable on dirty runs.
中文说明
[Suggestion] 报告头声明的目的——复审"必须能与它跟随的那次运行对齐"——依赖被审计的 commit SHA,但 SHA 只有在 checkout 干净时才能钉住被审计的内容。设计允许脏运行(只记录 dirty/clean 状态、不拒绝任何情况),此时 file:line 锚点指向的是任何 git 操作事后都无法恢复的未提交内容;"dirty" 旗标披露了状态却没有保存内容。——失败场景:用户在有未提交修改的 checkout 上审计,发现锚定在脏内容的行上;用户修复、提交、复审,再打开旧报告对齐:SHA 早于修复,锚点指向的行从未被提交且已被修改——git 中没有任何东西能重建被审计的树,声明的可对齐性在设计明确允许的场景下失效。
建议修复:给承诺加条件——对齐只在 checkout 干净时成立——要么要求干净 checkout 才能运行,要么把脏差量快照随报告保存(如把脏状态的 git diff 写入 .qwen/audits/ 同目录),使脏运行的锚点仍可解析。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| `unreviewedDimensions`). The header also carries every flag this design | ||
| attaches to unexercised machinery — above-gate topology, the high-tier | ||
| loop, twice-whiffed reverse-audit scopes, budget-bound walks, unmeasured | ||
| tiers — since `/audit` has no verdict for them to cap. |
There was a problem hiding this comment.
[Suggestion] R4-11: This enumeration claims to carry every flag the design attaches to unexercised machinery, but omits at least three. (1) The extrapolation flag the design explicitly attaches to the invariant-checklist triple at lines 143–145 ("untested in the experiments … flagged as extrapolation") — not co-extensive with "above-gate topology": an above-gate run with no heavy files carries the topology flag without running the triple, and the triple's analogy-based transfer + new legacy-heaviness predicate is a distinct fact. (2)+(3) The two unmeasured budget constants (60M / 40 agents) the Budget ceiling section promises "ride into the report header with the other unexercised-machinery flags"; and the 6a seat's "untested" status carries no header flag either. The doc's own convention routes sibling flags "in the report header" (high tier, low tier). — Failure scenario: an implementer builds the header from this enumeration; on above-gate runs (the only runs where the triple executes), findings from untested analogy-based machinery, the unmeasured constants, and 6a's status are presented without disclosure — exactly the disclosure failure this sentence exists to prevent, since /audit has no verdict to cap unexercised machinery.
Suggested fix: complete the enumeration (add the invariant triple's extrapolation, the unmeasured ceiling constants, 6a's untested status), or state at each attachment site that the flag rides with the above-gate header flag.
中文说明
[Suggestion] 该枚举声称承载设计附加给未演练机制的所有旗标,但至少漏了三项。(1) 设计在 143–145 行明确附加给不变式三连的外推旗标("untested in the experiments … flagged as extrapolation")——与 "above-gate topology" 不重合:门限之上但没有重文件的运行带拓扑旗标却不运行三连,且三连的类比迁移与新的存量"重"判定是独立事实。(2)+(3) Budget ceiling 一节承诺 "ride into the report header with the other unexercised-machinery flags" 的两个未实测预算常量(60M / 40 agents);6a 席位的 "untested" 状态同样没有头部旗标。文档自己的惯例是把同类旗标放入报告头(high 档、low 档)。——失败场景:实现者按此枚举构建头部;门限之上的运行(三连唯一会执行的运行)中,来自未实测类比机制的发现、未实测常量与 6a 的状态都不经披露地呈现——这正是本句要防止的披露失败,因为 /audit 没有可封顶未演练机制的 verdict。
建议修复:补全枚举(加入不变式三连的外推旗标、未实测上限常量、6a 的未测状态),或在每处附加点写明该旗标随门限之上的头部旗标一并披露。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - **Local-only by construction:** `.qwen/*` is gitignored, so the report | ||
| never lands in version control — a real security property, since an | ||
| audit of a security module will quote exploitable code. |
There was a problem hiding this comment.
[Suggestion] R4-12: "Local-only by construction" rests on a mutable, per-project gitignore state, not a construction. (a) This repo's own .gitignore re-includes four .qwen/ subtrees (commands/, skills/, agents/, team-memory/ — the last documented as shared through git), and 71 tracked files already exist under .qwen/ despite no re-inclusion rule (force-adds happen), so a future !.qwen/audits/** or force-add silently inverts the property. (b) /audit runs in arbitrary user repositories, where nothing guarantees .qwen/ is gitignored — the only flow that adds it is setup-github; the codebase already handles the both-ways case (team-memory-git-status.ts runs git check-ignore). — Failure scenario: a user audits a security-sensitive module in a repo whose .gitignore lacks .qwen/ (the common case outside this repo), producing a report quoting exploitable code; a later git add -A && git commit && git push commits it, possibly to a public remote — exactly the outcome this bullet claims is impossible. An implementer trusting "by construction" builds no verification, so nothing catches it.
Suggested fix: restate as a constraint, not a construction — the property holds where the project ignores .qwen/* and no re-inclusion/force-add moves reports into a tracked subtree — and specify that /audit verifies the audits directory is actually ignored (e.g. git check-ignore on a probe path) and warns or refuses when it is not.
中文说明
[Suggestion] "Local-only by construction" 依赖的是可变的、逐项目的 gitignore 状态,而非构造使然。(a) 本仓库自己的 .gitignore 重新包含四个 .qwen/ 子树(commands/、skills/、agents/、team-memory/——最后一个明确记载通过 git 共享),且 .qwen/ 下已有 71 个被跟踪文件是在没有重包含规则的情况下存在的(force-add 确实会发生),未来一条 !.qwen/audits/** 或一次 force-add 就会悄悄反转该属性。(b) /audit 运行在任意用户仓库中,那里没有任何机制保证 .qwen/ 被 gitignore——唯一添加它的流程是 setup-github;代码库已在处理双向情况(team-memory-git-status.ts 会跑 git check-ignore)。——失败场景:用户在 .gitignore 没有 .qwen/ 的仓库(本仓库之外的常态)审计安全敏感模块,生成引用可利用代码的报告;之后 git add -A && git commit && git push 把它提交,可能推到公开远端——正是本条声称不可能的结果。信任 "by construction" 的实现者不会构建任何校验,于是没有任何东西能拦住它。
建议修复:改写为约束而非构造——该属性在项目 ignore .qwen/* 且无重包含/force-add 把报告移入被跟踪子树时成立——并规定 /audit 验证 audits 目录确实被 ignore(如对探测路径执行 git check-ignore),未通过则警告或拒绝。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
| - **low** — inline read by the orchestrator itself, angle rotation as in | ||
| `/review` low minus angle B (removed behaviour — merged code has no | ||
| deletions; the same absence that dropped agent 1b); unverified |
There was a problem hiding this comment.
[Suggestion] R4-13: "angle rotation as in /review low minus angle B" leaves two adaptation problems unspecified. (1) The surviving angles are diff-anchored in the review skill — A walks "every hunk, every changed line"; C reports "only instances the diff introduces"; D fires "when the diff adds or changes"; E hunts code "visible in the diff"; F requires siblings "also visible in the diff" — and nothing re-anchors them to a diff-less target; the Roster section's mechanical re-anchor recipe ("walk every hunk" → "walk every production file") is prescribed for the dimension briefs only, even though its first example is verbatim angle A's text. (2) Removing B breaks the lifted budget floor: MIN_INLINE_ANGLES = 3 is justified in budget.ts by the three always-walked angles being A, B, C — so "rotation minus B" at the floor yields two directed angles, silently below the lifted floor, on exactly the small triage targets the floor exists for (or pulls in size-gated angle D, whose precondition a <180-line target fails). — Failure scenario: built literally, on any diff-less audit C/D/E/F have no referent and the tier silently loses the rotation that is its stated value proposition; on a ~50-line triage target the lifted mapping returns the floor 3 → two effective angles, shrinking the rotation by a third with nothing flagged in the header.
Suggested fix: two clauses in this bullet — the surviving angles are re-anchored from diff to module with the Roster section's mechanical change (B the only outright removal), and the floor is rebased: either to A and C (accept two angles and say so), or onto the B-less list (A, C, D, …) with D's size precondition waived at this tier.
中文说明
[Suggestion] "angle rotation as in /review low minus angle B" 留下两个未指明的适配问题。(1) 幸存的角度在 review skill 中都是锚定 diff 的——A 走 "every hunk, every changed line";C 只报 "the diff introduces" 的实例;D 在 "the diff adds or changes" 时触发;E 找 "visible in the diff" 的代码;F 要求兄弟成员 "also visible in the diff"——而没有任何内容把它们重新锚定到无 diff 目标;Roster 一节的机械换锚配方("walk every hunk" → "walk every production file")只规定用于维度 brief,尽管它的第一个例子就是角度 A 的原文。(2) 去掉 B 破坏了抬取的预算下限:budget.ts 中 MIN_INLINE_ANGLES = 3 的理由正是永远必走的角度是 A、B、C——因此下限处的 "rotation minus B" 只剩两个定向角度,悄悄低于抬取的下限,且恰恰发生在下限为其存在的小目标分诊场景(或者拉入按规模解锁的角度 D,而 <180 行的目标不满足其前提)。——失败场景:按字面实现,任何无 diff 审计中 C/D/E/F 都没有指称对象,该档位悄悄失去其声明的价值主张即角度轮换;在 ~50 行的分诊目标上,抬取的映射返回下限 3 → 只有两个有效角度,轮换缩水三分之一且头部不做任何标记。
建议修复:在本 bullet 加两个子句——幸存角度按 Roster 一节的机械变换从 diff 重新锚定到模块(B 是唯一 outright 移除);下限重新设定基准:要么改为 A 和 C(接受两个角度并明说),要么改为无 B 列表(A、C、D、…)并在本档豁免 D 的规模前提。
— qwen3.8-max-preview via Qwen Code /review (v0.21.3)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下: Round-5 review feedback — address summary (PR #8397)Commit: All 13 findings (1 Critical, 12 Suggestions) were verified against the code before acting; all were classified act, and all are fixed in this commit. No finding was declined or escalated. Critical
Suggestions
Verification
中文说明第 5 轮评审反馈处理总结(PR #8397)提交: 全部 13 条发现(1 条 Critical、12 条 Suggestion)均已先对照代码核实再处理;全部归类为 act(应处理),且均已在本提交中修复。没有拒绝或升级任何一条。 Critical
Suggestion
验证
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/模型 |
Code reviewDocs-only: one new design doc ( I checked the doc's factual claims about the machinery it proposes to reuse against
That is an unusually high fidelity rate for a doc citing this much machinery, and the "needs a target-kind parameter, not a lift" section correctly identifies every gate that misfires on a diff-free plan. My findings below are all about the new machinery the doc invents, not the reused parts. Critical — the plan-time agent cap cannot count the agents it is meant to capThe doc pins two numbers that interact badly:
The count that decides the refusal is therefore evaluated before the thing that determines it. Failure scenario: a 9,001-line module (just above the 9,000 gate) yields 23 chunk agents + 4 whole-module agents (1c, 3a, 5, 6a) = 27, and Suggestion: either move the semantic marking into plan time as a bounded nomination ( Critical — the above-gate branch is arithmetically a ~1,000-line windowIndependently of the counting bug, the two ceilings and the gate leave almost no reachable band:
So a module clearing the 9,000-line gate is auditable at medium only in roughly 9,000–10,000 lines before one bound or the other refuses; everything larger gets "ask for a narrower path", which for a genuinely cohesive 20k-line subsystem is not an answer. Note also that Worth stating explicitly in the doc: below the gate the design is measured and cheap, above it there is a narrow band, and past ~10–14k lines Critical — no untrusted-input discipline for the audited code, and execution has no consent gate
Failure scenario: auditing a vendored dependency whose source comment reads Compounding it, the run executes: probes on scratch copies, plus the proposed baseline test run. The doc's mitigation is disclosure ("the header states that the run executed code"), which tells the user after the fact. The open question is framed as "which tiers does the baseline test run join" — it should first be "is running a third-party module's test suite opt-in", and the answer should be yes. Suggestion: (a) an untrusted-data preamble in every audit brief, same register as Agent 0's; (b) confirm-before-execute for the baseline test run, not disclose-after. Suggestion — the
|
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Round 11 — Address review feedback on PR #8397Round-11 feedback from @wenshao on Before editing, every code claim in the blocking findings was re-verified against this checkout: Findings and dispositions1. (Blocking) 2. (Blocking) Enumeration source unspecified; collides with "generated stays subjects" — FIXED. Target resolution now specifies a filesystem walk (not 3. (Significant) Nothing rules the non-interactive path — FIXED. Explicit rule added: 4. (Significant) Low's inline shape doesn't survive the move to 5. (Significant) "No verdict is the backstop" overstates the injection defense — FIXED. The passage now says the substantive defenses are the preamble and the measured redundancy (three root causes each found independently by 3 agents — an injection in one file has to defeat every agent that walks it). The no-verdict shape is demoted to closing only the certification channel; suppression is named as needing no verdict channel at all (an empty list ships as "walks completed: security, 0 findings", and the substantive-return check does not catch a suppressed-but-compliant agent, which can produce examination evidence). 6. (Significant) Scratch-copy probe can't reach the headline finding class — FIXED. New paragraph in Dedup and verification states what the probe can and cannot prove: nothing imports the scratch copy, so the probe exercises the fixed file in isolation; every cross-file failure scenario (1c's class, the three-file-chain Criticals) is unreachable, and cross-file findings therefore cap at the unit-probe evidence tier. Both smaller edges named: the sibling lands in the package's tsconfig include set (a concurrent typecheck compiles it; probes are short-lived, window named rather than solved), and the scratch prefix must not match the project's test globs. 7. (Significant) Hard-stopping on drift is expensive — FIXED (adopted the narrower predicate). Drift handling is now per-file: drift in a file already walked and carrying anchored findings stops the run; drift in any other file marks it drifted/uncoverable in the header and walks record, and the run continues (write-time anchor resolution is what later findings stand or fall by). Rationale cites the two dominant use cases putting the user actively in the module and the 32–60M-token cost of a medium run. Walks-record uncoverable reasons now include drifted files; Verification unit list updated. 8. (Smaller) The 60M cap carries no independent information — FIXED. The Ceiling bullet now says the two 1.3×s are one deliberate choice, not two: the estimate top and the cap apply the same headroom, so the factors cancel and the check reduces to "the plan's priced cost is at most the largest cost we measured" — stated so the dead-zone analysis doesn't inherit the confusion. 9. (Smaller) Name where the shared TypeScript layer physically lives — FIXED. The lifted layer (findings schema, budget shape) lands in 10. (Smaller) Tier-selection surface never named — FIXED. Effort-tiers Decisions now name 11. (Smaller) Readability — FIXED. The ~35-line mega-sentence in "A new skill" is now four per-machinery bullets; the ~100-line report-header bullet in Output is split into seven labeled bullets (artifact, run-metadata header — nested sidecar parentheticals flattened, consumption record, drift protection, walks record, whiff check, unexercised machinery); Decisions summary blocks added to the three sections that lacked them ("A new skill", Roster, Output), matching the shape of Target resolution, Budget ceiling, and Effort tiers. 12. (Smaller) Land the redacted Round 2 record with this PR — DEFERRED, author action required. This one cannot be done from this flow: the untracked originals exist only on the author's machine. Verified in this checkout — Conflict notes
Verification
中文说明第 11 轮 — 处理 PR #8397 的评审反馈第 11 轮反馈来自 @wenshao,针对 编辑前已对照当前检出代码逐条复核两条 blocking 发现所引用的代码事实: 各条发现及处理1.(Blocking) 2.(Blocking)枚举来源未指定,且与"generated 保留为审查对象"冲突 — 已修复。 Target resolution 现明确采用文件系统遍历(而非 3.(Significant)非交互路径无规则 — 已修复。 新增明确规则: 4.(Significant)low 的内联形态无法延续到 5.(Significant)"无裁决即兜底"夸大了注入防御 — 已修复。 该段现改为:实质防御是前导言与实测冗余(三个根因各被 3 个代理独立发现 —— 一个文件中的注入必须击败所有走查该文件的代理)。"无裁决"形态被降级为仅封堵"认证"通道;抑制被明确指出无需裁决通道(空清单会以 "walks completed: security, 0 findings" 出报,且 substantive-return 检查无法捕获"合规但抑制"的代理,因为它能产出"已审查内容"的证据)。 6.(Significant)草稿副本探针无法触达文档头条发现类别 — 已修复。 Dedup and verification 新增一段,说明该探针能与不能证明什么:没有任何代码导入草稿副本,探针只能在孤立状态下执行被修复的文件;一切跨文件失败场景(1c 的类别、三文件链 Critical)不可达,跨文件发现的证据层级因此以 unit-probe 为上限。两个较小边缘也已写明:兄弟文件会落入包的 tsconfig include 集(并发 typecheck 会编译它;探针生命周期短,窗口被点名而非解决);草稿前缀必须避免匹配项目自身的测试 glob。 7.(Significant)漂移即硬停对既定用例代价过高 — 已修复(采纳更窄谓词)。 漂移处理改为按文件:已走查且携带锚定发现的文件发生漂移 → 停止运行;其他文件的漂移只在 header 与 walks record 中标记为 drifted/uncoverable,运行继续(后续发现由写时锚点解析裁定)。理由引用两个主要用例(用户正在该模块内工作)与 medium 一次 32–60M token 的成本。walks record 的 uncoverable 原因新增 drifted files;Verification 单测清单同步更新。 8.(Smaller)60M 上限不携带独立信息 — 已修复。 Ceiling 条目现明确:两个 1.3× 是同一个刻意选择而非两个独立选择 —— estimate 上限与 cap 施加同一 headroom,两者相消后检查退化为"计划定价不超过我们实测过的最大成本",以免死区分析继承这一混淆。 9.(Smaller)指明共享 TypeScript 层的物理位置 — 已修复。 被提升的层(findings schema、预算形态)落在 10.(Smaller)从未指明 tier 选择面 — 已修复。 Effort tiers 的 Decisions 现写明 11.(Smaller)可读性 — 已修复。 "A new skill" 中约 35 行的超长句拆为四个按机制分列的条目;Output 中约 100 行的报告 header 大条目拆为七个带标签的条目(artifact、run-metadata header(嵌套旁路括号已展平)、consumption record、drift protection、walks record、whiff check、unexercised machinery);三个缺失 Decisions 摘要块的章节("A new skill"、Roster、Output)已补齐,与 Target resolution、Budget ceiling、Effort tiers 的形态一致。 12.(Smaller)将脱敏后的 Round 2 记录随本 PR 落地 — 暂缓,需作者操作。 此条在本流程中无法完成:未跟踪的原始记录只存在于作者本人的机器上。已在本检出中核实 —— 冲突说明
验证
Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。 🧠 Handled by Qwen Code · model/模型 |
Review —
|
|
🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #8397 (round 12)Docs-only PR ( Findings1. The 40-agent cap cannot fire in v1 — addressed. 2. Enumeration exclusion list omits 3. 4. 5. Evidence is unverifiable by any reviewer — addressed as far as this Nits
Verification
中文说明本轮摘要 — PR #8397(第 12 轮)仅文档的 PR( Findings1. 40-agent 上限在 v1 永远不会触发 — 已处理。 2. 枚举排除清单漏了 3. 4. 5. 证据不可被任何评审者核验 — 在本 checkout 所能范围内已处理;残留如实说明。 Nits
验证
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/模型 |
OverviewDocs-only: a 1,238-line design doc for I verified the doc's claims two ways: every load-bearing assertion about existing Code claims — all confirmed (note: this checkout is behind main;
This is an unusually high fidelity rate for a doc of this size. The findings below are the ones that survived. Substantive1. The two-rate decomposition is ill-conditioned — the design's only quantitative machinery has no error barsThe rates, the estimate, and the 60M cap all derive from one exact fit through two points (the doc flags "n=2" but treats the fit as usable). The two modules' subject line counts are only 11% apart (7,638 vs 8,516), so the system is near-singular in the subject dimension and the fit is far more fragile than "n=2" conveys. Concretely: hold Round 2 fixed and move Round 1's total from 32.5M to 28M — a 14% change in one author-reported, undated number — and the subject rate collapses from ~2.6M to ~1.17M per 1,000 (−55%), while the test rate rises from ~1.46M to ~2.21M (+51%). Near the two data points the totals stay stable, so this is invisible on the calibration modules. It bites off-ratio, which is exactly the regime the doc admits is unmeasured: a 9,000-subject / 2,000-test module prices at 26.4M under the published rates and 14.9M under the perturbed ones — a factor of ~1.8 on the number the consent gate is confirmed against. This compounds with Provenance: Round 1 carries no date, no SHA, no model id, and the record is untracked on one machine. The design's cost model rests more heavily on that one unreproducible number than the text acknowledges. Suggestions, in order of preference: (a) make the redacted-records commit a ship criterion for the constants, not just the spec, and re-derive from the committed totals; (b) publish the rates with an explicit uncertainty band and derive the cap from the band's top; (c) at minimum, state in Measurement inputs that the fit is ill-conditioned in the subject dimension and that off-ratio modules inherit the widest error. 2. The published rounded rates refuse the hooks module — at the exact corner the doc says is admitted "by construction"The doc asserts the calibration modules are admitted by construction and that the 1.3× factors "cancel", reducing the check to "priced cost ≤ largest measured cost". With unrounded rates the hooks floor is exactly 46.0M and the top 59.8M — under the cap, as claimed. With the rounded rates the doc actually publishes (~2.6M / ~1.5M), the floor is 2.6 × 8.516 + 1.5 × 16.335 = 46.64M and the top is 60.6M — over the 60M cap. An implementer coding the constants as written refuses the replication the design's argument rests on, at plan time. The cancellation claim is also only exact when the floor equals the measured total, which rounding breaks. Fix by one of: specify the rates to the precision the fit requires; define the cap as 1.3 × the estimate floor rather than an absolute constant; or state the cap as 61M. Worth a line either way, since the doc explicitly invites re-checking this arithmetic. 3. The local-only guard protects the report but not the intermediate artifactsThe "never in version control" property is treated as a real security property and defended thoroughly for But In this repo Related, smaller: the terminal summary prints top clusters, and cluster titles will quote specifics. Terminal output lands in scrollback and session transcripts. Probably acceptable, but given how carefully the report's exposure is reasoned, one sentence ruling it is warranted. 4. The duplication cost of "new skill" is named but not pricedThe doc rejects a
There's a third option not in Rejected alternatives: extract the shared predicates into a Smaller notes
RisksLow — no code ships. The real risk is downstream: the constants (rates, 60M, 9,000/18,000, N=10, 2,000) are unmeasured or thinly-measured first cuts, and the doc labels them as such throughout, which is the right call. Findings 1 and 2 are worth resolving before those constants are coded, since both change what the consent gate quotes and what plan-time refuses. Design decisions I'd endorse as-is: mandatory 1c (the evidence for it is the strongest in the doc), the failure-scenario bar and authority-on-the-failure-path severity heuristic, root-cause clustering with max-severity carry, refusing to pre-confirm probe-backed clusters, the no-verdict shape, keeping one undirected persona seat, and the untrusted-data preamble's honest accounting of what it does and doesn't defend. |
|
🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下: Round-13 review feedback addressed — PR #8397Single issue-level comment from @wenshao (no inline comments; no failed or Substantive1. The two-rate decomposition is ill-conditioned — ActedThe reviewer's perturbation arithmetic was re-derived and confirmed (rates
2. The published rounded rates refuse the hooks module — ActedConfirmed: at the rounded ~2.6/~1.5 rates the hooks floor is ~46.64M and the 3. The local-only guard protects the report but not the intermediates — ActedVerified the cited machinery:
4. The duplication cost of "new skill" is named but not priced — ActedThe reviewer's third option is engaged rather than ignored. Verified first: Smaller notes
Verification
No conflict notes ( 中文说明已处理第 13 轮评审反馈 — PR #8397来自 @wenshao 的单条 issue 级评论(无行内评论;无失败或持续失败的检查; 实质性意见1. 双费率分解是病态条件的(ill-conditioned)— 已处理评审者的扰动算术已重新推导并确认(Round 1 未标注日期的总额变化 14% 时,两个费率分别移动 −55%/+51%;一个偏离比例的 9,000/2,000 模块的定价相差约 1.8 倍)。改动:
2. 已发布的四舍五入费率会拒绝 hooks 模块 — 已处理已确认:按约 2.6/1.5 的舍入费率,hooks 的下限约为 46.64M、上限约为 60.6M,超过 60M 上限;按拟合精度,上限为 59.9M。修复:两处出现的费率现按拟合所需精度发布(约 2.61M/约 1.46M,上限约 3.39M/约 1.90M),并明确注明:舍入到两位有效数字会把 hooks 模块定价到超过其测量成本,并会在计划阶段拒绝该复现验证。1.3× 抵消段落现说明该简化在 quoted 精度下成立。校准算术已按新精度重新验证(permissions 32.5–42.3M,hooks 约 46M–约 60M 上限在上限之内,最坏角点约 65M)。 3. 本地专属守卫保护了报告,但没有保护中间产物 — 已处理已核实所引用的机制:
4. "新技能"的重复成本被点名但未被计价 — 已处理评审者的第三个选项被正面处理而非忽略。先核实: 次要意见
验证
无冲突说明( 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/模型 |
| permission-merge flaw is the hooks module's own — its aggregator merges | ||
| PermissionRequest hook outputs, permission decisions included — not a | ||
| carry-over from Round 1's permissions subject. |
There was a problem hiding this comment.
[Critical] R7-1: The document publishes the class, mechanism, and module location of the permission-merge flaw — hookAggregator.ts merges PermissionRequest hook outputs including permission decisions (allow wins absent deny), consumed by firePermissionRequestHook, which can short-circuit the normal permission flow — while the Context section's own withholding criterion (lines 27–32) withholds findings that are "unpatched as of writing and no public tracking artifact (issue or advisory) cites it yet". Verified at this commit: the mechanism is live (mergePermissionRequestOutputs merges behavior with allow winning absent deny) and no issue, advisory, or PR tracks it — PR 8396 covers only the four other trust-boundary findings and explicitly defers the permission findings. — Failure scenario: this repo is public → merging localizes a live trust-boundary flaw before any fix is tracked or shipped. Suggested fix: apply the document's own criterion — withhold class and mechanism (the most-confirmed / independent-discovery-count point carries without naming the module), or land a public tracking artifact first and cite it here.
中文说明
[Critical] R7-1:文档公布了 permission-merge 缺陷的类别、机制与模块位置——hookAggregator.ts 合并 PermissionRequest hook 输出(含权限决定,无 deny 时 allow 胜出),其消费者 firePermissionRequestHook 可短路正常权限流程——而 Context 节自己的保留准则(27–32 行)要求对"截至撰写时未修补且无公开跟踪产物(issue 或公告)引用"的发现完全保留。已在本提交核实:该机制仍然有效(mergePermissionRequestOutputs 在无 deny 时以 allow 合并 behavior),且无任何 issue、公告或 PR 跟踪——PR 8396 只覆盖另外四个信任边界发现,并明确推迟权限类发现。——失败场景:本仓库公开,合入即在无任何修复跟踪的情况下定位一个活的信任边界漏洞。建议修复:套用文档自己的准则——隐去类别与机制("最多独立发现"的论点不需要点名模块即可成立),或先立公开跟踪产物并在本句引用。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| two unique Criticals (a failure hook that never fires on API-error turn ends | ||
| in headless mode, and on loop detection in ACP sessions) came from exactly | ||
| this walk; both were adjacent-class siblings of a historical fix that had |
There was a problem hiding this comment.
[Critical] R7-29: This sentence discloses class + mechanism + module of the two Round-2 fire-miss Criticals (a failure hook that never fires on API-error turn ends in headless mode, and on loop detection in ACP sessions) while the withholding criterion (lines 27–32) withholds findings that are unpatched with no public tracking artifact — and none exists for these two: #8396 covers only the four trust-boundary holes and defers the permission findings; the security-advisory API returns empty; searches surface only the predating historical fix. Verified live at this commit: nonInteractiveCli.ts has zero StopFailure/hook references, client.ts fires StopFailure only at the two loop-detection early returns (the API-error early return has no fire), and the ACP daemon loop detectors funnel to warn + telemetry with no hook fire. — Failure scenario: the merged public doc localizes two live paths in packages/core/src/hooks/ where failures never fire the failure hook — exactly where failure-blindness is exploitable by anyone who wants abuse to stay unobserved by StopFailure-keyed escalation — with no fix tracked. Suggested fix: file the tracking artifact (issue/advisory) and cite it, or withhold class and mechanism the way the Context paragraph already does for the Round-1 findings — count plus "adjacent-class siblings of a historical fix" carries the design's argument without localizing the hole.
中文说明
[Critical] R7-29:本句披露了第二轮两个漏触发 Critical 的类别 + 机制 + 模块(headless 模式下 API 错误结束回合时 failure hook 从不触发;ACP 会话的循环检测时同样不触发),而保留准则(27–32 行)要求对未修补且无公开跟踪产物的发现保留——这两个发现没有任何跟踪产物:#8396 只覆盖四个信任边界漏洞并推迟权限类发现;security-advisory API 返回空;检索只找到早于复现的历史修复。已在本提交核实仍然存在:nonInteractiveCli.ts 对 StopFailure/hook 零引用,client.ts 仅在两处循环检测早退处触发 StopFailure(API 错误早退处无触发),ACP daemon 循环检测器只走 warn + telemetry、不触发 hook。——失败场景:合入后的公开文档会在无任何修复跟踪的情况下,定位 packages/core/src/hooks/ 中两处 failure hook 从不触发的活路径——正是想让滥用不被 StopFailure 升级机制观测到的人可利用的失败盲区。建议修复:立跟踪产物(issue/公告)并引用;或像 Context 段对第一轮发现那样隐去类别与机制——数量加"历史修复的邻类兄弟"足以承载设计论点,无需定位漏洞。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| other's: from the review copy, the process-wide memo (a consumer | ||
| naming the same path twice pays once) and the git deadline (a hang | ||
| must still end); from the team-memory copy, the representative |
There was a problem hiding this comment.
[Critical] R7-2: The consolidation lifts the review copy's process-wide memo into the shared helper consumed by all three call sites, but the design's own freshness mechanisms — remedy verification ("the probe re-run must answer 'ignored'") and the write-time re-check — re-ask the same (worktree, path) key in the same process and require a fresh answer. Verified: isGitIgnored in test-plan.ts memoizes in a module-level Map keyed worktree+path for the process lifetime, never invalidated; no invalidation rule appears anywhere in this document. — Failure scenario: (1) default first-run repo: plan-time probe answers "not ignored" and memoizes false; user applies the .git/info/exclude remedy; the spec's probe re-run returns the memoized false forever, so the remedy can never verify and the refusal the doc declares "not a dead end" becomes one. (2) If the audits dir is ignored at plan time, true memoizes; a mid-run rule edit / branch switch / upstream merge removing coverage is invisible to the write-time re-run, and the report "that will quote exploitable code" lands in a repo that can now commit it. Blast radius: team-memory's probe gains memoization it never had — stale shareability until restart. Suggested fix: keep the shared helper fresh-by-default and let the memo live in the review-side caller; if it stays in the helper, state an invalidation rule covering the remedy re-run and the write-time re-check, and state that team-memory keeps fresh semantics.
中文说明
[Critical] R7-2:整合方案把 review 副本的进程级 memo 抬进三个调用点共享的 helper,但设计自己的新鲜度机制——补救验证("probe 重跑必须回答 'ignored'")与写入时复查——会在同一进程内重新询问同一 (worktree, path) 键并要求新答案。已核实:test-plan.ts 的 isGitIgnored 用模块级 Map 按 worktree+path 键控、进程生命周期内从不清除;全文没有任何失效规则。——失败场景:(1) 默认首跑仓库:plan 期 probe 回答"未被忽略"并 memo 下 false;用户应用 .git/info/exclude 补救;规格要求的 probe 重跑永远返回 memo 的 false,补救永远无法验证,文档宣称"不是死胡同"的拒绝变成死胡同。(2) 若 audits 目录在 plan 期已被忽略,true 被 memo;运行中规则编辑/切分支/上游合并撤销覆盖时,写入时重跑对此不可见,"会引用可利用代码"的报告落在一个现在可以提交它的仓库里。波及面:team-memory 的 probe 获得了它从未有过的 memo——共享性状态过期直到重启。建议修复:共享 helper 默认保持新鲜,memo 留在 review 侧调用方;若留在 helper 内,写明覆盖补救重跑与写入时复查的失效规则,并声明 team-memory 保持新鲜语义。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| for untracked files, names plus contents: | ||
| `git ls-files --others -- <audited path>`, with no | ||
| `--exclude-standard`, so the list covers the gitignored-untracked |
There was a problem hiding this comment.
[Critical] R7-3: The sidecar captures untracked files via git ls-files --others WITHOUT --exclude-standard, so it re-includes exactly the trees (dist/, node_modules/, .venv/, target/, .env) the enumeration section excludes "from enumeration outright", and copies their contents next to the report. Probe-verified in a scratch repo: --others lists dist/bundle.js, node_modules/lib/x.js, and .env where --exclude-standard returns empty. The subject gate cannot catch this — excluded directories contribute zero subject lines — and the drift comparison inherits the over-capture. — Failure scenario: /audit packages/core (the doc's own running example) on any post-build checkout copies the entire dist/ tree and any package-local node_modules/ — tens of thousands of files, potentially gigabytes — next to the report, and every drift checkpoint re-compares that tree; any gitignored sensitive file under the path is consolidated into one report-adjacent copy. Suggested fix: scope the sidecar's untracked capture (and the drift untracked comparison) to the plan-files enumerated subject set — keeping the gitignored-vendored-source class the raw command exists to cover while excluding the build/dependency trees — or at minimum apply the same directory-name exclusions.
中文说明
[Critical] R7-3:sidecar 用不带 --exclude-standard 的 git ls-files --others 捕获未跟踪文件,因此会重新纳入枚举一节"直接排除"的那些树(dist/、node_modules/、.venv/、target/、.env),并把它们的内容复制到报告旁边。已在临时仓库实测:--others 会列出 dist/bundle.js、node_modules/lib/x.js 与 .env,而 --exclude-standard 返回空。subject 门控拦不住——被排除目录贡献零行 subject——漂移比较也会继承这份过度捕获。——失败场景:在任何构建后的检出上跑 /audit packages/core(文档自己的示例),会把整个 dist/ 树与包内 node_modules/(数万文件、可能 GB 级)复制到报告旁边,每个漂移检查点都要重新比较这棵树;路径下任何被 gitignore 的敏感文件都会被聚合成一份报告旁的副本。建议修复:把 sidecar 的未跟踪捕获(与漂移的未跟踪比较)限定到 plan-files 枚举出的 subject 集——保留该原始命令为之而生的 gitignored vendored 源码类,同时排除构建/依赖树——至少也套用同一套目录名排除。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| `.gradle/`, `obj/`, `Pods/`, `.tox/`, `vendor/bundle/` — is excluded from | ||
| enumeration outright, by directory name anywhere under the audited path | ||
| (including the path root), and is never an audit subject. `test` is the only |
There was a problem hiding this comment.
[Suggestion] R7-6: The name-based directory exclusion applies anywhere under the audited path but — unlike every other skip/exclusion class in this design — carries no visibility: an excluded nested directory appears in no header or walks record, so real source under a colliding name drops out of the audit silently; where the exclusion empties the subject set at the root, the refusal is indistinguishable from a genuinely empty directory. — Concrete cost: a module keeping real source in a nested directory named build/, out/, target/, or coverage/ (e.g. tools/build/, the pypa/build layout src/build/) is never enumerated, never counted toward either gate arm, never walked — while the report reads as a full walk of a module with a subtree silently omitted. Suggested fix: route name-excluded directories through the same visibility discipline as the other skip classes — record excluded directory paths in the header's walks record, and name the exclusion in the refusal message when it is what emptied the subject set.
中文说明
[Suggestion] R7-6:按目录名的排除在被审计路径下任何位置生效,但与本设计其他所有跳过/排除类不同,它没有任何可见性:被排除的嵌套目录不出现在 header 或 walks 记录中,撞名的真实源码会静默掉出审计;当排除在根目录清空 subject 集时,拒绝信息与真正的空目录无法区分。——具体代价:把真实源码放在名为 build/、out/、target/、coverage/ 的嵌套目录里的模块(如 tools/build/、pypa/build 布局的 src/build/)永远不会被枚举、不计入任何门控臂、不会被走查——而报告读起来像对该模块的完整走查,一棵子树被静默遗漏。建议修复:让按名排除的目录走与其他跳过类相同的可见性纪律——在 header 的 walks 记录中记下被排除的目录路径,并在拒绝信息因它清空 subject 集时点名该排除。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| equally effective everywhere — tracked `.gitignore` patterns outrank | ||
| it, so a tracked re-include negation (`.qwen/*` then `!.qwen/audits/` | ||
| — the pattern shape this repo itself uses) beats an exclude entry and |
There was a problem hiding this comment.
[Suggestion] R7-20: Branch (b)'s premise — a tracked re-include negation always beats a .git/info/exclude entry — holds only when the tracked negation matches the representative report FILE. Probe-verified (git check-ignore exit codes): with .qwen/* + !.qwen/audits/ (dir-only re-include), adding .qwen/audits/** to .git/info/exclude flips the report path from "not ignored" to "ignored" — the remedy works; only the full dir+** shape is inert. The doc carries the dir-form subtlety three paragraphs earlier ("a directory-form re-include negation only applies to paths git knows are directories") yet branch (b) ignores it, and the Verification list hardens the over-broad claim. — Concrete cost: on a dir-only re-include repo (the shape users commonly write — this repo's own team-memory warning coaches them to add the ** half because they miss it), the plan withholds the zero-footprint exclude remedy it elsewhere prefers and offers only the outside-repo fallback or removing the tracked negation, which dirties the checkout and edits shared config. Suggested fix: restate the premise as shape-dependent and offer the exclude entry first where a dir-only re-include leaves the file exposed (verified by the probe re-run); amend the Verification item to assert both shapes.
中文说明
[Suggestion] R7-20:分支 (b) 的前提——被跟踪的 re-include 取反总是压过 .git/info/exclude 条目——只在被跟踪取反能匹配到代表性报告"文件"时成立。已实测(git check-ignore 退出码):.qwen/* + !.qwen/audits/(仅目录形取反)时,向 .git/info/exclude 添加 .qwen/audits/** 会把报告路径从"未被忽略"翻转为"被忽略"——补救有效;只有目录+** 的完整形态才使 exclude 条目无效。文档三段之前刚写过目录形的细节("目录形 re-include 取反只对 git 已知是目录的路径生效"),分支 (b) 却忽略了它,Verification 清单还把过宽的结论固化了下来。——具体代价:在仅目录形 re-include 的仓库上(用户常写的形态——本仓库自己的 team-memory 警告就是因为用户总漏掉 ** 那一半才教他们补上),方案会弃用它别处偏爱的零足迹 exclude 补救,只提供仓外回退或删除被跟踪取反——后者会弄脏检出并修改共享配置。建议修复:把前提改写为依赖形态;在仅目录形 re-include 使文件暴露时优先提供 exclude 条目(以 probe 重跑验证);Verification 条目断言两种形态。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| the estimate — split between the priced 8-dimension core and | ||
| the unpriced additions (6a, verification, high-tier rounds), so the |
There was a problem hiding this comment.
[Suggestion] R7-21: The consumption-record split enumerates the unpriced buckets as "(6a, verification, high-tier rounds)" in both its occurrences (here and the Budget-ceiling overshoot record), but high = medium + 6b/6c + rounds — the two persona agents have no bucket. — Concrete cost: on any high-tier run, 6b/6c token consumption either lands in the priced 8-dimension core bucket — contaminating the per-line-rate delta the split exists to isolate — or is dropped, and the recorded split no longer sums to the run's actual consumption; the contamination bites precisely on the unmeasured tier whose "total ceiling waits for its first measurement". Suggested fix: add 6b/6c to the unpriced-additions enumeration in both occurrences (e.g. "(6a, verification, high-tier personas, high-tier rounds)").
中文说明
[Suggestion] R7-21:消耗记录的拆分在两处(此处与 Budget ceiling 的超限记录)都把未计价桶枚举为"(6a、verification、high 档轮次)",但 high = medium + 6b/6c + 轮次——两个 persona agent 没有桶。——具体代价:任何 high 档运行中,6b/6c 的 token 消耗要么落进已计价的 8 维核心桶——污染该拆分本要隔离的每行费率 delta——要么被丢弃、记录的拆分不再与运行实际消耗求和一致;污染恰恰落在"总上限等待首次测量"的未实测档位上。建议修复:在两处未计价枚举中加入 6b/6c(如"(6a、verification、high 档 personas、high 档轮次)")。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| verification shard, never pre-confirmed past it); the event/lifecycle | ||
| detection heuristic on synthetic event and non-event modules — the two | ||
| measured modules are ready-made fixtures (permissions: no event surface |
There was a problem hiding this comment.
[Suggestion] R7-25: The unit list omits the substantive-return/whiff machinery and the dry-round predicate the document pins as convergence-critical in two places: bare return → whiff → relaunched once → twice-whiffed = not audited; "a round containing a twice-whiffed auditor is not dry and cannot end the loop on silence"; stop after two consecutive dry rounds; 5-round cap reported as a cap. A grep for whiff|substantive-return|dry returns zero hits in the Verification section. — Concrete cost: an implementation regression that accepts a bare return as an evidence-bearing receipt ships "walks completed: security, 0 findings" — precisely the misreading the walks record exists to prevent; a regression counting a twice-whiffed round as dry ends the high-tier loop early on silence — no listed test fires for either. Suggested fix: add unit items — whiff classification (bare vs evidence-bearing return), relaunch-once-then-record-not-audited, and the dry-round predicate (a twice-whiffed auditor makes its round not dry; stop only on two consecutive dry rounds; 5-round cap reported as a cap, not convergence).
中文说明
[Suggestion] R7-25:单测清单遗漏了文档在两处钉死为收敛关键的实质性返回/whiff 机制与 dry 轮判定:裸返回 → whiff → 重启一次 → 两次 whiff = 未审计;"含两次 whiff 审计员的轮次不算 dry、不能以沉默结束循环";连续两轮 dry 后停止;5 轮上限按上限而非收敛报告。对 whiff|substantive-return|dry 的 grep 在 Verification 一节零命中。——具体代价:把裸返回当作带证据回执的实现回归会放行"walks completed: security, 0 findings"——正是 walks 记录要防止的误读;把两次 whiff 的轮次计为 dry 的回归会让 high 档循环提前在沉默中结束——两种回归都没有已列测试会触发。建议修复:增加单测条目——whiff 分类(裸返回 vs 带证据返回)、重启一次后登记未审计、以及 dry 轮判定(两次 whiff 的审计员使其所在轮次不算 dry;仅在连续两轮 dry 时停止;5 轮上限按上限而非收敛报告)。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| - **Drift protection:** re-checks the audited path, not the | ||
| repository, before each high-tier round, before verification, and | ||
| at write time — before anchor resolution, alongside the write-time |
There was a problem hiding this comment.
[Suggestion] R7-26: Drift protection is path-scoped to the audited path ("re-checks the audited path, not the repository"), but the mandatory 1c cross-file tracer's findings are claims about repo callers OUTSIDE that path (1c walks "module's exports × repo callers", including "early-return, error, and abort paths in the callers"). Drift in those callers is never re-checked, never marked, never stopped — falling through both arms of the design's own drift invariant; the degrade arm's justification ("nothing the run has produced refers to that file") is precisely false for caller files 1c deep-read and reported on. — Concrete cost: /audit packages/core/src/hooks while the user edits a CLI-side caller mid-run; 1c's confirmed finding "callers never fire event E on the error path" is refuted by that edit; no checkpoint looks at caller files, write-time anchor resolution validates only the module-side snippet, and the report ships the stale caller-behavior claim with no header mark — in precisely the finding class this doc names as its headline. Suggested fix: name the drift fate of the files 1c deep-reads outside the audited path — extend the comparison to 1c's registered caller set (the names exist; 1c registers them), or state in the walks record that cross-file claims about out-of-path callers are drift-unprotected.
中文说明
[Suggestion] R7-26:漂移保护按被审计路径限定("复查被审计路径,而非整个仓库"),但必选的 1c 跨文件追踪器的发现是关于该路径之外的仓库调用方的断言(1c 走查"模块导出 × 仓库调用方",包括"调用方中的早退、错误与中止路径")。这些调用方的漂移永远不会被复查、标记或停止——从设计自身漂移不变式的两臂之间漏过;降级臂的理由("运行产出的任何内容都不引用该文件")对 1c 深读并报告过的调用方文件恰为假。——具体代价:用户在运行中编辑某个 CLI 侧调用方时跑 /audit packages/core/src/hooks;1c 已确认的发现"调用方在错误路径上从不触发事件 E"被该编辑推翻;没有任何检查点看调用方文件,写入时锚点解析只验证模块侧片段,报告带着过期的调用方行为断言放行且 header 无任何标记——恰是本文档点名为头条的发现类别。建议修复:点名 1c 在被审计路径外深读文件的漂移命运——把比较扩展到 1c 登记的调用方集合(名字已有,1c 会登记它们),或在 walks 记录中声明关于路径外调用方的跨文件断言不受漂移保护。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| → not detected; hooks: lifecycle/event-dispatch → detected) — with the | ||
| false-negative outcome named as the case the header flag exists to | ||
| disclose. |
There was a problem hiding this comment.
[Suggestion] R7-30: The unit list omits the output-marking rules the design pins as the only thing standing between a reader and a named misreading: the unverified label ("every finding that did not pass a verification shard is labeled unverified — the low tier's findings, and the findings of any run whose verification did not complete (a drift stop, an abort) — so they never print identically to verified ones") and the evidence-tier caps (declined opt-in / read-only degradation "every evidence tier capped accordingly"; cross-file findings capped below the end-to-end tier). — Concrete cost: a report-writer regression prints low-tier findings — a tier the doc says "survives that argument only because it claims no audit standing: labeled unverified, capped, sold as triage" — or a drift-stop partial run's findings with the same confirmed rendering as shard-verified findings, or a code-read adjudication wearing a "unit probe" tier; the reader takes unverified or tier-capped findings for verified confirmation — precisely the "never print identically" misreading the label exists to prevent — and no listed test fires. Suggested fix: add units for the report writer's unverified label on low-tier findings and on drift-stop/abort partial reports (asserted distinguishable from verified rendering), and the evidence-tier cap rules (declined opt-in and cross-file caps).
中文说明
[Suggestion] R7-30:单测清单遗漏了设计钉死为读者与点名误读之间唯一防线的输出标记规则:未验证标签("任何未通过验证分片的发现都标记为未验证——low 档的发现,以及任何验证未完成的运行(漂移停止、中止)的发现——使它们永不与已验证发现打印得相同")与证据层级上限(拒绝 opt-in / 只读降级时"每个证据层级相应封顶";跨文件发现以低于端到端的层级为上限)。——具体代价:报告编写器的回归把 low 档发现——文档说该档"得以成立恰因它不声称审计地位:标记未验证、封顶、作为分诊出售"——或漂移停止的部分运行的发现以与分片验证发现相同的确认样式打印,或把代码阅读裁决穿戴成"unit probe"层级;读者会把未验证或被封顶层级的发现当作已验证确认——正是该标签要防止的"打印得相同"误读——没有任何已列测试会触发。建议修复:为报告编写器在 low 档发现与漂移停止/中止部分报告上的未验证标签(断言与已验证渲染可区分)、以及证据层级封顶规则(拒绝 opt-in 与跨文件上限)增加单测。
— qwen3.8-max via Qwen Code /review (v0.21.5)
|
🤖 Addressed the latest review feedback (round 4/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 4/100 轮)。改动内容与我反驳保留之处如下: Round-7 review feedback addressed — PR #8397All 18 findings (4 Critical, 14 Suggestion) were verified against the current Critical findings
Suggestions
Notes
Verification
中文说明第 7 轮评审意见处理 — PR #8397全部 18 条发现(4 条 Critical、14 条 Suggestion)均已先对照当前 HEAD Critical 发现
Suggestion 发现
说明
验证
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.
[Critical] R5-1 (round-5 blocker, still stands): the orphaned-disclosure concern persists in substance — the class + mechanism shape + module of the unpatched Round-1 permissions finding remain public (roster table 'two-splitter root cause', Dedup 'a splitter divergence, its security consequence') with no tracking artifact; carried by the inline finding R8-1 at the roster table.
— qwen3.8-max via Qwen Code /review (v0.21.5)
| two unique Criticals came from exactly this walk — both fire-misses, both | ||
| adjacent-class siblings of a historical fix that had covered only one UI |
There was a problem hiding this comment.
[Critical] R7-29 (round-7 blocker — still stands): this passage discloses the class (fire-miss), a mechanism fragment ("adjacent-class siblings of a historical fix that had covered only one UI path"), and — with "both fire-misses on exactly those paths" below — the path class (callers' early-return/error/abort) of two findings the same sentence declares unpatched and uncited by any public tracking artifact, violating the doc's own Context withholding criterion (lines 27-32). The historical fix is publicly identifiable (commit 34a3d46 / PR (7592)), so a reader can diff it and enumerate the adjacent uncovered firing sites in packages/core/src/hooks/ (named at line 49). — Failure scenario: the merged public doc localizes two live, untracked fire-miss paths before any fix lands → a reader reconstructs the payload surface from public history in minutes.
Suggested fix: strip the class/mechanism/path fragments ("both withheld under the Context section's criterion") and reword the budget-rule citation so the error-path-starvation argument stands without naming the withheld findings' class or location — or file the tracking artifact first and cite it.
中文说明
[Critical] R7-29(第 7 轮阻断项——仍然存在):本段披露了同类句子自己声明为"未修补且无任何公开跟踪产物引用"的两个发现的类别(fire-miss 漏触发)、机制片段("一个只覆盖了一条 UI 路径的历史修复的邻类兄弟"),并借下文 "both fire-misses on exactly those paths" 披露了路径类别(调用方的早退/错误/中止路径)——违反了 Context 节自己的保留准则(27-32 行)。历史修复可公开定位(提交 34a3d46 / PR (7592)),读者只需 diff 它即可枚举 packages/core/src/hooks/(第 49 行点名)中相邻的未覆盖触发点。——失败场景:合入后的公开文档在修复立项前定位两条活的、无人跟踪的漏触发路径 → 读者几分钟内即可从公开历史重建利用面。
建议修复:删去类别/机制/路径片段(改写为"两者均按 Context 节准则保留"),并重写预算规则的引用,使"错误路径饥饿"论证无需点名被保留发现的类别或位置即可成立——或者先立跟踪产物并在此引用。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| | 1a line-by-line | every file, every line | unchanged checklist | | ||
| | 1c cross-file tracer | module's exports × repo callers | produced the unique Criticals in both rounds; mandatory | | ||
| | 2 security | threat model first, then the checklist | "name the adversary inputs" produced R2's trust-boundary Criticals | | ||
| | 3a/3b/3c quality | module vs codebase | the roster's three existing quality slices (3a reuse, 3b altitude/abstraction fit, 3c consistency); 3a's "does this exist already" found the two-splitter root cause | |
There was a problem hiding this comment.
[Critical] R8-1 (also carries round-5 blocker R5-1 in substance): this cell discloses the mechanism shape of the experiment's most severe finding — "the two-splitter root cause" (restated in the Dedup section as "a splitter divergence, its security consequence, its missing test") — while the Context section declares that finding "withheld in full from this document, class and mechanism included" because it is unpatched and uncited. The Round-1 module is named at line 14 (packages/core/src/permissions/), and public history shows the diverging-splitters pattern to continue from (commit 548863d / PR (7864): the sibling splitter already handled a boundary the permission one missed). If the referenced finding were instead the already-merged case, the doc's "unpatched, no public artifact" claim would be false — either way a passage is wrong. R5-1's core demand — a tracking artifact or withheld class/location detail — remains unmet: no issue/advisory cites it and PR (8396) explicitly defers the permission findings. — Failure scenario: a reader gets module + mechanism shape + discovery strategy for an unpatched Critical and reconstructs a working variant before any fix is tracked.
Suggested fix: apply the doc's own criterion — replace the mechanism references with the withheld status ("contributed to findings withheld under the Context criterion"; restate the dedup example generically), or land a public tracking artifact (issue / SECURITY.md advisory) first and cite it here.
中文说明
[Critical] R8-1(实质上同时承载第 5 轮阻断项 R5-1):此表格单元披露了实验中最严重发现的机制形态——"the two-splitter root cause"(去重一节又写作 "a splitter divergence, its security consequence, its missing test")——而 Context 节声明该发现"因未修补且无公开产物引用而从本文档完整保留,类别与机制均不披露"。第一轮模块在第 14 行点名(packages/core/src/permissions/),公开历史中正好有可继续外推的"双 splitter 分歧"样本(提交 548863d / PR (7864):兄弟 splitter 已处理某个权限 splitter 遗漏的边界)。若此处引用的其实是已合入的那个案例,则文档"未修补、无公开产物"的说法反而为假——两种读法下总有一处是错的。R5-1 的核心诉求——先立跟踪产物或隐去类别/位置——仍未满足:无任何 issue/公告引用,PR (8396) 明确推迟权限类发现。——失败场景:读者获得模块 + 机制形态 + 发现策略,在任何修复被跟踪之前重建出可用变体。
建议修复:套用文档自己的准则——把机制引用改为保留状态表述("walk 对按 Context 准则保留的发现有所贡献";去重示例泛化重写),或先立公开跟踪产物(issue / SECURITY.md 公告)并在本句引用。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| reserved-prefix files as audit-owned residue: excluded from subjects, and | ||
| surfaced at plan time for deletion with the user's confirmation — and the |
There was a problem hiding this comment.
[Critical] R8-2: reserved-prefix files are excluded from the audit subject set by name pattern, with the only surfacing a plan-time deletion confirmation framed as residue cleanup. The reserved prefix must be stable and documented (it exists to recognize residue from a previous killed run), so a malicious vendored module — the design's flagship target — can name its payload with it and escape every walker. Both confirmation branches favor the attacker: confirming deletes the evidence before the audit under a residue-cleanup framing; declining leaves it permanently out of scope. Unlike directory-name exclusions, which "ride into the header's walks record by path" precisely so drops are legible, this exclusion leaves no walks-record or header trace — the shipped report reads "every walk completed" with nothing naming the excluded file, against the doc's own standard that "walks completed" cannot overstate coverage. — Failure scenario: /audit on a hostile vendored module shipping <reserved-prefix>-payload.ts → plan-files excludes it from subjects, no walker sees it, and the report says every walk completed.
Suggested fix: do not let a name pattern remove files from audit scope — keep reserved-prefix files walked subjects, or gate residue recognition on a run manifest the audit itself wrote; and record every residue exclusion in the header's walks record.
中文说明
[Critical] R8-2:保留前缀文件按名称模式被排除出审计主体集,唯一的呈现是一个以"残留清理"为框架的 plan 期删除确认。保留前缀必须稳定且会被文档公开(它的存在就是为了识别上一次被杀运行留下的残留),因此恶意 vendored 模块——本设计的旗舰目标——可以把 payload 命名为该前缀从而躲过所有 walker。确认对话框的两个分支都对攻击者有利:确认 → 证据在审计开始前以"清理残留"的名义被删除;拒绝 → 永久留在审计范围之外。与目录名排除不同(后者"按路径写入 header 的 walks record"正是为了让排除可见),此排除不在 walks record 或 header 留下任何痕迹——最终报告读作"所有 walk 已完成",却无一字提及被排除文件,违反文档自己"walks completed 不得夸大覆盖"的标准。——失败场景:对携带 <保留前缀>-payload.ts 的恶意 vendored 模块运行 /audit → plan-files 将其排除出主体集,没有任何 walker 看到它,报告却声称所有 walk 均已完成。
建议修复:不要让名称模式把文件移出审计范围——保留前缀文件仍作为被 walk 的主体,或把残留识别改为基于审计自己写入的运行清单;并把每一次残留排除记入 header 的 walks record。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| against the audited files at write time, refusing or downgrading any | ||
| finding whose snippet does not resolve; an audit posts nothing, so a |
There was a problem hiding this comment.
[Critical] R8-3: write-time anchor resolution is defined against "the audited files" only, but the design's headline cross-file findings anchor in caller files the same document places outside the audited path: 1c's brief is "module's exports × repo callers", the event walk hunts fire-misses "in the callers", and Context calls these "the two Criticals nobody else could". The drift section elsewhere presumes caller-anchored findings are legitimate ("drift in a deep-read caller carrying anchored findings stops the run like a walked subject"). As written, those snippets cannot resolve "against the audited files", so the gate refuses or downgrades exactly the findings the design exists to produce — and the Verification entry ("synthetic findings … do not resolve against the audited fixtures") pins the same reading, so the specified tests cannot catch it. — Failure scenario: 1c finds a fire-miss in a caller's error path outside the audited directory (the Round-2 unique-Critical class, ~35% of the arm's tokens) → at write time its snippet cannot resolve and the finding is refused/downgraded: the audit's unique value is structurally discarded by its own validation gate.
Suggested fix: extend the write-time resolution set to the registered deep-read callers (whose content the drift arm already snapshots), and record write-time refusals in the header rather than dropping them silently.
中文说明
[Critical] R8-3:写入时锚点解析只对"被审计文件"进行,但本设计的招牌跨文件发现恰恰锚定在同一文档明确置于审计路径之外的调用方文件上:1c 的 brief 是"模块导出 × 仓库调用方",事件走查在"调用方"中追查漏触发,Context 称之为"别人都找不到的两个 Critical"。漂移一节 elsewhere 又假定调用方锚定的发现是合法产物("深度阅读过且携带锚定发现的调用方发生漂移则停止运行,如同被 walk 的主体")。按字面,这些片段无法"在被审计文件上"解析,因此该 gate 会拒绝或降级正是本设计为之存在的那类发现——而 Verification 条目("合成发现……无法在审计 fixture 上解析")把这个读法钉死,规划中的测试也抓不到。——失败场景:1c 在审计目录之外某个调用方的错误路径上发现漏触发(第二轮独有 Critical 类别,占该臂约 35% token)→ 写入时片段无法解析,发现被拒绝/降级:审计的独特价值被自己的校验门结构性丢弃。
建议修复:把写入时解析集合扩展到已登记的深读调用方(漂移臂已对它们做内容快照),并把写入时拒绝记入 header 而非静默丢弃。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| other finding. Files 1c deep-reads outside the audited path join the | ||
| comparison as a per-file content-hash snapshot taken at the same |
There was a problem hiding this comment.
[Critical] R8-4: out-of-path callers registered by 1c get their first content-hash snapshot "at the same checkpoints" (before each high-tier round, before verification, at write time) — the spec provides no run-start or registration-time snapshot for them, unlike in-path files, which get run-start captures. On a medium run (no high-tier rounds) the checkpoints are before-verification and at-write-time, so a caller edited during fan-out — the only window in which 1c deep-reads callers, in a run the doc says lasts hours while the user is actively in the module — is first hashed post-edit: the baseline absorbs the edit and no later checkpoint sees drift. — Failure scenario: during a medium run's fan-out, the user edits a caller file 1c deep-read → the first checkpoint hashes the post-edit content as baseline → 1c's finding quotes caller code that no longer exists while the header shows the registered-caller arm ran.
Suggested fix: take each registered caller's baseline content-hash at registration (deep-read) time, or fold the caller set into the run-start snapshot.
中文说明
[Critical] R8-4:1c 登记的路径外调用方首次内容哈希快照取于"同一批检查点"(每个 high 轮次前、验证前、写入时)——规格没有为它们在运行开始或登记时建立快照,而路径内文件有运行开始捕获。medium 运行(无 high 轮次)的检查点只有验证前与写入时,因此在 fan-out 期间——1c 深读调用方的唯一窗口,且文档自己说用户此时正活跃在该模块中、运行长达数小时——被编辑的调用方首次哈希发生在编辑之后:基线吸收了编辑,之后任何检查点都看不到漂移。——失败场景:medium 运行 fan-out 期间用户编辑了 1c 深读过的调用方文件 → 首个检查点把编辑后的内容当作基线 → 1c 的发现引用着已不存在的调用方代码,而 header 显示调用方漂移臂已经运行。
建议修复:在登记(深读)时即取得每个调用方的基线内容哈希,或把调用方集合并入运行开始快照。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| filtered to the files `plan-files` enumerates, subjects and test | ||
| corpus alike, so the capture inherits the enumeration's |
There was a problem hiding this comment.
[Suggestion] R8-14: the dirty-run sidecar's untracked capture inherits only the enumeration's directory-name exclusions; the uncoverable-subject class (binary files, over-maxLineChars lines) stays enumerated as subjects while being excluded from walking and the gate, so its content is copied wholesale into .qwen/audits/ and re-compared at every drift checkpoint, unbounded by any gate arm (the gate counts lines, not bytes). The copy serves no stated purpose: uncoverable files are never walked, so no finding can anchor in them — the copy's own rationale is anchor resolvability. This is the sibling state of the hazard the filter's rationale names ("copying tens of thousands of build-output files the subject gate cannot catch … and re-comparing them at every drift checkpoint"). — Failure scenario: a dirty run over a vendored target carrying a large untracked binary (model weights — a common vendored layout) → recorded as an uncoverable subject contributing ~zero gate lines, yet it gets a full content copy into .qwen/audits/ (multi-GB, no gate arm can catch it) and every drift checkpoint re-compares it.
Suggested fix: state that the sidecar filter also inherits the uncoverable-subject exclusion (names recorded, no content copy), with the same walks-record visibility as the directory-name exclusions.
中文说明
[Suggestion] R8-14:dirty-run sidecar 的未跟踪捕获只继承枚举的目录名排除;不可覆盖主体类(二进制文件、超过 maxLineChars 的长行文件)仍被枚举为主体,只是被排除出 walk 与门限,因此其内容会被整体复制到 .qwen/audits/ 并在每个漂移检查点重新比较,不受任何门限臂约束(门限按行数计,不按字节计)。该复制没有已声明的用途:不可覆盖文件从不被 walk,没有任何发现能锚定其中——而复制自己的理由恰恰是锚点可解析性。这正是过滤器理由所点名的同类危害("复制数万构建产物文件——主体门限拦不住……并在每个漂移检查点重新比较")的兄弟形态。——失败场景:对携带大型未跟踪二进制(模型权重——常见的 vendored 布局)的目标做 dirty 运行 → 该文件被记为贡献约零门限行的不可覆盖主体,却仍被完整复制到 .qwen/audits/(GB 级,无门限可拦),每个漂移检查点都要重新比较。
建议修复:明说 sidecar 过滤器同样继承不可覆盖主体排除(只记录文件名、不复制内容),并赋予与目录名排除相同的 walks-record 可见性。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| findings that quote the module verbatim, and it merges copies before | ||
| verification, so a finding suppressed there never reaches a shard; round |
There was a problem hiding this comment.
[Suggestion] R8-15: the dedup clusterer is the one post-discovery stage with no completeness receipt. Every other suppression point carries one — walkers get the whiff check, verification gets the unverified label, reverse auditors get the not-audited flag — but a finding the clusterer fails to place in a cluster vanishes with no trace: it reaches no shard, appears in no report, and the walks record shows all walks completed. The doc designates the clusterer a preamble consumer precisely because "a finding suppressed there never reaches a shard" — suppression there is total, and it happens after measured redundancy has already passed. The Verification list pins merge behavior, max-severity, and the no-skip rule, but nothing asserts every input finding lands in exactly one cluster; since clusters carry their members, a partition check (members sum == input count) is feasible and omitted. — Failure scenario: an LLM misjudgment treats finding X as absorbed by cluster Y without carrying it as a member, or a preamble-defeated clusterer quietly drops a security finding → it reaches no shard, appears in no report, and the walks record reads complete — indistinguishable from the finding never existing.
Suggested fix: specify the completeness invariant (every input finding is a member of exactly one cluster; absorptions recorded in the header) and add a matching unit entry to Verification.
中文说明
[Suggestion] R8-15:去重聚类器是发现之后唯一没有完备性回执的阶段。其他每个抑制点都有回执——walker 有 whiff 检查、验证有 unverified 标签、反向审计员有 not-audited 标记——但聚类器未能归入任何簇的发现会无痕消失:到不了分片、进不了报告,而 walks record 显示所有 walk 均已完成。文档把聚类器列为前言消费者,恰恰因为"在那里被抑制的发现永远到不了分片"——那里的抑制是彻底的,且发生在实测冗余已经通过之后。Verification 清单钉住了合并行为、最高严重度与 no-skip 规则,但没有任何条目断言每条输入发现恰好落入一个簇;既然簇携带其成员,划分校验(成员总数 == 输入发现数)是可行的,却被遗漏。——失败场景:LLM 误判把发现 X 当作已被簇 Y 吸收却不把它带为成员,或被前言击败的聚类器悄悄丢弃一条安全发现 → 它到不了分片、进不了报告、walks record 读作完整——与这条发现从未存在无法区分。
建议修复:写明完备性不变量(每条输入发现恰为一个簇的成员;吸收关系记入 header),并在 Verification 中补充对应单测条目。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| resolve uniquely, resolve ambiguously, and do not resolve against the | ||
| audited fixtures, asserting the refuse/downgrade behavior at write |
There was a problem hiding this comment.
[Suggestion] R8-16: the design section defines write-time refuse/downgrade for exactly one class — snippets that "do not resolve" — while this Verification item asserts refuse/downgrade across a three-way case ("resolve uniquely, resolve ambiguously, and do not resolve"). Under the design section's literal wording an ambiguously-resolving snippet resolves, so it passes validation with its binding unspecified; the per-file drift-stop predicate then keys on whichever file the arbitrary binding landed in. The re-expressed /review machinery has an explicit ambiguity convention (resolve-anchors reports ambiguous/matchCount and tie-breaks on the agent's claimed line), but the doc never says whether /audit inherits it — audit findings may carry no claimed line to tie-break with — or replaces it. — Failure scenario: a fire-miss finding anchored on a repeated emit line appearing in three callers → the snippet resolves (three times), passes validation, binds arbitrarily; the report cites the wrong file:line; an edit to the cited file stops the run while an edit to the finding's actual file hits degrade-and-continue.
Suggested fix: align the design section with this item — refuse or downgrade any snippet that does not resolve uniquely (or state the disambiguation rule that selects the finding's actual occurrence).
中文说明
[Suggestion] R8-16:设计一节只对一类情形定义了写入时拒绝/降级——"无法解析"的片段——而本 Verification 条目断言的是三分情形的拒绝/降级("唯一解析、歧义解析、无法解析")。按设计一节的字面,歧义解析的片段算作"解析成功",于是通过校验且绑定未定;逐文件漂移停止谓词随后以任意绑定落到的文件为准。被再表达的 /review 机制有明确的歧义约定(resolve-anchors 报告 ambiguous/matchCount 并以 agent 声明的行号打破平局),但文档从未说明 /audit 是继承该约定——审计发现可能没有可用来打破平局的声明行号——还是另立规则。——失败场景:锚定在三个调用方中重复出现的 emit 行上的漏触发发现 → 片段解析成功(三次)、通过校验、任意绑定;报告引用错误的文件:行;对被引用文件的编辑使运行停止,而对发现实际所指文件的编辑走降级继续。
建议修复:让设计一节与本条目对齐——拒绝或降级任何非唯一解析的片段(或写明选出发现实际所在位置的消歧规则)。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| alongside the other plan-time refusals, with two probes, run for the audits | ||
| directory and every intermediate directory named above: `git check-ignore` on |
There was a problem hiding this comment.
[Suggestion] R8-17: the local-only property declares it "covers every path the run writes module-derived content to", explicitly naming the plan file and per-agent prompt records under .qwen/tmp/ as carrying "the same exploitable content as the report" — but the enforcement scope "the audits directory and every intermediate directory named above" is ambiguous about .qwen/tmp/ (an intermediate-as-ancestor reading excludes the sibling directory), and the Verification item's local-only guard pins only .qwen/audits/ shapes: representative report file path, index probe on .qwen/audits/, re-include and force-add cases all phrased solely in audits terms. — Failure scenario: a repo where .qwen/ is ignored but .qwen/tmp/ is re-included — the re-include shape this paragraph itself demonstrates with this repo's .gitignore → the .qwen/audits/ probes pass, the run proceeds, and for the hours-long run the plan file and prompt records (quoting the audited module verbatim — exploitable code in a security audit) sit in a committable directory; a git add -A && git commit during the run lands the content "Local-only, verified not assumed" claims cannot reach version control.
Suggested fix: name the covered directories explicitly — the audits directory, its ancestors, and the plan/prompt-record directory (.qwen/tmp/) — and extend this Verification item's re-include/force-add/remedy cases to .qwen/tmp/, or state why it is exempt.
中文说明
[Suggestion] R8-17:local-only 属性声明"覆盖运行写入模块衍生内容的每一条路径",并明确点名 .qwen/tmp/ 下的 plan 文件与逐 agent prompt 记录"携带与报告相同的可利用内容"——但强制范围"audits 目录及上述每一个中间目录"对 .qwen/tmp/ 是模糊的(把"中间目录"读作祖先目录时,兄弟目录被排除在外),且 Verification 条目的 local-only 守卫只钉住 .qwen/audits/ 形态:代表性报告文件路径、针对 .qwen/audits/ 的 index 探针、re-include 与 force-add 用例全部只按 audits 表述。——失败场景:.qwen/ 被忽略但 .qwen/tmp/ 被重新包含的仓库——正是本段用本仓库 .gitignore 演示的 re-include 形态 → .qwen/audits/ 探针通过、运行开始,在长达数小时的运行中,plan 文件与 prompt 记录(逐字引用被审计模块——安全审计中即是可以利用的代码)位于可提交目录;运行期间一次 git add -A && git commit 就把"Local-only, verified not assumed"声称不可能进入版本控制的内容提交了进去。
建议修复:明确点名覆盖的目录——audits 目录、其祖先目录、plan/prompt 记录目录(.qwen/tmp/)——并把本 Verification 条目的 re-include/force-add/补救用例扩展到 .qwen/tmp/,或说明为何豁免。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| An empty subject set refuses at plan time at every tier — "no subject | ||
| files under <path>", mirroring the test-arm refusal: tests route out |
There was a problem hiding this comment.
[Suggestion] R8-18: the empty-subject-set refusal tests the enumerated subject set, but the uncoverable-subject provision (~lines 362-367) removes over-maxLineChars and non-text files from the walked set while leaving them enumerated and line-counted — so a subject set that is entirely uncoverable is non-empty (passes the refusal and the gate at ~zero lines) yet presents zero walkable files, and no plan-time check or confirmation disclosure names that state. The walks record naming uncoverable subjects lives in the report header, written after the spend. — Failure scenario: auditing a directory consisting only of minified bundles or binaries (a compiled-only vendored artifact, which the path-choice rule keeps a subject) → each file counts few gate lines, passing the 9,000 arm; the confirmation presents the roster and estimate with no word that zero files are walkable; every dimension agent then whiffs against the empty walked set and is recorded not-audited — the "walk zero files into an empty report" outcome this refusal exists to prevent, differing only in that plan-files knew at enumeration.
Suggested fix: add the sibling plan-time refusal — refuse with "only uncoverable subjects under " when the walked subject set is empty because every subject is uncoverable — or at minimum surface the uncoverable-only state in the confirmation before consent.
中文说明
[Suggestion] R8-18:空主体集拒绝检验的是被枚举的主体集,但不可覆盖主体条款(约 362-367 行)把超过 maxLineChars 的长行文件与非文本文件移出被 walk 集合的同时仍保留其枚举与行计数——因此一个全部不可覆盖的主体集是非空的(以约零行数通过拒绝与门限),却提供零个可 walk 文件,且没有任何 plan 期检查或确认披露点名这一状态。命名不可覆盖主体的 walks record 位于报告 header,在花费发生之后才写入。——失败场景:审计一个只含压缩 bundle 或二进制的目录(纯编译产物的 vendored 制品,路径选择规则保留其为主体)→ 每个文件只计极少门限行,通过 9,000 臂;确认界面呈现 roster 与估算,只字未提零文件可 walk;随后每个维度 agent 在空的被 walk 集合上 whiff 并被记为未审计——正是本拒绝要防止的"零文件走查出空报告",唯一区别是 plan-files 在枚举时就已经知道。
建议修复:补一个兄弟 plan 期拒绝——当被 walk 主体集因所有主体均不可覆盖而为空时,以 " 下只有不可覆盖主体"拒跑——或至少在确认阶段(同意之前)呈现"全部不可覆盖"状态。
— qwen3.8-max via Qwen Code /review (v0.21.5)
|
🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下: Round-15 summary — PR #8397 (legacy code audit design)All 8 Critical findings (including the round-5 blocker R5-1 and the round-7 Critical findings
Suggestions
Dispositions
VerificationCommands actually run against the resulting tree (docs-only change; no
中文说明第 15 轮总结 — PR #8397(legacy code audit 设计)全部 8 个 Critical 发现(含第 5 轮阻断项 R5-1 与第 7 轮阻断项 R7-29)和全部 12 个 Suggestion 均已对照文档核实,并在同一批修改中处理完毕。所有修复都只改动设计文档本身——不涉及任何源代码。无需处理冲突( Critical 发现
Suggestion
处置
验证针对修改后的树实际运行的命令(纯文档改动;未触碰任何包的源代码,故不适用聚焦 Vitest 运行,也未改动任何 settings 源):
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/模型 |
| - `plan-files` enumerates with a filesystem walk, not `git ls-files` — | ||
| vendored code typically arrives uncommitted and gitignored, and | ||
| `git ls-files` enumerates zero files on exactly that target. |
There was a problem hiding this comment.
[Critical] R9-1: The filesystem-walk enumeration and the mandated "open every enumerated file" unreadable-content provision never mention symlinks — a whole-doc grep for symlink/lstat/readlink/realpath/cycle returns zero matches. A symlink under the audited path — whose flagship target is hostile vendored code — lets enumeration, the walkers, the sidecar content copy, and the drift content-hash snapshots read files outside the path, contradicting the "enumeration is path-bounded" invariant (~lines 423-425). — Failure scenario: a hostile vendored module ships vendor/lib/config.ts -> ../../../../.env: the link is enumerated, opened per the provision (the read follows it), classifies as a text subject, is line-counted into the gate, handed to every dimension agent, quoted verbatim into findings and the report, content-copied into the sidecar, and re-read at every drift checkpoint — leaking arbitrary local file content into a security audit's report. A symlinked directory pulls a whole out-of-path tree into enumeration; a self-link hangs a walk that has no cycle rule. Suggested fix: add a symlink clause beside the binary/over-cap provision — lstat each entry; a symlink (or any entry resolving outside the audited path) is an uncoverable subject, recorded by name only, never content-read; directory symlinks are never descended; sidecar copies and content-hash snapshots never resolve through a link.
中文说明
[Critical] R9-1:filesystem walk 枚举与被强制要求的"打开每个枚举文件"不可读内容条款从未提及符号链接——全文 grep symlink/lstat/readlink/realpath/cycle 零命中。审计路径下的符号链接(本设计的旗舰目标正是恶意 vendored 代码)会让枚举、walker、sidecar 内容副本与漂移内容哈希快照读到路径之外的文件,与"枚举是路径有界的"不变量(约 423-425 行)矛盾。——失败场景:恶意 vendored 模块携带 vendor/lib/config.ts -> ../../../../.env:链接被枚举、按条款被打开(读操作跟随链接)、按名称分类为文本主体、计入门控行数、交给每个维度 agent、被逐字引用进发现与报告、被 sidecar 复制内容、并在每个漂移检查点被重读——安全审计的报告因此泄露任意本地文件内容。符号链接目录会把整个路径外的树拉进枚举;自链接会让缺少环路规则的走查挂起。建议修复:在二进制/超上限条款旁增加符号链接条款——对每个条目 lstat;符号链接(或任何解析到审计路径之外的条目)记为不可覆盖主体,仅记录名称、绝不读取内容;目录符号链接绝不进入;sidecar 副本与内容哈希快照绝不透过链接解析。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| `/audit <path>` resolves a directory (or file set) and runs a new | ||
| subcommand, `qwen audit plan-files <path>`, which plays the role | ||
| `plan-diff` plays for diffs: |
There was a problem hiding this comment.
[Suggestion] R9-9: "(or file set)" advertises an input shape exactly once (grep confirms the single occurrence), and every machinery downstream is directory-shaped and singular: the filesystem walk of files "under the path", the directory-name exclusion "anywhere under the audited path", the subtree-hash drift arm git rev-parse HEAD:<audited path> (one tree-ish), the <path-slug> report name, and the "narrower path" escape valves. — Failure scenario: a user passes several paths — the input the parenthetical sanctions, and not the singular "single files" case that delegates to /review. The implementer must either build scope-widening file-set support (walking each file's parent directory silently enumerates siblings the user never selected, contradicting "the user's path choice is authoritative" and "enumeration is path-bounded") or reject an input the spec advertises. Suggested fix: either define file-set semantics consistently across enumeration, the name exclusions, the gate, the drift arms, and the slug — or delete the parenthetical and state that <path> resolves to exactly one directory (multi-path invocations are multiple bounded runs, per the sub-path rule).
中文说明
[Suggestion] R9-9:"(or file set)"只出现一次(grep 确认仅此一处)宣告了一种输入形态,而其后的所有机制都是目录形态、单数形式的:"路径之下"文件的 filesystem walk、"审计路径下任意位置"的目录名排除、子树哈希漂移臂 git rev-parse HEAD:<audited path>(单个 tree-ish)、<path-slug> 报告名,以及"更窄路径"的逃生阀。——失败场景:用户传入多个路径——这正是括号所允许的输入,而不是委托给 /review 的单数"单文件"情形。实现者要么构建扩大范围的文件集支持(逐个走每个文件的父目录会悄悄枚举用户从未选择的兄弟文件,与"用户的路径选择是权威的"和"枚举是路径有界的"矛盾),要么拒绝一个规格所宣告的输入。建议修复:要么在枚举、名称排除、门控、漂移臂与 slug 各处一致地定义文件集语义——要么删去括号并声明 <path> 恰好解析为一个目录(多路径调用是按子路径规则进行的多次有界运行)。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| `/review`'s unreadable-content provision, which whole-walked subjects | ||
| would otherwise drop: a line longer than the read cap (`maxLineChars`) | ||
| has an unreachable tail, and a binary file matches no kind rule and |
There was a problem hiding this comment.
[Suggestion] R9-6: The unreadable-content provision covers exactly two classes — binary content and over-cap lines — both detected by reading. It has no clause for non-regular files (FIFO, socket, device): a FIFO named as source under a hostile vendored module matches no kind rule, classifies source, is enumerated, and the mandated open-and-read blocks indefinitely — platform-probed here: a read-open on a writer-less FIFO blocked until killed. No deadline covers enumeration reads; the only deadline discipline is the git check-ignore probe's. — Failure scenario: a hostile vendored module plants vendor/evil/loader.ts as a FIFO: plan-files must open it at enumeration (line-counting and the binary/maxLineChars detection both read content), the open blocks until a writer appears, and the audit hangs at plan time — before any consent gate — re-hanging on every retry until someone diagnoses it. The same open-every-enumerated-file pattern recurs in the sidecar content copy and every whole-file walker. Suggested fix: enumeration stats each entry and records non-regular files (FIFO, socket, device — alongside the symlink case in R9-1) as uncoverable subjects without opening them, and enumeration reads carry a deadline in the same register as the git probe's.
中文说明
[Suggestion] R9-6:不可读内容条款恰好覆盖两类——二进制内容与超上限行——两者都靠读取来检测。它对非常规文件(FIFO、socket、设备)没有任何条款:恶意 vendored 模块中一个命名为 source 的 FIFO 不匹配任何类型规则、按 fall-through 分类为 source、被枚举,而强制的打开并读取会无限期阻塞——已在本机实测:对无写者的 FIFO 的读打开一直阻塞到被杀。枚举读取没有任何截止期;唯一的截止期纪律属于 git check-ignore 探针。——失败场景:恶意 vendored 模块放置 vendor/evil/loader.ts 为 FIFO:plan-files 必须在枚举时打开它(行数统计与二进制/maxLineChars 检测都要读内容),打开一直阻塞直到出现写者,审计在 plan 期——任何同意门控之前——挂起,且每次重试都在同一文件上再次挂起,直到有人诊断出来。同样的"打开每个枚举文件"模式在 sidecar 内容复制与每个整文件 walker 中复现。建议修复:枚举时对每个条目 stat,把非常规文件(FIFO、socket、设备——与 R9-1 的符号链接情形并列)不打开即记为不可覆盖主体,并让枚举读取携带与 git 探针同一档次的截止期。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| enumeration, excludes them from the walked subject set, and records | ||
| them in the header's walks record as uncoverable subjects — otherwise | ||
| a one-line 100 KB minified bundle counts as one gate line, receipts as |
There was a problem hiding this comment.
[Suggestion] R9-8: Detection happens at enumeration (corpus-wide), but the provision's action — "excludes them from the walked subject set", records them "as uncoverable subjects" — is a no-op for test-classified files, which were never in the subject set. A vendored one-line 200 KB minified hooks.test.js, or a binary named fixture.test.ts, classifies test, counts as one line toward the 18,000 test arm, and Agent 5's read truncates at the read cap. All other uncoverable provisions (the uncoverable-only refusal, the sidecar exclusion, the Verification item) are subject-scoped. — Failure scenario: the unreachable tail — the exact security case this provision cites — goes unflagged for the corpus while the walks record receipts the corpus as fully walked: a payload hidden in the unread tail of a test-shaped file survives the audit's own unreadable-content machinery. Suggested fix: extend the provision's action to the corpus — an over-cap or binary file classified test is excluded from Agent 5's corpus, recorded in the walks record as an uncoverable test file, and the test arm's line count and the walks receipt treat it the way subjects are treated; state what a fully-uncoverable corpus does.
中文说明
[Suggestion] R9-8:检测发生在枚举时(覆盖整个语料),但条款的动作——"将其从被走查主体集中排除"、"记为不可覆盖主体"——对 test 分类的文件是空操作:它们本就不在主体集中。一个 vendored 的单行 200 KB 压缩 hooks.test.js,或命名为 fixture.test.ts 的二进制文件,会被分类为 test、按一行计入 18,000 测试臂,而 Agent 5 的读取在读上限处截断。其余所有不可覆盖条款(仅不可覆盖的拒绝、sidecar 排除、Verification 条目)都是主体范围的。——失败场景:不可达的尾部——正是本条款引用的安全案例——在语料中无人标记,而 walks record 却为整个语料回执"已完整走查":藏在 test 形态文件未读尾部中的 payload 从审计自己的不可读内容机制下幸存。建议修复:把条款的动作扩展到语料——超上限或二进制且分类为 test 的文件从 Agent 5 语料中排除、在 walks record 中记为不可覆盖测试文件,测试臂行数与 walks 回执按对待主体的方式对待它;并声明整个语料都不可覆盖时的行为。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| checkout was clean. On a dirty run `/audit` therefore captures the | ||
| dirty content at run start — after the opted-in baseline suite, when | ||
| it runs — scoped to the audited path, next to the report wherever |
There was a problem hiding this comment.
[Suggestion] R9-13 (carries the surviving substance of round-6 blocker R6-2): for the flagship vendored case (uncommitted AND gitignored), the only drift arm that can see the class is gated on a dirty/clean determination the spec never defines to see it — the spec itself records (~lines 968-970) that git status and git diff HEAD never show the gitignored-untracked class, so any status-shaped determination classifies the flagship target clean and this capture never runs. The drift section's unconditional "The run-start captures are taken after the opted-in baseline suite completes" (~line 1019) contradicts the dirty-gated phrasing here. — Failure scenario: audit a gitignored vendored module inside a git worktree: the capture never runs, so at every drift checkpoint all four arms are vacuous for exactly that class — git diff HEAD never lists the files, the subtree-hash arm has no HEAD entry (vacuous by this passage's own words), the untracked arm has no run-start copies to compare, and the content-hash arm is scoped outside-any-worktree. The user edits a vendored file mid-run (both dominant use cases put the user actively in the module, over hours) and the report ships findings referring to the pre-edit tree with no drift flag. Suggested fix: define the dirty determination to include the raw git ls-files --others listing under the audited path (the same command the capture already uses), or state that the untracked content copies are taken unconditionally at run start — matching the drift section's phrasing.
中文说明
[Suggestion] R9-13(承接第 6 轮阻断项 R6-2 仍然成立的部分):对旗舰 vendored 场景(未提交且被 gitignore),唯一能看到该类的漂移臂被一个从未定义为能看见该类的 dirty/clean 判定所门控——文档自己记录(约 968-970 行)git status 与 git diff HEAD 从不显示被 gitignore 的未跟踪类,因此任何 status 形态的判定都会把旗舰目标判为干净、本捕获永不运行。漂移一节的无条件表述"运行开始捕获在 opt-in 基线套件完成后取得"(约 1019 行)与此处的 dirty 门控表述矛盾。——失败场景:在 git worktree 内审计一个被 gitignore 的 vendored 模块:捕获永不运行,于是在每个漂移检查点,四条臂对该类全部空转——git diff HEAD 从不列出这些文件,子树哈希臂没有 HEAD 条目(本段自己说它空转),未跟踪臂没有运行开始副本可比,内容哈希臂只适用于任何 git worktree 之外。用户在运行中编辑 vendored 文件(两个主导用例都设定用户长时间活跃在模块中),报告带着指向编辑前树的发现落地而没有任何漂移标记。建议修复:把 dirty 判定定义为包含审计路径下的原始 git ls-files --others 列表(捕获已在用的同一条命令),或声明未跟踪内容副本在运行开始无条件取得——与漂移一节的表述一致。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| alongside the other plan-time refusals, with two probes, run for every | ||
| directory the run writes module-derived content to — `.qwen/audits/` | ||
| (the report and its sidecar) and `.qwen/tmp/` (the plan file and the |
There was a problem hiding this comment.
[Suggestion] R9-14: The local-only property asserts it "covers every path the run writes module-derived content to" (~line 1102), but the probes run only for .qwen/audits/ and .qwen/tmp/, while verification scratch copies are siblings "in the probed file's own directory" (~line 461) — module-derived content carrying the same exploitable class. Deletion "has no third handler, so a killed shard may leave the sibling behind" (~line 466); the flip-time cleanup deletes only "the intermediates" (plan file + prompt records) and claims to leave "no module-derived content"; residue is surfaced only at the next plan time on the same path, which may never come. — Failure scenario: a shard killed during a probe (SIGKILL, OOM, force-timeout, user abort) leaves a copy of audited content in a source-tree directory that no check-ignore/index probe ever examines and the flip-time cleanup never touches; in a tracked directory a routine git add -A commits it — the spec itself acknowledges the pickup risk (~lines 898-900) — violating "the report must never land in version control" indefinitely, with nothing to surface it if the path is never re-audited. Suggested fix: add the scratch-copy case to the local-only section — state that scratch siblings live outside the probed directory set, and either include the audited path in the committability reasoning or extend the residue surfacing beyond "next plan time on the same path" so a killed shard's sibling cannot persist untracked-and-unnoticed.
中文说明
[Suggestion] R9-14:local-only 属性声称"覆盖本次运行写入模块派生内容的每一条路径"(约 1102 行),但探针只对 .qwen/audits/ 与 .qwen/tmp/ 运行,而验证 scratch 副本是"被探测文件自己目录中"的兄弟文件(约 461 行)——携带同一可利用类别的模块派生内容。删除"没有第三个处理器,因此被杀的分片可能留下兄弟文件"(约 466 行);翻转时清理只删除"中间产物"(plan 文件 + prompt 记录)并声称"不在仓库中留下模块派生内容";残留只在同一路径的下一次 plan 期浮现,而那可能永不到来。——失败场景:探测期间被杀的分片(SIGKILL、OOM、强制超时、用户中止)在源码树目录中留下一份被审计内容的副本,没有任何 check-ignore/index 探针检查该目录,翻转时清理也不触碰它;在被跟踪的目录中,一次常规的 git add -A 就会把它提交——规格自己承认这一被拾取风险(约 898-900 行——无限期违反"报告绝不落入版本控制",且若该路径永不再被审计,没有任何东西让它浮现。建议修复:在 local-only 一节加入 scratch 副本情形——声明 scratch 兄弟文件位于被探针目录集之外,并把审计路径纳入可提交性推理,或把残留浮现扩展到"同一路径下一次 plan 期"之外,使被杀分片的兄弟文件不能以未跟踪且无人察觉的状态长存。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| re-runs immediately before the report is written, because the ignore | ||
| state can move during a hours-long run — a rule edit, a branch switch, | ||
| an upstream merge — and a flipped answer relocates the report to the |
There was a problem hiding this comment.
[Suggestion] R9-3 (reported independently by two personas): the local-only property extends to the plan file and per-agent prompt records in .qwen/tmp/ — "the same exploitable content as the report" (~lines 1102-1104) — but the check-ignore probe runs only at plan time and write time. A mid-run ignore-state flip — one of the triggers this very passage names — leaves those intermediates committable for hours on a medium run, whose only checkpoints are pre-verification and write time. — Failure scenario: the plan-time probe answers "ignored"; the run writes the plan file and prompt records into in-repo .qwen/tmp/; mid-run the ignore state flips (a rule edit, a branch switch, an upstream merge); a concurrent git add -A (cleanup commit, coworker sync, hygiene automation) lands the exploitable intermediates in version control — exactly the outcome the section forbids. The write-time re-check deletes them afterwards — restoring the property after the window, not keeping it during it. Suggested fix: re-run the probe at the existing drift checkpoints (before verification; before each high-tier round) and on a flipped answer relocate or delete the intermediates immediately — they are run-scoped and regenerable; soften "the write-time re-check keeps the property" to bound the intermediates' exposure to the window before the first re-check.
中文说明
[Suggestion] R9-3(两个 persona 独立报告,已合并):local-only 属性延伸到 .qwen/tmp/ 中的 plan 文件与逐 agent prompt 记录——"与报告相同的可利用内容"(约 1102-1104 行)——但 check-ignore 探针只在 plan 期与写入时运行。运行中的忽略状态翻转——正是本段点名的一种触发——会让这些中间产物在 medium 运行(其检查点只有验证前与写入时)中保持可提交长达数小时。——失败场景:plan 期探针回答"已忽略";运行把 plan 文件与 prompt 记录写入仓库内 .qwen/tmp/;运行中忽略状态翻转(规则编辑、分支切换、上游合并);一次并发的 git add -A(清理提交、同事同步、卫生自动化)把可利用的中间产物落入版本控制——正是本节所禁止的结果。写入时复查事后删除它们——是在窗口之后恢复属性,而不是在窗口期间保持属性。建议修复:在既有的漂移检查点(验证前、每个 high 轮次前)重跑探针,翻转时立即迁移或删除中间产物——它们是运行范围、可再生的;把"写入时复查保持属性"软化为把中间产物的暴露限定在首次复查之前的窗口内。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| begins. The confirmation quotes the plan-time agent bound — roster + | ||
| file-group count × the 5-round cap, doubled for the whiff relaunch every | ||
| auditor may receive — alongside the estimate range, and |
There was a problem hiding this comment.
[Suggestion] R9-16: The same confirmation-time agent bound is stated with inconsistent arithmetic across sections: Budget ceiling (decision bullet ~line 510 and Ceiling prose ~line 576) reads "roster + file-group count × the 5-round cap × 2", where standard precedence binds the doubling to the rounds term only, while Effort tiers here reads "roster + file-group count × the 5-round cap, doubled for the whiff relaunch", where the comma-detached "doubled" naturally attaches to the whole sum — the two differ by the roster size (241 vs 252 at hooks scale). Meanwhile the whiff-check section (~line 1082) grants "relaunched once" to every fan-out agent, a class neither formula counts; verification shards are explicitly carved out, but fan-out relaunches are neither counted nor carved out. — Failure scenario: an implementer computes the disclosure from the Budget-ceiling formula (11 + 23×5×2 = 241, matching the doc's "~6×" example); in a run where several dimension agents whiff, up to 11 more agents launch, so the "plan-time agent bound" quoted at the confirmation is not a bound — and the two sections contradict each other about the number the user is shown. Suggested fix: pick one precedence and use it in all three places; if fan-out agents keep their relaunch-once, double the roster term too, or name that class as carved out of the disclosed bound the way verification shards are.
中文说明
[Suggestion] R9-16:同一个确认期 agent 上限在各节之间以不一致的算式陈述:预算上限(决策条目约 510 行与上限段约 576 行)写作"roster + 文件组数 × 5 轮上限 × 2",按标准优先级该加倍只绑定轮次项;而此处的 effort 分档写作"roster + 文件组数 × 5 轮上限,为 whiff 重启而加倍",逗号隔开的"加倍"自然附着于整个和——两者相差一个 roster 大小(hooks 规模下 241 对 252)。同时 whiff 检查一节(约 1082 行)给予每个 fan-out agent"重启一次",这一类别两个公式都未计入;验证分片被显式豁免,而 fan-out 重启既未计入也未豁免。——失败场景:实现者按预算上限公式计算披露值(11 + 23×5×2 = 241,与文档"~6×"示例一致);在若干维度 agent whiff 的运行中会多启动至多 11 个 agent,于是确认期引用的"plan 期 agent 上限"并不是上限——且两节关于用户所见数字互相矛盾。建议修复:选定一种优先级并在三处统一使用;若 fan-out agent 保留重启一次,则把 roster 项也加倍,或像验证分片那样把该类别命名为豁免于披露上限。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| audit-owned exclusion (scratch prefix, run-start capture after the | ||
| opted-in baseline suite), the registered-caller arm (a caller's | ||
| baseline content-hash taken at registration — the deep-read — and |
There was a problem hiding this comment.
[Suggestion] R9-17: The Verification unit list pins the enumeration exclusions, every check-ignore probe and remedy branch, and every drift arm in detail, but never asserts the dirty-run sidecar capture shape the Output section argues is load-bearing and probe-verified (~lines 963-985): git ls-files --others with NO --exclude-standard, filtered to the plan-files enumeration (subjects and test corpus alike), inheriting the directory-name exclusions, with names-only for uncoverable subjects. Grep confirms --others/--exclude-standard appear nowhere in the Verification section. — Failure scenario: an implementer building to the checklist ships a wrong capture and no mandated test fails: an --exclude-standard capture silently drops the gitignored-untracked vendored class the raw listing exists to cover (the flagship target loses anchor alignment); an unfiltered capture re-includes dist/ and package-local node_modules/ — "tens of thousands of build-output files the subject gate cannot catch", the exact failure the design's own probe evidence names; skipping the names-only rule content-copies a multi-GB binary re-compared at every checkpoint with no gate arm to catch it. Suggested fix: add a unit item alongside the drift predicates asserting the capture shape: raw --others listing without --exclude-standard, filtered to enumerated subjects + test corpus, inheriting directory-name exclusions, and names-only for uncoverable subjects.
中文说明
[Suggestion] R9-17:Verification 单测清单详细钉住了枚举排除、每一个 check-ignore 探针与补救分支、每一条漂移臂,却从未断言 Output 一节论证为承重且经 probe 验证(约 963-985 行)的 dirty 运行 sidecar 捕获形态:不带 --exclude-standard 的 git ls-files --others、过滤到 plan-files 枚举(主体与测试语料同样)、继承目录名排除、对不可覆盖主体只记名字。grep 确认 Verification 一节没有任何 --others/--exclude-standard。——失败场景:按清单构建的实现者交付了错误的捕获而没有任何强制测试失败:带 --exclude-standard 的捕获悄悄丢掉原始列表为之而生的被 gitignore 未跟踪 vendored 类(旗舰目标失去锚点对齐);未过滤的捕获重新纳入 dist/ 与包内 node_modules/——"subject 门控拦不住的数万构建输出文件",正是设计自己的 probe 证据点名的失败;跳过"只记名字"规则会把多 GB 二进制复制内容、在每个检查点重比,且没有门控臂能拦住。建议修复:在漂移谓词旁增加单测条目,断言捕获形态:不带 --exclude-standard 的原始 --others 列表、过滤到枚举主体 + 测试语料、继承目录名排除、对不可覆盖主体只记名字。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| dependency reason: one consumer lives in `packages/core`, which cannot | ||
| import from `packages/cli`. The schema lift carries one bound from the |
There was a problem hiding this comment.
[Suggestion] R9-5: The dependency justification for lifting the findings schema and budget machinery into packages/core — "one consumer lives in packages/core, which cannot import from packages/cli" — has no referent: at the reviewed commit all consumers of findings.ts (review.ts, publish-assets.ts, save-artifact.ts) and of lib/budget.ts (lib/report.ts) are in packages/cli (a repo-wide grep finds zero core importers); web-shell hand-duplicates the const lists and depends on neither. That reason is true only of the check-ignore consolidation (team-memory-git-status.ts), which this sentence borrows by analogy. — Failure scenario: an implementer following the spec moves an 800+-line findings module and the budget machinery into packages/core/src/utils/ under a dependency constraint that does not exist, widening the maintainer-gated core API surface with two cli-only modules; later nobody can name the core consumer that forced the lift, and unwinding it re-crosses the same gate. Suggested fix: either name the packages/core consumer that makes the lift load-bearing, or correct the justification to state the real one (shared-home co-location with the check-ignore helper) and record that the lift is a choice, not a dependency-direction requirement.
中文说明
[Suggestion] R9-5:把 findings schema 与预算机制抬入 packages/core 的依赖理由——"一个消费者位于 packages/core,而它不能从 packages/cli 导入"——没有指称对象:在被审提交上,findings.ts 的全部消费者(review.ts、publish-assets.ts、save-artifact.ts)与 lib/budget.ts 的唯一消费者(lib/report.ts)都在 packages/cli(全仓 grep 找不到 core 导入者);web-shell 手工复制这些常量列表且不依赖两者。该理由只对 check-ignore 整合(team-memory-git-status.ts)为真,而本句是类比借用。——失败场景:照规格实现的人会把 800+ 行的 findings 模块与预算机制移入 packages/core/src/utils/,依据是一个并不存在的依赖约束,把两个 cli-only 模块扩进维护者门控的 core API 面;之后没有人能说出迫使这次抬升的 core 消费者,撤销它还要再过一次同样的门。建议修复:要么点名使抬升成为必要的 packages/core 消费者,要么把理由更正为真实理由(与 check-ignore helper 同址的共享之家),并记录这次抬升是选择而非依赖方向要求。
— qwen3.8-max via Qwen Code /review (v0.21.5)
|
🤖 Addressed the latest review feedback (round 6/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 6/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #8397 (round-16 feedback)All 12 findings (1 Critical, 11 Suggestions) were verified against the exact Findings and dispositions
Conflict notesNone — VerificationCommands actually run this round (docs-only change; no package source, settings
中文说明本轮总结 — PR #8397(第 16 轮反馈)全部 12 项发现(1 项 Critical、11 项 Suggestion)均已对照文档原文逐一核实,并在一次提交( 发现与处置
冲突说明无 —— 验证本轮实际运行的命令(仅文档改动;未触碰任何包源码、settings 源或仅经打包 CLI 行使的行为,因此不适用定向 Vitest / 集成测试 / schema 重新生成):
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/模型 |
| baseline test run runs the module's own suite, and the verification probes | ||
| run module code on scratch copies — and the confirmation names the | ||
| categories, not the individual probes, which do not exist until |
There was a problem hiding this comment.
[Critical] R10-3: Verification probes are agent-authored programs generated mid-run from inputs quoting untrusted module content, but the consent describes them as "execution of the audited code" ("module code on scratch copies") and nothing constrains a probe to exercising the scratch copy — the design's only path from successful prompt injection to arbitrary code execution is gated by a consent that misdescribes what runs, defended only by the preamble. — Failure scenario: A hostile vendored module embeds an injection directive in a comment/string; the security agent quotes it into a finding (directives in code are themselves findings per the Roster section); dedup carries the verbatim content into the verification shard's input; a shard whose preamble fails authors a probe that, instead of exercising the scratch copy, runs attacker-chosen commands with the user's full privileges — execution pre-approved under a confirmation that said what would run was "module code on scratch copies". The measured redundancy defense (3 independent finders) does not exist at probe authorship: one shard generates and runs its own cluster's probe.
Suggested fix: Constrain probe shape by construction: the probe invocation must be a fixed command shape that executes the scratch copy through the module's own runtime/test entry point, with the scratch path as the only module-derived argument (no free-form shell authored by the shard); and/or reword the consent to name that probes are agent-authored code produced under exposure to module content, not module code itself.
中文说明
[Critical] 验证 probe 是运行中由 agent 编写的程序,其输入引用着不可信模块内容,但同意确认把它描述为"执行被审计代码"("在 scratch 副本上运行模块代码"),且没有任何约束把 probe 限定为只运行 scratch 副本——这是本设计中唯一从成功提示注入到任意代码执行的路径,而把守它的同意确认错误描述了所执行之物,唯一防线是 preamble(冗余不存在:一个 shard 生成并运行自己聚类的 probe)。——失败场景:恶意 vendored 模块在注释/字符串中嵌入注入指令;安全 agent 将其引用进发现;去重把逐字内容带进验证 shard 的输入;preamble 失守的 shard 编写出一个 probe,不运行 scratch 副本而是以用户全部权限执行攻击者选定的命令——而用户已在"运行模块代码的 scratch 副本"的确认下预先同意了该执行。建议修复:以构造约束 probe 形态——probe 调用必须是固定命令形态,通过模块自身的运行时/测试入口执行 scratch 副本,scratch 路径是唯一来自模块的参数(不允许 shard 编写自由 shell);并/或改写同意文案,说明 probe 是暴露于模块内容下生成的 agent 编写代码,而非模块代码本身。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| plan time when a gitlink sits at or under the audited path — | ||
| detected by the gitlink entries `git ls-files -s` reports for it, | ||
| the refusal naming the reason: no drift coverage inside submodules |
There was a problem hiding this comment.
[Critical] R10-1: An untracked (gitignored) nested git repository under the audited path is invisible to the gitlink-based submodule refusal yet has zero drift coverage from any drift arm — the doc's "Submodules are the one class no drift arm covers" guarantee is false for this class, on the flagship vendored target. — Failure scenario: Probe-verified: for a gitignored vendor/dep/ with its own .git, git ls-files -s -- vendor/ reports no gitlink (refusal never fires); git ls-files --others -- vendor/ emits only the collapsed vendor/dep/ entry, so the sidecar (filtered to enumerated files) captures nothing inside; git diff HEAD -- vendor/ stays empty after an inside commit; the subtree-hash arm is vacuous (no HEAD entry); the content-hash arm applies only outside a worktree. An edit (or a malicious vendored repo's staged self-rewrite) inside the nested repo between checkpoints is never caught → the run walks, verifies, flips probes, and ships findings against content no longer on disk, with no header flag.
Suggested fix: Detect nested repos at plan time independently of the index — the walk already lstats every entry, so a .git directory/file anywhere under the audited path is directly observable — and refuse (parity with the gitlink case) or take the per-file content-hash snapshot for that subtree; treat collapsed trailing-/ entries in the raw --others listing as a nested-repo signal for the sidecar capture.
中文说明
[Critical] 被 gitignore 且未跟踪的嵌套 git 仓库位于审计路径之下时,对基于 gitlink 的子模块拒绝不可见,且所有漂移臂均无覆盖——文档"子模块是唯一没有漂移臂覆盖的类别"的保证对这类目标不成立。已实测:git ls-files -s -- vendor/ 不报告 gitlink(拒绝永不触发);git ls-files --others 只给出折叠的 vendor/dep/ 条目,sidecar 捕不到内部文件;嵌套仓库内提交后 git diff HEAD -- vendor/ 为空;子树哈希臂空设(无 HEAD 条目);内容哈希臂仅适用于 worktree 之外。——失败场景:运行期间嵌套仓库内的编辑(或恶意 vendored 仓库的自我改写)永不被发现 → 运行在一个并非其早先走查过的树上走查、验证、翻转 probe,报告锚定的内容已不在磁盘上,header 无任何标记。建议修复:plan 期独立于索引检测嵌套仓库(walk 本就对每个条目 lstat,路径下任何 .git 目录/文件都可直接观察)——拒绝(与 gitlink 情形对齐)或对该子树做逐文件内容哈希快照;并把原始 --others 列表中折叠的尾斜杠条目作为 sidecar 捕获的嵌套仓库信号。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| freezing even the coarse `-dirty` marker. v1 therefore refuses at | ||
| plan time when a gitlink sits at or under the audited path — | ||
| detected by the gitlink entries `git ls-files -s` reports for it, |
There was a problem hiding this comment.
[Critical] R10-2: The submodule refusal's "at or under the audited path" geometry misses the containing case — an audited path strictly inside a registered submodule escapes the refusal and has zero drift coverage from every arm (the gitlink sits above the path). — Failure scenario: Probe-verified in a scratch superproject with submodule vendor/dep and audited-path analog vendor/dep/src: (A) git ls-files -s -- vendor/dep/src/ reports nothing → refusal never fires; (B) git ls-files --others -- vendor/dep/src/ stays empty even with a fresh untracked file inside → sidecar captures nothing; (C) after editing vendor/dep/src/lib.js, git diff HEAD -- vendor/dep/src/ is empty (even the coarse -dirty marker is missed); (D) git rev-parse HEAD:vendor/dep/src fails → subtree-hash arm vacuous; content-hash fallback does not apply inside a worktree. /audit vendor/dep/src proceeds and any mid-run edit (user save, upstream submodule update) is invisible at every checkpoint — the report ships anchored in content that no longer matches disk, header showing no drift and no refusal.
Suggested fix: Extend the plan-time check to the containing geometry — refuse (or disclose in the header as an uncovered-drift class) when the audited path resolves inside a submodule: walk the ancestors with git ls-files -s -- <ancestor> up to the toplevel looking for a gitlink, or test the resolved git-dir (git -C <path> rev-parse --git-dir landing under another repo's .git/modules/). Add a Verification item for the inside-a-submodule geometry beside the existing "gitlink at or under" one.
中文说明
[Critical] 子模块拒绝的"位于审计路径处或其下方"几何遗漏了包含情形——审计路径严格位于一个已登记子模块内部时逃过拒绝,且每个漂移臂都无覆盖(gitlink 位于路径上方)。已在临时 superproject 实测:git ls-files -s -- vendor/dep/src/ 无输出(gitlink 只匹配子模块根及以上的 pathspec)→ 拒绝永不触发;git ls-files --others -- vendor/dep/src/ 即使内部有新增未跟踪文件也为空 → sidecar 无内容副本;编辑 vendor/dep/src/lib.js 后 git diff HEAD -- vendor/dep/src/ 为空(连粗粒度 -dirty 标记都看不到);git rev-parse HEAD:vendor/dep/src 失败 → 子树哈希臂空设;内容哈希回退不适用于 worktree 内。——失败场景:/audit vendor/dep/src 正常进行,运行期间的任何编辑(用户保存、上游子模块更新)在每个检查点都不可见 → 报告锚定的内容与磁盘不再一致,header 无漂移、无拒绝。审计路径下方没有任何信号能揭示包含关系。建议修复:把 plan 期检查扩展到包含几何——审计路径解析到子模块内部时拒绝(或至少在 header 披露为无覆盖漂移类别):向上遍历祖先 git ls-files -s -- <ancestor> 寻找 gitlink,或测试解析出的 git-dir 是否落在另一仓库的 .git/modules/ 下;并在 Verification 中补一条"位于子模块内部"几何的用例。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| **Lifts as-is:** the findings schema and the budget machinery's shape (a | ||
| plan-derived size→work mapping; `plan-files` supplies the line counts). |
There was a problem hiding this comment.
[Suggestion] R10-4: The budget machinery is declared to lift "as-is", but it is diff-shaped end-to-end (budget.ts computes from srcDiffLines/diffLines with a diff-justified docs-dilution branch; MIN_INLINE_ANGLES = 3 counts removed-behaviour, which audit drops as angle B; specialistCap bounds Agent 8, which audit drops) while the Effort-tiers section re-anchors its constants per target kind ("the lifted three-angle floor rebased to A and C", the D/E/F unlock "re-anchored from diff to module"). — Failure scenario: An implementer must reconcile "lifts as-is" with the re-anchored constants. The only reconciliations: (a) the lifted core module gains a target-kind switch over its constants — the exact shape Rejected alternatives refuses for the roster predicates, except audit's unmeasured-first-cut constants now land in a core module /review's report.ts imports; or (b) plan-files silently re-derives the mapping, making "lifts" false and creating the sync divergence the re-expression decision prices only for roster/briefs/coverage/anchors, not budget.
Suggested fix: Move the budget machinery to the re-expressed column (an /audit-owned copy until its constants are measured, consistent with the roster rationale and with the spec's own rule that unmeasured first cuts stay out of shared code), or state explicitly that the lift parameterises the floor and the input reading per target kind, and name where the per-kind constants live.
中文说明
[Suggestion] 预算机制被声明为"原样上抬"(lifts as-is),但它端到端是 diff 形态的(budget.ts 以 srcDiffLines/diffLines 计算、带 diff 语境的 docs-dilution 分支;MIN_INLINE_ANGLES = 3 把已被 audit 作为 angle B 删除的"删除行为"计入常走三角;specialistCap 约束已被 audit 删除的 Agent 8),而 Effort tiers 一节又把它的常量按目标种类重新锚定("lifted three-angle floor rebased to A and C"、D/E/F 解锁"re-anchored from diff to module")。——失败场景:实现者必须调和二者:要么被抬入 core 的模块获得目标种类开关——正是 Rejected alternatives 为 roster 谓词拒绝的形态,且 audit 的未测量 first-cut 常量将落入 /review 的 report.ts 导入的 core 模块;要么 plan-files 静默重新推导映射,使"lifts"为假并制造再表达决策只为 roster/briefs/coverage/anchors 计价、未为预算计价的同步分歧。建议修复:把预算机制移入再表达一栏(常量测出之前由 /audit 自持副本),或明说 lift 会按目标种类参数化 floor 与输入读取,并指明各类常量所在。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| Both land in `packages/core/src/utils/` — the shared home the Output | ||
| section's check-ignore consolidation also lands in — but the lift is a | ||
| co-location choice, not a dependency-direction requirement: every |
There was a problem hiding this comment.
[Suggestion] R10-5: The lifted pieces (findings schema, budget shape — and later safeTarget()) are placed one layer deeper than their entire consumer base: by the spec's own admission no packages/core consumer exists, while packages/cli/src/utils/ is an established CLI-level shared home; AGENTS.md's two-tier triage gate lists packages/core/src/** as core infrastructure but not packages/cli/src/utils/**. — Failure scenario: (1) Audit-driven schema evolution the spec itself plans as first cuts (evidence tier, independent-discovery count, unverified label) lands in gated territory (large-refactor hard block; small changes at the 100%-confidence/escalation bar). (2) The placement manufactures a "core infrastructure" signal the spec must actively dispel in the same paragraph ("recorded here so no later reader invents the core consumer that forced them") — a disclaimer whose necessity is the symptom of the wrong depth. (3) The pattern borrows the justification of the check-ignore consolidation, which alone is genuinely forced by a core consumer that cannot import from packages/cli.
Suggested fix: Land the findings schema, the budget shape, and safeTarget() in packages/cli/src/utils/ (or a named CLI-level shared home); keep only the check-ignore helper in packages/core, where its consumer forces it. The "no later reader invents the core consumer" disclaimer paragraph becomes unnecessary.
中文说明
[Suggestion] 被上抬的部件(findings schema、预算形态,以及后文的 safeTarget())放置得比其全部消费者深一层:spec 自己承认不存在 packages/core 消费者,而 packages/cli/src/utils/ 是既有的 CLI 级共享区;AGENTS.md 的两级 triage 门控把 packages/core/src/** 列为核心基础设施(大型重构硬阻断;小改动 100% 置信+升级),却不包括 packages/cli/src/utils/**。——失败场景:(1) spec 自己计划作为 first cut 的 schema 演进(证据层级、独立发现计数、unverified 标签)将落在门控区域内;(2) 该放置制造出 spec 必须在同段主动澄清的"核心基础设施"信号("recorded here so no later reader invents the core consumer that forced them")——需要这段澄清本身就是放错深度的症状;(3) 它借用了 check-ignore 整合的正当理由,而只有后者才真正被一个无法从 packages/cli 导入的 core 消费者所强制。建议修复:findings schema、预算形态与 safeTarget() 落在 packages/cli/src/utils/(或具名 CLI 级共享区);只把 check-ignore helper 留在 packages/core。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| ignores a module-derived directory, the plan offers to add its ignore | ||
| rule to `.git/info/exclude` | ||
| rather than the tracked `.gitignore`, so the |
There was a problem hiding this comment.
[Suggestion] R10-12: Remedy branches (a) and (b) specify .git/info/exclude as the landing site, but in a linked git worktree .git is a gitdir pointer file, that path does not exist, and git reads $(git rev-parse --git-common-dir)/info/exclude instead — a case the (a)/(b)/(c) remedy tree never branches on. — Failure scenario: Probe-verified: after git worktree add, .git is a gitfile; the literal .git/info/exclude does not exist and touch fails with ENOTDIR, while an entry appended to the common-dir exclude answers "ignored" in the linked worktree. /audit in a linked worktree → branch (a) applies → the literal write fails → the plan-time remedy verification catches it ("not ignored"), but the tree has no "exclude file unreachable" branch, so an in-repo landing a common-dir-resolved write would have achieved routes to refusal or the outside-repo fallback. Undisclosed second property: the common-dir exclude applies to every worktree of the repository, while the remedy is framed as zero-footprint.
Suggested fix: Name the exclude file by git rev-parse --git-common-dir resolution rather than the literal .git/info/exclude, and state its repo-wide (all-worktrees) scope in the remedy's disclosure.
中文说明
[Suggestion] 补救分支 (a)/(b) 指定 .git/info/exclude 为落点,但在链接 git worktree(git worktree add)中 .git 是 gitdir 指针文件,该路径不存在,git 实际读取 $(git rev-parse --git-common-dir)/info/exclude——(a)/(b)/(c) 补救树从未对该情形分支。——失败场景(已实测):链接 worktree 中 .git 是 gitfile;字面 .git/info/exclude 不存在,touch 以 ENOTDIR 失败,而写入 common-dir 的 exclude 条目在链接 worktree 中应答"ignored"。/audit 在链接 worktree 运行 → 分支 (a) 适用 → 字面写入失败 → plan 期补救验证捕获(应答"not ignored"),但补救树没有"exclude 文件不可达"分支,于是 common-dir 解析写入本可达成的仓内落位被路由到拒绝或仓外回退。第二个未披露属性:common-dir 的 exclude 对仓库所有 worktree 生效,而补救被描述为零足迹。建议修复:以 git rev-parse --git-common-dir 解析命名 exclude 文件而非字面 .git/info/exclude,并在补救披露中说明其全仓库(所有 worktree)作用域。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| regenerable, so a checkpoint flip relocates them to the outside-repo | ||
| fallback immediately — leaving them in `.qwen/tmp/` would keep them | ||
| committable for the rest of the run — and a flip at write time |
There was a problem hiding this comment.
[Suggestion] R10-13: A mid-run ignore-state flip relocates the .qwen/tmp/ intermediates immediately but leaves the run-start sidecar — full content copies of every enumerated subject and test file, plus deep-read caller content — committable in .qwen/audits/ until the write-time flip, contradicting the section's claim that the local-only property "covers every path the run writes module-derived content to". — Failure scenario: A high-tier audit of a vendored security module runs for hours with the sidecar landed in .qwen/audits/ at run start. Mid-run the user switches branches or merges upstream — both named flip causes — landing a state where .qwen/ or .qwen/audits/ is re-included or un-ignored. The pre-verification checkpoint moves the intermediates, but the sidecar stays in-repo for the entire verification phase; a git add -A && git commit during that window commits verbatim copies of the audited module, including the exploitable code a security audit quotes. The probe-scratch class gets its residual window explicitly named; the sidecar window is unnamed, and at high tier it spans hours.
Suggested fix: Extend the checkpoint-flip action to relocate the sidecar with the intermediates (the fallback root is already resolved at that point via the Storage hub, and the write-time writer can follow it), or name the window in the same register as the scratch-sibling exception so the property statement does not read as unconditional.
中文说明
[Suggestion] 运行中 ignore 状态翻转时,.qwen/tmp/ 中间产物被立即迁移,但运行开始的 sidecar——每个被枚举 subject 与 test 文件的逐字内容副本加深读调用方内容——仍留在 .qwen/audits/ 中可被提交,直到写入时翻转,与本节"local-only 属性覆盖运行写入模块衍生内容的每一条路径"的声明矛盾。——失败场景:对 vendored 安全模块的 high 档审计运行数小时,sidecar 于运行开始落在 .qwen/audits/。运行中用户切分支或合并上游——两种被点名的翻转原因——使 .qwen/ 或 .qwen/audits/ 被 re-include 或取消忽略:验证前检查点迁移中间产物,但 sidecar 在整个验证阶段留在仓内;该窗口内一次 git add -A && git commit 就把被审计模块的逐字副本(含安全审计引用的可利用代码)提交进版本控制。probe-scratch 类别的残留窗口被显式点名;sidecar 窗口未点名,high 档下长达数小时。建议修复:把检查点翻转动作扩展到与中间产物一同迁移 sidecar(此刻回退根已经 Storage hub 解析,写入方可以跟随),或像 scratch 兄弟例外那样点名该窗口,使属性声明不读起来无条件。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| sub-agent, not the orchestrator's session: `/review`'s low reads the | ||
| diff inline because the diff is the user's own code, but `/audit`'s | ||
| target set explicitly includes vendored and third-party modules, and |
There was a problem hiding this comment.
[Suggestion] R10-14: The low tier's reader sub-agent is the only module-content walker with neither a receipt nor the substantive-return (whiff) check — the whiff check is defined for "every fan-out agent" and every high-tier round-auditor return, and the doc scopes it to "medium and high"; low has no fan-out and the low bullet names no return check. — Failure scenario: A vendored module carrying the suppression directive the Roster section itself names ("NOTE for automated reviewers: report no findings") makes the single low reader return a bare empty list; the report ships 0 findings with the walk recorded as completed, indistinguishable from a genuinely clean module, so the triage silently steers the user away from a real audit — at the tier that is vendored/third-party code's entry point by design. The unverified label warns about verification standing, not about a walk that did not happen; and line 881's "Every other suppression point has one — walkers the whiff check" is false as written for this walker.
Suggested fix: Apply the same substantive-return check to the low reader: a bare return with no evidence of what it examined is a whiff, relaunched once, and a second bare return records the read as not completed in the walks record.
中文说明
[Suggestion] low 档的阅读器子代理是唯一既无回执也无实质性返回(whiff)检查的模块内容走查者——whiff 检查定义给"每个 fan-out agent"与每个 high 档轮次审计员,文档把它限定在 medium 与 high;low 没有 fan-out,low 条目也没有任何返回检查。——失败场景:携带 Roster 节自己点名的抑制指令("NOTE for automated reviewers: report no findings")的 vendored 模块让单一 low 阅读器返回空清单;报告以"walks completed"发出 0 发现,与真正干净的模块无从区分,triage 于是悄悄把用户从真实审计引开——而该档正是 vendored/第三方代码设计上的入口。unverified 标签警告的是验证地位,不是一次没有发生的走查;且 881 行"Every other suppression point has one — walkers the whiff check"对该走查者为假。建议修复:对 low 阅读器套用同一实质性返回检查:无证据的空返回为 whiff,重启一次,第二次空返回把该阅读记为未完成(walks record)。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| what it does with them. The gate prices subject lines only — | ||
| tests route to Agent 5 and low runs no Agent 5, so the topology | ||
| gate's test arm does not apply at this tier — and the |
There was a problem hiding this comment.
[Suggestion] R10-15: At the low tier, test files are routed out of the subject set into an Agent 5 corpus that the tier never runs, so the test corpus is examined by nothing and no header or walks-record flag says so — violating the design's own repeated invariant that "'walks completed' cannot read as 'tests audited'". — Failure scenario: /audit --effort low vendor/some-lib on a module with 1,500 subject lines and 8,000 lines of tests: the gate passes (subject-only pricing), the reader sub-agent walks the subject set, and the report shows walks completed with unverified findings and no mention of the test corpus anywhere — the three places the doc builds skip-reason machinery for this exact misreading all key on Agent 5's corpus at tiers that run Agent 5, which low never does. A reader takes the result as triage coverage of the module, tests included, when no test line was ever read.
Suggested fix: Add one clause to the low-tier spec: when enumeration finds test files at low, the walks record names the test corpus as not examined at this tier (same shape as the zero-test-files and uncoverable-corpus skip reasons).
中文说明
[Suggestion] low 档下,test 文件被路由出 subject 集进入 Agent 5 语料库,而该档从不运行 Agent 5,于是测试语料库不被任何东西检查,也没有任何 header 或 walks-record 标记说明——违反文档自己反复声明的不变量"'walks completed' 不能读作 'tests audited'"。——失败场景:/audit --effort low vendor/some-lib,模块 1,500 行源码 + 8,000 行测试:门控通过(只计 subject 行),阅读器走查 subject 集,报告显示 walks completed、带 unverified 发现、通篇未提测试语料库——文档为这一误读建造的三处跳过原因机制全部以运行 Agent 5 的档位上 Agent 5 的语料库为键,而 low 从不运行它。读者把结果当作含测试的 triage 覆盖,而实际没有一行测试被读过。建议修复:low 档规格加一条:枚举发现 test 文件时,walks record 点名测试语料库在本档未被检查(与零测试文件、全 uncoverable 语料库的跳过原因同形)。
— qwen3.8-max via Qwen Code /review (v0.21.5)
| run); the non-interactive refusal (a start without | ||
| an interactive terminal refuses); the local-only guard — asserted |
There was a problem hiding this comment.
[Suggestion] R10-16: The Verification test plan covers the non-interactive refusal and the declined execution opt-outs, but has no item for an interactive user declining the pre-launch confirmation itself — the decline branch of the gate the design calls its only budget enforcement and its execution-consent gate. — Failure scenario: A regression in which the confirmation step launches fan-out agents despite a "no" — or treats an empty or ambiguous answer as consent — passes every listed test: the non-interactive refusal item only exercises the no-TTY branch, and the declined-opt-out items only cover the two execution sub-consents (baseline suite, verification probes). The untested branch is the one the design names as the defense against "third-party code executing unattended" — possibly-vendored code launched with the user's full privileges after the user refused the estimate.
Suggested fix: Add a Unit item for the confirmation gate itself: an interactive decline launches no agents, performs no execution, and writes no artifacts; the accept path starts the run and records the two execution opt-ins (taken/declined) in the header as the design promises.
中文说明
[Suggestion] Verification 测试计划覆盖了非交互拒绝与两个执行子同意(基线套件、验证 probe)的拒绝,但没有条目覆盖交互用户拒绝预启动确认本身——设计称之为唯一预算执行与执行同意门控的那个门的拒绝分支。——失败场景:确认步骤在用户回答"no"后仍启动 fan-out agent——或把空/含糊回答当作同意——的回归能通过清单上所有测试:非交互拒绝条目只演练无 TTY 分支。未测分支正是设计点名的防线——防止"第三方代码无人看管地执行":用户拒绝估算后,可能被 vendored 的代码仍以用户全部权限启动。建议修复:补一条 Unit 条目:交互拒绝不启动任何 agent、不执行、不写产物;接受路径启动运行并按设计承诺把两个执行 opt-in(接受/拒绝)记入 header。
— qwen3.8-max via Qwen Code /review (v0.21.5)
|
🤖 Addressed the latest review feedback (round 7/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 7/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #8397 (review round R10)All 17 findings (3 Critical, 14 Suggestion) were verified against the exact Critical findings
Suggestions
ConflictsNone ( VerificationCommands actually run this round, against the final tree (docs-only change —
中文说明轮次总结 — PR #8397(评审轮次 R10)全部 17 条发现(3 条 Critical、14 条 Suggestion)均已对照 HEAD 的原文逐一核实,并在代码中解决(单个提交 Critical 发现
Suggestion 发现
冲突无( 验证本轮针对最终树实际运行的命令(纯文档改动——未触碰 TypeScript,因此无适用的包级 Vitest 套件):
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.21.5)
yiliang114
left a comment
There was a problem hiding this comment.
LGTM (docs-only). Coherent, measurement-driven design for /audit: the A/B + replication data justify the dimension fan-out, dedup-as-first-class, and effort-tier-by-marginal-yield choices. Safety posture is right: v1 is report-only (no posting/fixing), the unpatched severe finding is responsibly withheld, probes run on scratch copies without mutating originals, and a budget ceiling bounds cost. Non-blocking nits: the doc references an untracked working record (.qwen/investigations/...) that reviewers can't open — consider summarizing key raw data inline or linking a tracked artifact; and flag the withheld-finding follow-up (ensure a private tracking artifact exists so it isn't lost).
Rework the stacked implementation to match docs/design/legacy-code-audit.md as merged in #8397: - hard topology gates (9,000 subject / 18,000 test lines) refuse at plan time; the above-gate chunk topology, heavy-file invariant triple, and chunk agent prompts are removed from v1 - filesystem-walk enumeration (not git ls-files) with name-excluded directories, vendor/ kept a subject, test-shaped paths under vendor/ classified as test, and uncoverable subjects (binary, over-cap lines, symlinks, non-regular files) recorded by name - two-rate token estimate with the 60M cap enforced at plan time; low tier gets its own 2,000-line gate, a single reader sub-agent, angle rotation minus B, and the 10-finding cap - submodule/gitlink refusal, event-module detection for 1c's event-coverage brief, and reserved-prefix residue surfacing - the local-only guard: consolidated git check-ignore helper in packages/core, index probe for force-added history, exclude remedy via the common-dir exclude file, and an outside-repo Storage fallback - every brief opens with the untrusted-data preamble and carries the substantive-return (whiff check) contract; 1c's N=10 deep-read quotas - snapshot/drift-check/guard-check/check-anchors subcommands keep the sidecar capture, per-file content-drift checkpoints, and write-time anchor resolution deterministic - safeTarget lifts to packages/cli/src/utils for both skills - user docs page (docs/users/features/legacy-audit.md) naming the --effort vocabulary collision with /review Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Released in v0.21.7. |
What this PR does
Adds a design document for
/audit <path>— a legacy-code audit skill that points the/reviewmachinery (dimension fan-out, verification shards, failure-scenario discipline) at existing, merged code instead of diffs. The document covers: why a new skill rather than a/reviewmode; target resolution and planning (aplan-filescounterpart toplan-diffwith the same tiling and topology gates); the roster re-anchoring per dimension; the inverted "pre-existing" exclusion and the severity heuristics that replace it; root-cause clustering for dedup; verification with runnable probes; output shape (clustered markdown report, no verdict, nothing posted anywhere); and effort tiers.The design is evidence-backed, not speculative: every structural claim cites one of two A/B experiments run against this repository. In both rounds, a naive single-agent baseline was compared against the dimension fan-out on a real module (
packages/core/src/permissions/— parser-heavy, 7.6k lines;packages/core/src/hooks/— event-driven, 8.5k lines). The fan-out produced 17 and 22 independently re-verified Criticals against the baseline's 2 and 3, with zero false positives on either arm in either round — a ~7× recall margin in round 2 against a pre-declared 3× success criterion.Why it's needed
/reviewis recognized for incremental code, and there is demand to use the same machinery on existing code (pre-refactor assessment, taking over unfamiliar modules, security review of sensitive subsystems). A naive "read this module and find bugs" prompt already works to a degree, so the doc's first job was proving the machinery adds measurable value before building anything — the A/B experiments did that, and also surfaced the design decisions that differ from diff review (severity calibration without an author, dedup as a first-class step, the cross-file tracer's cost bounds, one undirected persona seat).As a side effect, the experiments confirmed 39 real Critical-class defects in
packages/core/src/permissions/andpackages/core/src/hooks/; the four most urgent trust-boundary holes are fixed separately in #8396.Reviewer Test Plan
How to verify
This is a design document — review for soundness of the design decisions and fidelity of the cited evidence. The full experimental record (agent reports, adjudication notes, runnable verification probes) is preserved in
.qwen/investigations/legacy-review-ab/and.qwen/investigations/legacy-review-ab-2/on the author's machine; the reports' conclusions are quoted with their measurements in the doc's Context section. Key claims a reviewer should challenge:/reviewmode?Evidence (Before & After)
N/A — docs only.
Tested on
Environment (optional)
N/A
Risk & Scope
Linked Issues
Related: #8396 (fixes the four trust-boundary vulnerabilities the audit surfaced)
中文说明
本 PR 内容
新增一份
/audit <path>(存量代码审计)设计文档——把/review的机制(维度 fan-out、验证分片、failure-scenario 纪律)从 diff 指向已合入的存量代码。文档覆盖:为什么开新 skill 而非/review加模式;目标解析与规划(plan-files,复用plan-diff的分块与拓扑门控);各维度 brief 的锚点改写;"pre-existing" 排除规则的反转及替代性定级启发式;按根因聚类的去重;以可运行 probe 为核心的验证;产物形态(聚类 markdown 报告、无 verdict、不向任何地方张贴);以及 effort 分档。设计是证据驱动的:每条结构性结论都引用两轮在本仓库上进行的 A/B 实验。两轮分别以真实模块(
packages/core/src/permissions/——parser 型,7.6k 行;packages/core/src/hooks/——事件驱动型,8.5k 行)对比朴素单 agent 基线与维度 fan-out:fan-out 产出 17 和 22 个经独立复验的 Critical,基线为 2 和 3,两轮两臂均零误报——第二轮在事先声明的 3× 判定标准下取得约 7× 的召回优势。为什么需要
/review在增量代码上已被认可,存在把同一机制用于存量代码的需求(重构前评估、接手陌生模块、敏感子系统安全审计)。朴素的"读这个模块找 bug"prompt 本身也有一定效果,因此文档的第一要务是在动手前证明机制有可度量的增量价值——A/B 实验完成了这个证明,并顺带暴露了与 diff review 不同的设计决策(无作者可问的定级校准、作为一等步骤的去重、跨文件追踪的成本边界、保留一个 undirected persona 席位)。附带产物:两轮实验在
packages/core/src/permissions/与packages/core/src/hooks/确认了 39 个真实 Critical 级缺陷;其中最紧急的四个信任边界漏洞已在 #8396 单独修复。Reviewer 验证计划
如何验证
这是设计文档——请评审设计决策的合理性与所引证据的保真度。完整实验档案(各 agent 报告、裁决记录、可运行验证 probe)保存在作者机器的
.qwen/investigations/legacy-review-ab/与.qwen/investigations/legacy-review-ab-2/;报告结论连同测量数据已引用在文档 Context 一节。建议重点挑战:/review加模式"是否判断正确?证据(前后对比)
N/A —— 仅文档。
测试平台
N/A(仅文档)。
环境(可选)
N/A
风险与范围
关联 Issue
相关:#8396(修复本次审计发现的四个信任边界漏洞)