feat(review): swap re-review rounds to a fix-audit shape under the critical posture - #10136
feat(review): swap re-review rounds to a fix-audit shape under the critical posture#10136wenshao wants to merge 18 commits into
Conversation
…itical posture Once a multi-round review settles into the critical-only posting posture (floor: c), the re-review round still ran round 1's full shape: the whole territory fan-out plus up to five full-width reverse-audit waves, while everything found below Critical was deferred anyway. Measured on PR #9729 round 15, the 3h13m / 131M-token round's entire finder fan-out contributed nothing postable, all three posted Criticals first surfaced in the reverse-audit waves, and the one-hop import widening re-entered 89% of the diff. When the posture is knowable at capture time and a usable anchor exists, the round now changes shape: - fetch-pr predicts the compose-time floor resolution from the side file pr-context persisted (round schedule and latched flatRounds — monotone arms only) or the CLI-recorded explicit floor, and records incremental.posture: "critical" with its postureCause in the plan. - The topology gate reads the posture: a fix-audit round is a territory fan-out whatever its narrowed sizes say, so the roster (chunk agents, no Agent 0), the round-cap tier and the #9242 note all follow from the one shared predicate. Chunk briefs carry a fix-audit frame; severities are unchanged (the floor governs posting, never finding). - Interaction files re-enter seam-bounded: only the hunks displaying a line that imports or uses what changed republish, with a seam: {kept, total} census per entry; a file with no seam hunk publishes header-only and still lands in a chunk so its brief asks the seam question from the worktree. Every doubt state republishes in full. - Reverse-audit waves narrow instead of the cap lowering: from round 3 a chunk holding no delta file leaves the schedule after one substantive dry audit and takes no cold checks, while delta territories keep the full retirement rules — recall stays where the measured fix-induced Criticals surfaced (waves up to the cap), over a shrinking front. - Every reduction is disclosed: the plan record, the briefs' seam census, a posture-narrowing note beside the retirement note, and a round-shape paragraph compose-review renders into the posted body. Closes #10104
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Thanks for the PR, @wenshao. The linked issue is clear and the measurements behind it (PR #9729 round 15: 3h13m, ~131M input tokens, the full finder fan-out contributing nothing postable under the critical floor) make the problem concrete, and the proposed direction looks reasonable.
One gate item before we can go deeper, though: the PR body doesn't follow the PR template. It has ## What this PR does, but is missing the other required sections:
## Why it's needed## Reviewer Test Plan— including### How to verify,### Evidence (Before & After), and the### Tested onOS matrix## Risk & Scope## Linked Issues
Most of the substance is already in the body — "How this was verified" maps to the Reviewer Test Plan, "What deliberately did not change" fits Risk & Scope, and Closes #10104 belongs under Linked Issues — so this should be a restructure rather than new work. Once the body follows the template, re-run with @qwen-code /triage and we'll pick up from the code review.
中文说明
感谢这个 PR,@wenshao。关联的 issue 很清晰,背后的测量数据(PR #9729 第 15 轮:3h13m、约 1.31 亿 input tokens、critical floor 下整个 finder 扇出没有任何可发布产出)让问题非常具体,提出的方向也看起来合理。
但在深入之前有一个门禁项:PR 正文没有遵循 PR 模板。目前有 ## What this PR does,但缺少其余必填章节:
## Why it's needed## Reviewer Test Plan—— 包括### How to verify、### Evidence (Before & After)和### Tested on操作系统矩阵## Risk & Scope## Linked Issues
正文里其实已经包含了大部分实质内容——"How this was verified" 对应 Reviewer Test Plan,"What deliberately did not change" 适合放进 Risk & Scope,Closes #10104 应放在 Linked Issues 下——所以这应该是一次重组,而不是新增工作。正文按模板调整后,用 @qwen-code /triage 重新触发,我们会从代码审查继续。
— Qwen Code · qwen3.8-max
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
|
@qwen-code /triage |
|
Sandboxed verification: ❌ not passed — findings reported (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 103 passed · 1 failed · 104 total Flakiness gate: ✅ 9 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:❌ 不通过 · 报告了发现(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:103 通过 · 1 失败 · 104 总计 抖动门:✅ 9 changed test file(s) x 5 identical rounds, no divergence Verification reportPR #10136 Deep Verification — fix-audit round shape under the critical postureVerdict: 中文摘要结论: Scope selectionCentral claim: when the critical-only posting posture is knowable at capture time and a usable anchor exists, the round switches to the fix-audit shape — plan records Secondary claims: (1) Central claim — A/B tableBehavioral harness (
Head arm: 29/29 checks; base arm: 21/21 checks with every encoded difference flipping to the pre-PR shape. Prediction⊆resolution containment (P-cells, head): all three predicting arms ( Test-level A/B (same tests, both arms) — head's 9 new/changed test files copied verbatim into the base worktree and run there (
All 25 base failures are the PR's own new assertions (every one tagged Vacuity & mutation matrixEvery mutation reverted exactly one guard in a scratch worktree (
M3+M4 defend the same hazard from two directions (compute vs emit); both are killed independently, so the set is load-bearing and neither hunk is redundant. No new test is vacuous; every central guard is pinned at the assertion level. The one survivor is adjudicated in Finding 1. Corrections
Findings1. Suggestion — the lookbehind
|
|
Thanks for the PR, @wenshao — the re-run picks up where the last pass stopped. The template restructure landed, so the gate clears this time.
Moving on to code review. 🔍 中文说明感谢这个 PR,@wenshao —— re-run 从上一轮停下的地方继续。模板重组已完成,门禁这次通过。
进入代码审查。🔍 — Qwen Code · qwen3.8-max Reviewed at |
|
Code review — I wrote an independent proposal from the issue before opening the diff; the implementation lands on the same decomposition component for component (posture prediction at capture, one topology-gate override, seam-bounded republication, cap-preserving wave narrowing, disclosure at each reduction), so the review went to the edges instead. What I verified:
One non-blocking observation: How the posture fact flowssequenceDiagram
participant P1 as fetch-pr capture
participant P2 as plan posture record
participant P3 as roster and budget
participant P4 as reverse-audit waves
participant P5 as compose floor
P1->>P2: predict from side file and recorded floor
P2->>P3: flip topology gate, drop Agent 0
P1->>P4: seam-bounded widening, narrowing context
P2->>P5: posture record resolves the auto floor
Note over P1,P5: explicit suggestion floor turns the posture off at either end
Files changed (22)
Test evidence — the PR's own CI (this pass never builds or runs PR code; per policy the evidence below is the PR's own check results fetched via the API): both
Not verified, and named as such: there is no live multi-round dogfood — the shape only engages from round 6 of a real long-lived review, which neither sandboxed lane can reach ( 中文说明代码审查 —— 在读 diff 之前先只依据 issue 写了独立方案;实现与该方案逐组件吻合(捕获期姿态预测、单一拓扑门覆盖、接缝限宽重发、保上限的波次收窄、每处收窄均披露),因此审查重点放在边界情形:
一个非阻塞观察: 测试证据 —— PR 自身 CI(本审查不构建、不运行 PR 代码;以下证据为通过 API 获取的 PR 自身检查结果):两个 未验证并如实声明:没有真实多轮 dogfood——形态仅在真实长寿 PR 的第 6 轮起生效,沙箱通道无法触及( — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — solid across every stage; the only nits are the inline-duplicated admission gate and the pending live dogfood, and neither blocks. Stepping back: the independent proposal I wrote from the issue alone and the implementation land on the same decomposition, which is a good sign the shape is not overbuilt — each of the three levers maps to a measured waste, and every reduction carries its disclosure on the record. The part that holds up best under scrutiny is the alignment discipline: the prediction never outruns the resolution (monotone arms only, clamped streak), the residual divergences are closed from the compose side rather than wished away, and the one combination nothing licenses — a narrowed round posting sub-Critical in full — is tested as unreachable. The recall trades are priced and documented in DESIGN.md instead of hidden, which is the honest way to buy back ~50 runner-hours. If I were maintaining this in six months: the posture fact has one writer, one predicate, and disclosed reductions; the schedule constants live in one module both readers import. That is maintainable. The one thing to watch is the dogfood the author already named — the first real critical-posture round on a long-lived PR — and the non-blocking reuse note in the review above. Approving, pinned to the reviewed commit. ✅ 中文说明置信度:4/5 —— 各阶段均扎实;仅有的两个小问题是内联重复的准入校验门与尚待进行的真实 dogfood,均不构成阻塞。 退后一步看:仅凭 issue 写出的独立方案与实现落在同一分解上,说明形态并未过度设计——三个杠杆各自对应一处实测浪费,且每处收窄都在记录中留有披露。最经得起推敲的是对齐纪律:预测从不跑在决议前面(只取单调臂、钳制信号),残余分歧从 compose 一侧闭环而非回避,唯一不被许可的组合——收窄轮全量发布 sub-Critical——被测试钉为不可达。召回取舍在 DESIGN.md 中计价并记录,而非隐藏——这是换回约 50 runner 小时的诚实方式。 若六个月后由我维护:姿态事实只有一个写入者、一个谓词、处处披露;日程常量位于两个读取端共同导入的单一模块。这是可维护的。需要关注的是作者已点名的 dogfood——长寿 PR 上第一次真实的 critical 姿态轮——以及上方审查中的非阻塞复用建议。批准,锚定在被审 commit。✅ — Qwen Code · qwen3.8-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
@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 冲突,直到移除标签或达到轮次上限。移除 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not explored to full depth (tool budget reached): "agent reverse-audit (round 4)": none — the full chunk (diff lines 1–392) was read un-truncated and every check above was completed.; chunk 7: executed run of roster.test.ts / retirement.test.ts — the review worktree has no node_modules , and a full monorepo install plus build exceeded the tool bu….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory.
中文说明
未探索到全部深度(达到工具调用预算):"agent reverse-audit (round 4)":none — the full chunk (diff lines 1–392) was read un-truncated and every check above was completed.;chunk 7:executed run of roster.test.ts / retirement.test.ts — the review worktree has no node_modules , and a full monorepo install plus build exceeded the tool bu…。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| typeof scope.anchor === 'string' && | ||
| scope.anchor !== '' && | ||
| Array.isArray(scope.deltaFiles) |
There was a problem hiding this comment.
[Critical] R1-1: This scope bar is strictly weaker than the paired reader it claims parity with. incrementalScopeOf in agent-prompt.ts additionally rejects non-string deltaFiles elements and the both-empty case (deltaFiles.length === 0 && interaction.length === 0 → null), and fixAuditShapeFacts in compose-review.ts repeats this same weak bar. A plan carrying posture: 'critical', effective: true, a valid anchor and deltaFiles: [] (or non-string elements) therefore reads as fix-audit at the roster, topology gate, round-cap tier and compose floor arm, but as full-scope at the brief builder — the exact two-reader disagreement this function's own comment says it exists to prevent ('a hand-edited plan claiming the posture over a full-range diff must not shrink the roster'). Such a plan drops Agent 0, flips a small plan to territory fan-out, records the round cap as 5 instead of 10, degrades every brief to full-scope, and defers sub-Critical findings beside a 'Round shape: fix-audit' disclosure describing a shape the round's briefs never ran. Honest captures never produce this shape (empty delta → upToDate before posture is written), so the trigger is a corrupted/hand-edited plan — the stated threat model. Reported independently by three dimension agents; confirmed by probe.
Witness (probe on the unmodified PR, scratch tree):
isFixAuditRound(DIVERGENT) = true
isTerritoryFanOut(small) = false | with DIVERGENT = true
reverseAuditRoundTier(small) = 10 | with DIVERGENT = 5
requiredAgents(DIVERGENT) has Agent 0 = false | keys = [chunk-1, chunk-2, test-matrix, 1b, 1c, 7]
brief(DIVERGENT): INCREMENTAL frame = false | Fix-audit frame = false
compose(DIVERGENT): floorEnforced = [0] | body has "fix-audit round" = true
After the parity fix below every axis flips back (isFixAuditRound=false, tier 10, Agent 0 present, floorEnforced=[]) while the honest valid shape stays admitted.
| typeof scope.anchor === 'string' && | |
| scope.anchor !== '' && | |
| Array.isArray(scope.deltaFiles) | |
| typeof scope.anchor === 'string' && | |
| scope.anchor !== '' && | |
| Array.isArray(scope.deltaFiles) && | |
| scope.deltaFiles.length > 0 && | |
| scope.deltaFiles.every((p) => typeof p === 'string' && p !== '') |
Mirror the same element/empty check in fixAuditShapeFacts (compose-review.ts), or extract one shared predicate all three readers call.
中文说明
该 scope 校验栏严格弱于其声称对齐的配对读取器。agent-prompt.ts 中的 incrementalScopeOf 还会拒绝非字符串的 deltaFiles 元素以及两者皆空的情况(deltaFiles.length === 0 && interaction.length === 0 → null),而 compose-review.ts 的 fixAuditShapeFacts 重复了同样宽松的校验。一个携带 posture: 'critical'、effective: true、有效 anchor 但 deltaFiles: [](或含非字符串元素)的 plan,会在 roster、拓扑门、轮次上限档位与 compose 下限臂上被读作 fix-audit,却在 brief 构建器上退化为全量形态——正是本函数注释声称要防止的"两个读取器对同一 plan 各执一词"。这样的 plan 会丢掉 Agent 0、把小 plan 翻转为领地扇出、把轮次上限从 10 记为 5、让所有 brief 退化为全量形态,并在延后 sub-Critical 发现的同时发布"Round shape: fix-audit"披露——描述的却是该轮 brief 从未运行的形态。诚实的 capture 不会产生此形状(空 delta 在写入 posture 前即 upToDate),触发条件是损坏/手工编辑的 plan——即本函数声明的威胁模型。三个维度 agent 独立报告,probe 确认。
建议按上方 suggestion 收紧校验(并在 fixAuditShapeFacts 中做同样的镜像,或抽取一个共享谓词供三个读取器调用)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| // divergence is an explicit `suggestion` floor this round beside a stale | ||
| // plan posture — and there the body must say the floor was open rather | ||
| // than claim a deferral beside its own inline Suggestions. | ||
| const fixAuditFloorEngaged = convergence?.criticalFloorKind !== undefined; |
There was a problem hiding this comment.
[Critical] R1-2: The deferral claim keys off the wrong floor reading. criticalFloorKind (the reporting read) folds an ABSENT model-written severityFloor to auto, so the new fix-audit arm at :578 fires; but the enforcement reads (floorEnforcedReroute / criticalFloorInEffect) normalize an absent floor to undefined, where no arm of floorResolvesCritical fires. Absence is documented as reachable by this module's own comment ('omit what does not apply'), and under the default configuration recordedSeverityFloor recovers nothing to override the state. So an honest fix-audit round whose compose state omits severityFloor posts 'Findings below Critical were recorded and deferred, never posted.' and stamps the ledger marker floor: 'c' while enforcement fails open and drafted Suggestions post inline in the same body — beside the mechanism-health note accusing the same body of the floor being 'engaged in name and not in effect'. Pre-PR, the absent-floor reporting/enforcement gap never posted a text asserting deferral had happened; this diff converts that gap into a posted false statement. Confirmed by probe.
Witness (probe: fix-audit plan + absent severityFloor + one drafted Suggestion):
floorEnforced = []
body has "Findings below Critical were recorded and deferred, never posted." = true
body has "the posting floor ... resolved to critical, and Suggestion-level findings posted inline anyway" = true
marker = {"floor":"c","posted":1} (the Suggestion recorded as POSTED)
Contrast arm: with severityFloor: 'auto' present, floorEnforced = [0].
| const fixAuditFloorEngaged = convergence?.criticalFloorKind !== undefined; | |
| const fixAuditFloorEngaged = convergence?.floorEnforcementEngaged === true; |
floorEnforcementEngaged is already carried on the convergence object (:1716-1721). Then the engaged sentence only posts when the enforcement reading held, and the OPEN sentence posts exactly when nothing was withheld.
中文说明
延后声明引用了错误的下限读取。criticalFloorKind(报告读取)会把缺失的模型写入 severityFloor 折叠为 auto,从而触发 :578 的新 fix-audit 臂;但强制读取(floorEnforcedReroute / criticalFloorInEffect)把缺失的下限归一化为 undefined,floorResolvesCritical 没有任何臂会触发。缺失是本模块注释明确可达的状态("不适用则省略"),且默认配置下 recordedSeverityFloor 不会恢复出任何值来覆盖它。于是,一个省略了 severityFloor 的诚实 fix-audit 轮次会发布"Findings below Critical were recorded and deferred, never posted."、把台账标记盖为 floor: 'c',而强制侧却放行、让起草的 Suggestion 原样发布在同一篇正文里——旁边还跟着机制健康提示指责该正文"下限有名无实"。PR 之前,缺失下限的报告/强制分歧从未发布过"已延后"的断言文本;本 diff 把这个分歧变成了发布出去的错误陈述。probe 确认。
建议按上方 suggestion 改为以强制读取为准(floorEnforcementEngaged 已在 convergence 对象上,:1716-1721):只有强制读取成立时才发布"已延后"句;未扣留任何发现时恰好发布 OPEN 句。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| **Whole-diff agents — launched alongside the chunk agents, in the same response.** | ||
|
|
||
| **Their blocks are already in the `--roster` output above — you have them.** Roles there: `0` (PR reviews), `1b` (when the diff removes anything, or a repository context requires it), `1c`, `test-matrix`, `7` (same-repo), and for a **heavy** file three more, one per checklist slice (their blocks are labelled `Invariant agent A|B|C: … — <path>`). Pass each **verbatim**. To rebuild one for a relaunch: `--role <role>` (an invariant agent adds `--file <path>`). `check-coverage` derives the same list from the plan and will name any role that did not run. | ||
| **Their blocks are already in the `--roster` output above — you have them.** Roles there: `0` (PR reviews — but not on a fix-audit round, whose roster deliberately omits it; see Step 3's topology note), `1b` (when the diff removes anything, or a repository context requires it), `1c`, `test-matrix`, `7` (same-repo), and for a **heavy** file three more, one per checklist slice (their blocks are labelled `Invariant agent A|B|C: … — <path>`). Pass each **verbatim**. To rebuild one for a relaunch: `--role <role>` (an invariant agent adds `--file <path>`). `check-coverage` derives the same list from the plan and will name any role that did not run. |
There was a problem hiding this comment.
[Suggestion] R1-3: This cross-reference points at the wrong step. The fix-audit topology bullet it names lives in Step 1's '### Diff capture and the review topology' subsection (line 299 of this file), and Step 3 contains no topology note — Step 3 itself delegates topology back to Step 1 ('as the topology gate in Step 1 decided'). On a fix-audit round the roster omits Agent 0, and this paragraph exists to keep the orchestrator from treating that omission as a mistake; an orchestrator following the reference into Step 3 finds nothing and is left without the explanation — risking a hand-built Agent 0 relaunch or re-deriving the topology from the wrong section. The identical wrong reference was also added near line 166 ('see Step 3's topology note and Step 5's posture narrowing' — the Step 5 half of that one is correct).
Suggested fix: change both occurrences to see Step 1's topology note.
中文说明
该交叉引用指向了错误的步骤:它所指代的 fix-audit 拓扑条目位于 Step 1 的 "### Diff capture and the review topology" 小节(本文件第 299 行),而 Step 3 并没有拓扑说明——Step 3 自己就把拓扑裁决委托回 Step 1("as the topology gate in Step 1 decided")。fix-audit 轮的 roster 会省略 Agent 0,本段的存在正是为了让编排者不把这一省略当作错误;若编排者按引用去 Step 3 查找,会一无所获、失去解释——可能手工补发 Agent 0,或从错误的章节重推拓扑。约第 166 行新增的引用存在同样的错误("see Step 3's topology note and Step 5's posture narrowing"——其中 Step 5 的半句是正确的)。
建议将两处均改为 see Step 1's topology note。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
|
||
| - **Incremental review check** (high effort only — neither low nor medium consults or updates the cache): read `.qwen/review-cache/pr-<n>.json` **before** `fetch-pr` (it is a local file; nothing about it needs the fetch) and, when it holds a `lastCommitSha`, pass BOTH fields to the fetch verbatim: `--since <lastCommitSha> --since-model <lastModelId>` (omit `--since-model` when the cache has no `lastModelId`; do not substitute anything for it). **Copy them; do not compare them to anything.** The same-model gate is ruled inside `fetch-pr`, over the identity the runtime published — "clean up to `lastCommitSha`" is the recorded identity's verdict, and the command validates an anchor against the HISTORY, never against who certified it, so an anchor from another identity is ancestrally perfect and would scope this round past code it never reviewed. A hand-applied version of that gate was wrong every time it was written, because `{{model}}` interpolates the BARE model id while every identity the CLI records is provider-qualified: two provider configurations exposing one model name compared equal and passed each other's gate. When the gate refuses, the report says `cross-model-anchor` and the round reviews the full diff. Read the cache's `findings` ledger either way (Step 6 owes each entry a ruling; the work list carries across models, only the anchor does not). **You never run `git` against an anchor yourself** — no `git diff <sha>..HEAD`, no `cat-file`, no `merge-base --is-ancestor`: the command validates the anchor against the fetched history and computes the scoped diff and chunk plan in one pass, because a hand-run check is one a run can skip, and the hand-computed delta was exactly the shape this skill forbids everywhere else (the diff is a file the CLI writes, never a command you run). The report's `incremental` field is the decision; act on it with `lastModelId` from the cache and the current model ID (`{{model}}`): | ||
| - `effective: true` (no `upToDate`) → the report's diff and plan ARE the incremental scope (`since..head`); continue with them exactly as with a full plan. The file set is **widened by one import hop**: a still-clean source file that imports a changed one re-enters the scope with its own full-range hunks, because the round before cleared it against the callee's OLD shape. `incremental.scope` names each file's class — `deltaFiles` (touched since the anchor), `interaction[]` (widened back in, each with the edges that did it), `contextFileCount` (weighed and passed over) — and a chunk brief built for an interaction file points its agent at that seam instead of a from-scratch re-review. **Also read the cache's `findings` ledger** (older caches have none — then there is nothing to track): these are the previous round's findings with their ids, and Step 6 owes each of them a ruling this round. (Reachable only under a matching identity: the gate inside the command is what keeps a cross-model anchor from scoping anything.) | ||
| - `effective: true` (no `upToDate`) → the report's diff and plan ARE the incremental scope (`since..head`); continue with them exactly as with a full plan. The file set is **widened by one import hop**: a still-clean source file that imports a changed one re-enters the scope with its own full-range hunks, because the round before cleared it against the callee's OLD shape. `incremental.scope` names each file's class — `deltaFiles` (touched since the anchor), `interaction[]` (widened back in, each with the edges that did it), `contextFileCount` (weighed and passed over) — and a chunk brief built for an interaction file points its agent at that seam instead of a from-scratch re-review. On a round the capture resolved to the **critical posting posture** the report also carries `incremental.posture: "critical"` with its `postureCause` (`round`, `flat-trend`, or `explicit` — the same facts Step 6's floor resolution reads, predicted from the side file and the CLI-recorded invocation), and the round runs the **fix-audit shape**: see Step 3's topology note and Step 5's posture narrowing. On such a round the interaction files re-enter **seam-bounded** — each `interaction[]` entry then carries a `seam: {kept, total}` census of the hunks republished (the ones displaying a line that imports or uses what changed; the rest were cleared by an earlier round and are not re-shown), and a file whose census is `kept: 0` arrives as a header-only section that still lands in a chunk, so its agent is still briefed to answer the seam question from the worktree. **Also read the cache's `findings` ledger** (older caches have none — then there is nothing to track): these are the previous round's findings with their ids, and Step 6 owes each of them a ruling this round. (Reachable only under a matching identity: the gate inside the command is what keeps a cross-model anchor from scoping anything.) |
There was a problem hiding this comment.
[Suggestion] R1-3 (second occurrence): Same wrong cross-reference as the one at line 405 — 'see Step 3's topology note' should point at Step 1's topology subsection, where the fix-audit bullet actually lives (line 299). The Step 5 half of this sentence is correct (the posture-narrowing text at line 709 is inside Step 5).
Suggested fix: see Step 1's topology note and Step 5's posture narrowing.
中文说明
与第 405 处相同的错误交叉引用——"see Step 3's topology note" 应指向 Step 1 的拓扑小节(fix-audit 条目实际所在的第 299 行)。本句中 Step 5 的半句是正确的(第 709 行的姿态收窄文本位于 Step 5 内)。
建议改为:see Step 1's topology note and Step 5's posture narrowing。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| if (narrowing != null && !narrowing.deltaChunkIds.has(chunkId)) { | ||
| const latest = audits[audits.length - 1]; | ||
| if (latest !== undefined && latest.outcome === 'dry') { |
There was a problem hiding this comment.
[Suggestion] R1-4: The narrowing's distinguishing rule — a non-delta chunk leaves the wave after ONE substantive dry audit, where ordinary retirement needs two — has no discriminating test. Every narrowed chunk in the new suites is dry in rounds 1 AND 2 (retirement.test.ts and agent-prompt.test.ts alike), so ordinary two-dry retirement would produce identical schedules: mutating the one-receipt check to the two-consecutive-dry bar survives all 149 retirement tests and both agent-prompt fix-audit tests green, while the waves would silently re-launch proven-dry non-delta territories every round — re-spending exactly the auditor cost this feature removes (the measured 16-round / ~50-runner-hour loop).
Witness: probe fixture with a non-delta chunk that YIELDS round 1 and is DRY round 2 — real code round 3 gives due=[] narrowed=[{chunkId:14,dryRound:2}] converged=true; the two-dry mutant gives due=[14] narrowed=[] converged=false (probe fails on the mutant, all existing tests stay green on it).
Suggested fix: add a fixture where a non-delta chunk yields in round 1 and dries in round 2; at round 3 expect narrowed: [{ chunkId, dryRound: 2 }] and the chunk absent from due — under the ordinary rules that history is hot, so this case alone distinguishes the one-receipt bar.
中文说明
收窄的区分性规则——非 delta chunk 在一次实质性干燥审计后即离开波次(普通退役需要两次)——没有区分性测试。新测试套件里每个被收窄的 chunk 都在第 1、2 轮连续干燥(retirement.test.ts 与 agent-prompt.test.ts 皆然),因此把单次收据判定变异为"连续两次干燥"也能让全部 149 个 retirement 测试与两个 agent-prompt fix-audit 测试保持绿色——而波次会悄悄每轮重启已证干燥的非 delta 领地,重新付出本特性要消除的审计成本(测得的 16 轮 / 约 50 runner 小时循环)。
建议:新增一个 fixture——某非 delta chunk 第 1 轮 YIELD、第 2 轮 DRY;第 3 轮断言 narrowed: [{ chunkId, dryRound: 2 }] 且该 chunk 不在 due 中——按普通规则该历史是热态,只有这个用例能区分单次收据门槛。
— qwen3.8-max via Qwen Code /review (v0.22.0)
There was a problem hiding this comment.
Deferred to the next round (batch bound: this round implemented the two Criticals first plus six smaller findings). The finding is accepted as described — every narrowed chunk in the current suites is dry in rounds 1 AND 2, so the one-receipt narrowing bar has no discriminating witness; the proposed fixture (non-delta chunk yields round 1, dries round 2, expect narrowed at round 3) is the right shape and will land next round.
中文说明
延后到下一轮处理(本轮批次上限:优先实现了两条 Critical 与六条较小的发现)。该发现按描述接受——当前套件中每个被收窄的 chunk 都在第 1、2 轮连续干燥,因此单次收据收窄门槛没有区分性见证;所建议的 fixture(非 delta chunk 第 1 轮 YIELD、第 2 轮 DRY,第 3 轮断言进入 narrowed)形态正确,将在下一轮落地。
| - `chunks[]` — contiguous, non-overlapping line ranges tiling the whole diff. Each entry has `id`, `startLine`, `endLine` (1-based, inclusive), `lines`, `chars`, an `oversized` flag, and `files[]` naming the source files and new-side line ranges it covers. A chunk with `oversized: true` may exceed what one `read_file` call returns. | ||
| - `files[]` — per-file `kind` (`source` / `test` / `generated`), `hunks[]` new-side ranges (Step 7 validates comment anchors against these), `addedRanges[]` and `diffRange` (present only on `heavy` files — the exact lines the PR wrote, and where that file's own diff lives, so an invariant agent can see what was deleted), change counts, and the `heavy` flag | ||
| - `budget` — how much walking the **size-elastic** parts of this run owe, sized from `srcDiffLines` except that an all-non-source diff (docs, lockfiles) counts its total lines at an eighth rate, so the size these tiers read is `effective = max(srcDiffLines, floor(diffLines / 8))`; recorded here rather than passed as a flag so every reader sees one number. `inlineAngles` and `sweep` scope Step 3C's low pass; `specialistCap` is the Agent 8 ceiling (**0** below 80 source lines — "one domain dominates the diff" is a judgement, and a judgement made about forty lines finds a dominant domain every time, because forty lines are usually all one thing — **and 0 again for a huge diff (effective ≥ 3000)**, where an Agent 8 whole-diff pass on top of the base fan-out is the marginal cost that tips a review too big to finish into posting nothing); `verifyShard` is Step 4's findings-per-verifier; `reverseAuditRounds` is the reverse-audit loop's round cap, **one value per topology**: **10** on a Step 3A diff, **5** on a Step 3B one, **3 for a huge diff** (effective ≥ 3000 lines) — but the huge reduction applies **only when the run has a deadline** (`QWEN_REVIEW_DEADLINE_EPOCH`); without a clock a huge diff is just a large 3B diff and gets 5. One number cannot price all three, because what is being capped is a _round_ and a round costs one auditor on 3A, one auditor per non-retired chunk on 3B, and ~90 minutes on a 4,000-line PR — where five rounds (450 min) alone exceed the six-hour ceiling before the fan-out and tail are counted, and the 6-hour timeouts that posted nothing were 4,000-5,300-line PRs (measured; DESIGN.md — The six-hour timeouts). Ten on 3A because the marginal round there is a single agent against a whole review of 19-30 calls: five was the 3B arithmetic applied where it does not hold, and it stopped loops that were still confirming Criticals to save ~5 calls. Three when huge is not a claim that a huge diff converges sooner — it plainly does not, and on recall it deserves more rounds than a small one, not fewer; it is a claim that five ~90-minute rounds do not fit a six-hour ceiling, and a review killed mid-flight posts nothing at all. Where there is no ceiling the premise is absent and so is the reduction. Three is one audit round above the convergence floor of two — the all-dry rounds-1-and-2 shape converges under any cap of two or more, since the convergence check runs before the cap gate; the extra round buys hot chunks one more pass. An operator may LOWER the tier for every review through the `review.reverseAuditRounds` setting (honoured from the User, System and SystemDefaults scopes — never from the repository's own `.qwen/settings.json`; a value below 3, or above the tier, is ignored rather than clamped, so it leaves the tier alone) — the capture command resolves it into this field, so you read one number here either way and never learn that a setting was involved; it can never RAISE a tier. The `agent-prompt` builder enforces the cap itself (a `ROUND CAP:` refusal, exit 4, that writes a marker `compose-review` caps on — same contract as the deadline gate below), so you never count rounds yourself. `agentToolBudget` is the base rate of the soft tool-call ceiling `agent-prompt` bakes into every finder and auditor brief — not the verifier's, not Agent 7's, and not Agent 0's, whose mandatory work scales with the linked issues rather than the diff. The ceiling is per **launch**: a scoped agent (a chunk, a heavy file) gets an allowance derived from its own territory — never above the plan's recorded allowance, which is clamped into the budget's own band in both directions, so the plan stays the one number every launch answers to — and every launch's assigned reads ride on top of the allowance rather than inside it, so a huge diff's mandatory chunk reads can never exhaust the exploration a whole-diff role owes — because a wave's wall clock is its slowest agent and the slowest agent is reliably one that kept exploring past any recall gain: the same 14-agent fan-out has measured 11.7 and 41 minutes on comparable diffs, the difference being individual agents spending 40-100 calls walking the tree (measured; DESIGN.md — The forty-one minute wave). The ceiling is soft and the briefs restate the recall rule beside it: at the budget an agent stops **exploring**, never reporting — findings in hand are filed, and each stopped check is disclosed on its own line in the fixed form `Budget gap: <the check>`, which `check-coverage` parses out of the transcripts (its report's `budgetGaps`) — see Step 3D for the ruling each gap is owed. **It never scales a dimension away** — which agents a review owes is the roster's answer and the roster reads `effort`, so a size input cannot become a back door into shrinking coverage. Nothing here is yours to override: a budget the caller can inflate is a budget that gets inflated. **A plan with no `budget` field** (written by an older CLI — the version-skew this skill has already measured once) falls back to the pre-budget flat behaviour: walk all six angles, run the sweep, cap Agent 8 at 2, shard verification at 8. Those four err toward more coverage, never less. The round cap is the one exception and is worth naming rather than lumping in: **in a run that has a deadline**, a field-less **huge** plan reads 3 where the flat fallback read 5 — deliberately _less_, because that tier is a finishability ruling and the reviews it exists for are the ones that ran six hours and posted nothing. Without a deadline it reads 5, the same as the flat fallback. | ||
| - `budget` — how much walking the **size-elastic** parts of this run owe, sized from `srcDiffLines` except that an all-non-source diff (docs, lockfiles) counts its total lines at an eighth rate, so the size these tiers read is `effective = max(srcDiffLines, floor(diffLines / 8))`; recorded here rather than passed as a flag so every reader sees one number. `inlineAngles` and `sweep` scope Step 3C's low pass; `specialistCap` is the Agent 8 ceiling (**0** below 80 source lines — "one domain dominates the diff" is a judgement, and a judgement made about forty lines finds a dominant domain every time, because forty lines are usually all one thing — **and 0 again for a huge diff (effective ≥ 3000)**, where an Agent 8 whole-diff pass on top of the base fan-out is the marginal cost that tips a review too big to finish into posting nothing); `verifyShard` is Step 4's findings-per-verifier; `reverseAuditRounds` is the reverse-audit loop's round cap, **one value per topology**: **10** on a Step 3A diff, **5** on a Step 3B one (a fix-audit round reads this tier whatever its narrowed sizes say — the posture flips the same gate the tier reads), **3 for a huge diff** (effective ≥ 3000 lines) — but the huge reduction applies **only when the run has a deadline** (`QWEN_REVIEW_DEADLINE_EPOCH`); without a clock a huge diff is just a large 3B diff and gets 5. One number cannot price all three, because what is being capped is a _round_ and a round costs one auditor on 3A, one auditor per non-retired chunk on 3B, and ~90 minutes on a 4,000-line PR — where five rounds (450 min) alone exceed the six-hour ceiling before the fan-out and tail are counted, and the 6-hour timeouts that posted nothing were 4,000-5,300-line PRs (measured; DESIGN.md — The six-hour timeouts). Ten on 3A because the marginal round there is a single agent against a whole review of 19-30 calls: five was the 3B arithmetic applied where it does not hold, and it stopped loops that were still confirming Criticals to save ~5 calls. Three when huge is not a claim that a huge diff converges sooner — it plainly does not, and on recall it deserves more rounds than a small one, not fewer; it is a claim that five ~90-minute rounds do not fit a six-hour ceiling, and a review killed mid-flight posts nothing at all. Where there is no ceiling the premise is absent and so is the reduction. Three is one audit round above the convergence floor of two — the all-dry rounds-1-and-2 shape converges under any cap of two or more, since the convergence check runs before the cap gate; the extra round buys hot chunks one more pass. An operator may LOWER the tier for every review through the `review.reverseAuditRounds` setting (honoured from the User, System and SystemDefaults scopes — never from the repository's own `.qwen/settings.json`; a value below 3, or above the tier, is ignored rather than clamped, so it leaves the tier alone) — the capture command resolves it into this field, so you read one number here either way and never learn that a setting was involved; it can never RAISE a tier. The `agent-prompt` builder enforces the cap itself (a `ROUND CAP:` refusal, exit 4, that writes a marker `compose-review` caps on — same contract as the deadline gate below), so you never count rounds yourself. `agentToolBudget` is the base rate of the soft tool-call ceiling `agent-prompt` bakes into every finder and auditor brief — not the verifier's, not Agent 7's, and not Agent 0's, whose mandatory work scales with the linked issues rather than the diff. The ceiling is per **launch**: a scoped agent (a chunk, a heavy file) gets an allowance derived from its own territory — never above the plan's recorded allowance, which is clamped into the budget's own band in both directions, so the plan stays the one number every launch answers to — and every launch's assigned reads ride on top of the allowance rather than inside it, so a huge diff's mandatory chunk reads can never exhaust the exploration a whole-diff role owes — because a wave's wall clock is its slowest agent and the slowest agent is reliably one that kept exploring past any recall gain: the same 14-agent fan-out has measured 11.7 and 41 minutes on comparable diffs, the difference being individual agents spending 40-100 calls walking the tree (measured; DESIGN.md — The forty-one minute wave). The ceiling is soft and the briefs restate the recall rule beside it: at the budget an agent stops **exploring**, never reporting — findings in hand are filed, and each stopped check is disclosed on its own line in the fixed form `Budget gap: <the check>`, which `check-coverage` parses out of the transcripts (its report's `budgetGaps`) — see Step 3D for the ruling each gap is owed. **It never scales a dimension away** — which agents a review owes is the roster's answer and the roster reads `effort`, so a size input cannot become a back door into shrinking coverage. Nothing here is yours to override: a budget the caller can inflate is a budget that gets inflated. **A plan with no `budget` field** (written by an older CLI — the version-skew this skill has already measured once) falls back to the pre-budget flat behaviour: walk all six angles, run the sweep, cap Agent 8 at 2, shard verification at 8. Those four err toward more coverage, never less. The round cap is the one exception and is worth naming rather than lumping in: **in a run that has a deadline**, a field-less **huge** plan reads 3 where the flat fallback read 5 — deliberately _less_, because that tier is a finishability ruling and the reviews it exists for are the ones that ran six hours and posted nothing. Without a deadline it reads 5, the same as the flat fallback. |
There was a problem hiding this comment.
[Suggestion] R1-15: The new fix-audit parenthetical — 'a fix-audit round reads this tier whatever its narrowed sizes say' — contradicts reverseAuditRoundTier (budget.ts:361-377), which checks the huge gate (effective ≥ 3000 → 3 with a deadline) BEFORE the posture flip in isTerritoryFanOut; its docblock says 'The huge tier is checked first and wins', and budget.test.ts pins exactly that (reverseAuditRoundTier({srcDiffLines: 4000, diffLines: 5000, ...POSTURE}, true) === 3, 'The huge finishability ruling still wins where there is a wall' — ran green at this commit). There is no size gate on posture capture (fetch-pr resolves posture from the recorded floor and side ledger only), so a time-budgeted CI run re-reviewing a ≥ 3000-effective-line delta under the posture records budget.reverseAuditRounds: 3 while this prose tells the executing model 5 'whatever its narrowed sizes say' — a self-contradiction in exactly the state the model must narrate (cap stops, #9242-style anomaly rulings). The sibling claim near line 299 ('the round-cap tier (the 3B tier of 5)') needs the same qualification.
Suggested fix: qualify the parenthetical — '(a fix-audit round below the huge floor reads this tier whatever its narrowed sizes say — the posture flips the same gate the tier reads, but the huge finishability ruling still wins where there is a wall)'.
中文说明
新增的 fix-audit 括注——"fix-audit 轮无论其收窄后的尺寸如何都读取该档位"——与 reverseAuditRoundTier(budget.ts:361-377)矛盾:该函数在 isTerritoryFanOut 的姿态翻转之前先检查巨型门(有效行 ≥ 3000 且有截止时间 → 3);其文档块写明"巨型档先检查且获胜",budget.test.ts 恰好钉住了这一点(reverseAuditRoundTier({srcDiffLines: 4000, diffLines: 5000, ...POSTURE}, true) === 3,"有墙时巨型可完成性裁决仍然获胜"——在本提交上运行通过)。姿态捕获没有尺寸门(fetch-pr 只依据已记录下限与 side ledger 决议姿态),因此一个有截止时间预算的 CI 运行在姿态下重审 ≥ 3000 有效行的 delta 时会记录 budget.reverseAuditRounds: 3,而此处行文却告诉执行模型"无论收窄尺寸如何"都是 5——恰恰在模型必须叙述的状态(上限停止、#9242 式异常裁决)上自相矛盾。约第 299 行的孪生表述("round-cap tier(3B 档的 5)")需要同样的限定。
建议:限定括注——"(低于巨型档的 fix-audit 轮无论其收窄后的尺寸如何都读取该档位——姿态翻转的是档位读取的同一道门,但有墙时巨型可完成性裁决仍然获胜)"。
— qwen3.8-max via Qwen Code /review (v0.22.0)
There was a problem hiding this comment.
Deferred to the next round (batch bound). Accepted: 'a fix-audit round reads this tier whatever its narrowed sizes say' contradicts reverseAuditRoundTier, whose huge gate is checked first and wins (pinned by budget.test.ts); the parenthetical at SKILL.md:242 and its sibling near line 299 will be qualified next round.
中文说明
延后到下一轮处理(批次上限)。接受该发现:“fix-audit 轮无论其收窄后的尺寸如何都读取该档位”与 reverseAuditRoundTier 矛盾——巨型门先检查且获胜(budget.test.ts 已钉住);SKILL.md:242 的括注与约第 299 行的孪生表述将在下一轮限定。
|
|
||
| **Choose the topology from `srcDiffLines`, not from `diffLines`.** | ||
|
|
||
| - **the plan carries `incremental.posture: "critical"`** — a **fix-audit round** (#10104): use Step 3B whatever the sizes say. The narrowed delta is usually 3A-sized, but the posture defers everything below Critical, so the round owes one accountable reader per territory of the fix commits — not thirteen dimension lenses re-walking a delta whose sub-Critical yield is deferred wholesale. The CLI's own gate reads the same plan field, so the roster, the round-cap tier (the 3B tier of 5) and the #9242 stderr note all agree with this routing; the roster the plan builds already reflects the shape (no Agent 0 — issue fidelity was ruled by the full rounds before the posture engaged, and a fix commit that removes required behaviour is the removed-behavior audit's territory, which the round keeps). Tell the user: "Critical posture (<postureCause>): fix-audit round over the commits since the last round." |
There was a problem hiding this comment.
[Suggestion] R1-16: 'thirteen dimension lenses' contradicts this file's own lens definition six lines below (line 305, unchanged): 'the fourteen lenses it deserves ("lenses" = the diff-reading dimension agents: the sixteen minus Issue Fidelity and Build & Test)' — 16 − 2 = 14, and the roster corroborates fourteen diff-reading 3A roles at this commit (1a/1b/1c/1d/1e, 2, 3a/3b/3c, 4, 5, 6a/6b/6c; 1d and conditional 1e exist at roster.ts:278-279). The new isTerritoryFanOut comment in budget.ts:305-307 carries the same 'thirteen' off-by-one. Any future dimension-roster change must keep this file's agent counts in lockstep (16/15/14/11/10/9 all appear as load-bearing prose); an editor reconciling the counts meets 13 (new text, twice) and 14 (the section's arithmetic definition) six lines apart with no rule to pick between them, and the stale count survives in the sentence justifying the fix-audit trade.
Suggested fix: use 'fourteen' in both new sites (this bullet and the budget.ts comment) to match the definition at line 305.
中文说明
"thirteen dimension lenses" 与本文件下方六行处的透镜定义(第 305 行,未修改)矛盾:"the fourteen lenses it deserves('lenses' = 读 diff 的维度 agents:十六个减去 Issue Fidelity 与 Build & Test)"——16 − 2 = 14,且 roster 在本提交上证实了十四个读 diff 的 3A 角色(1a/1b/1c/1d/1e、2、3a/3b/3c、4、5、6a/6b/6c;1d 与条件性的 1e 存在于 roster.ts:278-279)。budget.ts:305-307 新增的 isTerritoryFanOut 注释带有同样的 "thirteen" 差一错误。未来任何维度 roster 变更都必须让本文件的 agent 计数保持联动(16/15/14/11/10/9 均以承重行文出现);编辑核对计数时会在相隔六行处遇到 13(新增文本,两处)与 14(本节的算术定义)而无从取舍,陈旧计数会存活在为 fix-audit 代价辩护的句子里。
建议:在两个新增位置(本条目与 budget.ts 注释)改用 'fourteen',与第 305 行的定义一致。
— qwen3.8-max via Qwen Code /review (v0.22.0)
| ...retirementNote, | ||
| ...narrowingNote, | ||
| ].join('\n\n'), |
There was a problem hiding this comment.
[Suggestion] R1-17: The launch preamble's tail grammar — 'the output ends with an end-of-round line — followed by the retirement note, when there is one' — was not updated when this diff added the posture-narrowing note (the ...narrowingNote line anchored here) to the output tail. The diff updated the sibling scope sentence in the same header ('the notes after the end-of-round line say which — relay them') but left this enumeration naming only the retirement note. On the feature's primary path — a fix-audit round where narrowing fires and nothing retires (the new test's round-3 shape: skipped=0, narrowed=[chunk 14]) — the tail after the end-of-round line contains ONLY the narrowing note, which the preamble never announces; a structure-following orchestrator validating the output against this header can flag the tail as malformed or drop the unannounced disclosure the feature's contract promises ('every reduction is disclosed … in the round's posture narrowing note'). Reported in two audit waves.
Suggested fix: update the preamble with the scope clause — '…followed by the retirement and posture-narrowing notes, when there are any.'
中文说明
启动前言的尾部语法——"输出以 end-of-round 行结束——其后在有退役 note 时跟随退役 note"——在本 diff 把姿态收窄 note(锚点处的 ...narrowingNote 行)加入输出尾部时未同步更新。diff 更新了同一头部中的孪生范围句("end-of-round 行之后的 notes 说明情况——转述它们"),却让此处列举仍然只点名退役 note。在本特性的主要路径上——收窄生效而无可退役对象的 fix-audit 轮(新测试的第 3 轮形态:skipped=0、narrowed=[chunk 14])——end-of-round 行之后的尾部只含收窄 note,而前言从未宣告它;遵循结构的编排者按此头部校验输出时,可能把尾部判为畸形,或丢弃特性契约承诺的未宣告披露("所有收窄都在轮次的 posture narrowing note 中披露")。该问题在两个审计波次中被报告。
建议:用范围句更新前言——"……其后在有退役与姿态收窄 notes 时跟随它们。"
— qwen3.8-max via Qwen Code /review (v0.22.0)
There was a problem hiding this comment.
Deferred to the next round (batch bound). Accepted: the launch preamble's tail grammar names only the retirement note and never announces the posture-narrowing note this diff added to the output tail; the scope clause ('the retirement and posture-narrowing notes, when there are any') will land next round.
中文说明
延后到下一轮处理(批次上限)。接受该发现:启动前言的尾部语法只点名退役 note,从未宣告本 diff 加入输出尾部的姿态收窄 note;范围句(“其后在有退役与姿态收窄 notes 时跟随它们”)将在下一轮落地。
| * It lives here beside `isTerritoryFanOut` because that predicate is its one | ||
| * structural consumer and this module must stay import-free. |
There was a problem hiding this comment.
[Suggestion] R1-18: This doc block claims isTerritoryFanOut is the ONE structural consumer of isFixAuditRound, but the same commit wires three more direct consumers: roster.ts:229 (!isFixAuditRound(plan) gates Agent 0), agent-prompt.ts:776 (the fix-audit brief frame), agent-prompt.ts:2810 (postureNarrowing), plus the roster.ts:33 re-export. No reading of 'one structural consumer' is true at the commit. The cost is concrete: the weak-scope-bar defect (R1-1 above) will be fixed in this very function, and a fixer trusting this comment scopes the edit to the topology flip alone, while the same edit simultaneously changes which rounds drop Agent 0, which chunk agents get the fix-audit brief frame, and which rounds postureNarrowing narrows — unreviewed side effects on three consumers the comment says do not exist.
Suggested fix: reword to name the real consumer set, e.g. 'It lives here beside isTerritoryFanOut because this module must stay import-free; the topology gate reads it here, and the roster's Agent-0 exclusion plus the brief builder's posture frame read it back directly.'
中文说明
该文档块声称 isTerritoryFanOut 是 isFixAuditRound 的唯一结构消费者,但同一提交接入了另外三个直接消费者:roster.ts:229(!isFixAuditRound(plan) 门控 Agent 0)、agent-prompt.ts:776(fix-audit brief 框架)、agent-prompt.ts:2810(postureNarrowing),外加 roster.ts:33 的再导出。在本提交上,"唯一结构消费者"没有任何读法成立。代价是具体的:上方 R1-1 的弱校验栏缺陷将在本函数内修复,若修复者信任此注释、只把编辑范围限定在拓扑翻转上,同一处编辑却同时改变哪些轮次丢掉 Agent 0、哪些 chunk agent 获得 fix-audit brief 框架、哪些轮次被 postureNarrowing 收窄——对注释声称不存在的三个消费者造成未经审查的副作用。
建议:改写以点名真实的消费者集合,例如"它放在 isTerritoryFanOut 旁,因为本模块必须保持无导入;拓扑门在此读取它,roster 的 Agent-0 排除与 brief 构建器的姿态框架则直接回读。"
— qwen3.8-max via Qwen Code /review (v0.22.0)
| // two constants this resolution does, so the two cannot drift. Re-exported | ||
| // here because this module is where every earlier reader imported it from. | ||
| export { FLAT_STREAK_TO_ENGAGE } from './lib/posture.js'; |
There was a problem hiding this comment.
[Suggestion] R1-19: The added re-export of FLAT_STREAK_TO_ENGAGE has zero importers anywhere, and its justification comment is factually false. Exhaustive grep: the name's only readers post-PR are lib/posture.ts (definer), lib/posture.test.ts (imports from ./posture.js), and this module's own import (used internally at :1591, :1630); the modules importing from compose-review.js (submit.ts, save-artifact.ts, compose-review.test.ts, submit-aone.test.ts) do not take this name, and no barrel re-export exists. At merge base, git grep outside this file finds no importer either — there were no 'earlier readers' this module served. The PR moves the constant to lib/posture.ts precisely 'so the two cannot drift', yet adds a second, dead export site kept alive by a claim a grep disproves — so either the dead export survives unexamined or its removal triggers a hunt for readers that do not exist.
| // two constants this resolution does, so the two cannot drift. Re-exported | |
| // here because this module is where every earlier reader imported it from. | |
| export { FLAT_STREAK_TO_ENGAGE } from './lib/posture.js'; | |
| // two constants this resolution does, so the two cannot drift. |
(keep the true sentence, drop the false 'Re-exported here because …' claim and the export line).
中文说明
新增的 FLAT_STREAK_TO_ENGAGE 再导出在任何地方都没有导入者,其理由注释与事实不符。穷尽 grep:PR 后该名称的唯一读取者是 lib/posture.ts(定义方)、lib/posture.test.ts(从 ./posture.js 导入)与本模块自身的 import(内部使用于 :1591、:1630);从 compose-review.js 导入的模块(submit.ts、save-artifact.ts、compose-review.test.ts、submit-aone.test.ts)都不取该名称,也不存在桶式再导出。在合并基线上,git grep 在本文件之外同样找不到导入者——并不存在本模块所服务的"早先读取者"。本 PR 把常量移到 lib/posture.ts 恰恰是"为了让两者不会漂移",却又新增了一个死导出位,且靠一条被 grep 证伪的说法维持——结果要么死导出未经审视地存活,要么删除它时引发一场寻找不存在读取者的搜寻。
建议按上方 suggestion 保留真实句子、删除虚假的 "Re-exported here because …" 说法与导出行。
— qwen3.8-max via Qwen Code /review (v0.22.0)
… off enforcement (#10136)
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下: Review-feedback round — PR #10136Commit Resolved (8 inline findings)
Declined (1 review-level item)
Escalated (1 review-level item)
Deferred to the next round (15 inline findings, batch bound ~8)R1-4 (retirement one-receipt discriminating test), R1-5 (fetch-pr recorded-floor wiring tests), R1-6 (APPROVE-branch disclosure test), R1-7 + documentation twin (seam census Notes
VerificationCommands actually run, in order:
中文说明评审反馈轮 — PR #10136提交 已解决(8 条内联发现)
拒绝(1 条评审级条目)
升级(1 条评审级条目)
延后到下一轮(15 条内联发现,批次上限约 8)R1-4(retirement 单次收据区分性测试)、R1-5(fetch-pr 已记录下限接线测试)、R1-6(APPROVE 分支披露测试)、R1-7 + 文档孪生(接缝计数 备注
验证实际执行的命令,按顺序:
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.
15 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-5 retirement one-receipt discriminating test — already reported (comment 3864213983)
- R1-6 fetch-pr recorded-floor wiring tests — already reported (comment 3864213990)
- R1-7 APPROVE-branch disclosure test — already reported (comment 3864213996)
- R1-8 seam-census clause in the interaction brief — already reported (comment 3864214000)
- R1-9 SKILL.md documentation twin of the seam-census clause — already reported (comment 3864214010)
- R1-10 floorEnforcedReroute doc block not updated for the plan arm — already reported (comment 3864214018)
- R1-11 ledgerMarkerFor marker-floor doc block — already reported (comment 3864214025)
- R1-13 narrowed list discarded on the convergence round — already reported (comment 3864214047)
- R1-14 SKILL.md plan-arm sentence vs the context-unavailable sentence — already reported (comment 3864214055)
- R1-15 capture-time recorded-floor identity axes — already reported (comment 3864214058)
- R1-16 posture-narrowing note exclusivity claim — already reported (comment 3864214070)
- R1-17 RoundSchedule.converged contract — already reported (comment 3864214075)
- R1-18 DESIGN.md two-consecutive-dry enumeration twin — already reported (comment 3864214087)
- R1-19 SKILL.md fix-audit tier parenthetical — already reported (comment 3864214093)
- R1-21 launch preamble tail grammar — already reported (comment 3864214106)
Not explored to full depth (tool budget reached): chunk 4: executing import-graph.test.ts and budget.test.ts to confirm green — the review worktree has no node_modules and installing into the shared tree was not appropr…; chunk 2: executing the new #10104 describe block ( cd packages/cli && npx vitest run src/commands/review/compose-review.test.ts ) — the review worktree has no node_mo….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/compose-review.ts:2604 — [probe] fixAuditShapeFacts counts seam censuses without the entry-level admissionpackages/cli/src/commands/review/compose-review.ts:2613 — [review] The compose-side seam-census guard has no testpackages/cli/src/commands/review/compose-review.ts:4810 — [review] explicit-cause branch, fallback and zh rendering of the disclosure are untestedpackages/cli/src/commands/review/agent-prompt.ts:2827 — [probe] postureNarrowing returns an empty deltaChunkIds set instead of nullpackages/cli/src/commands/review/compose-review.ts:4846 — [probe] The engaged-floor sentence posts even when nothing was deferredpackages/core/src/skills/bundled/review/SKILL.md:709 — [review] The exclusivity claim omits the unknown-receipt re-launch class (3 new sites)
中文说明
本轮确认的 15 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):chunk 4:executing import-graph.test.ts and budget.test.ts to confirm green — the review worktree has no node_modules and installing into the shared tree was not appropr…;chunk 2:executing the new #10104 describe block ( cd packages/cli && npx vitest run src/commands/review/compose-review.test.ts ) — the review worktree has no node_mo…。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 6 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| // disclosure describing the posture it did not run. Gated on `auto` | ||
| // exactly like the other arms: an explicit `suggestion` is the operator | ||
| // turning the posture off, and it wins over a stale plan record. | ||
| if (floor === 'auto' && fixAuditPlan === true) return 'auto-resolved'; |
There was a problem hiding this comment.
[Critical] R2-1: The new fix-audit plan arm resolves the auto floor to critical without a contextUnavailable gate, and floorEnforcedReroute then moves drafted Suggestions into the deferral list — but the deferral-licence block in composeReviewBody (~3371-3381, untouched by this PR) still treats ANY deferral under auto + contextUnavailable as unlicensed. One posted body therefore pairs "Findings below Critical were recorded and deferred, never posted." with the unlicensed-deferral cap is stamped onto the ledger marker and the run report — falsifying this file's own documented invariant "Enforcement fires only under conditions where the deferral licence below already holds".
Concretely: a fix-audit round whose pr-context fetch failed (contextUnavailable: true, floor auto or absent-folded, plan carrying the posture record — the flagship scenario of this PR's own new test "the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)") posts a body that simultaneously asserts the posture IS known (licensed deferral, round-shape disclosure) and is NOT knowable (prevRound === 0 — exactly the "side file rewritten between capture and compose" case the arm's rationale names) the false cap is the ONLY cap: it flips the composed event and withholds the incremental anchor.
Witness (probe through the real composeReview, scratch tree):
flagship: floorEnforced: [0]
flagship: cappedBy: ["context-unavailable","unlicensed-deferral"]
flagship body: "...Findings below Critical were recorded and deferred, never posted."
flagship body: "⚠️ 1 finding(s) were deferred without a posture licence — the round is
unknowable in the context-unavailable state ... findings may be under-posted this round."
sibling (prevRound 0): cappedBy: ["unlicensed-deferral"] alone
The PR's own 8-test #10104 describe block runs green — it asserts only floorEnforced and the licensed sentence, never the warning or cappedBy, so the contradiction ships green.
Suggested fix: teach the licence block about the plan record the floor resolution already trusts — hoist the fixAuditShapeFacts(input.planPath) read (already performed later in the same function for the disclosure) or pass the fixAuditPlan flag composeReview computes, and let severityFloor === 'auto' && contextUnavailable (and the prevRound === 0 arm) resolve licensed when the plan's fix-audit record is present.
Fix witness: extend compose-review.test.ts "the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)" with expect(r.cappedBy).not.toContain('unlicensed-deferral') and expect(r.body).not.toContain('without a posture licence') — both are red today (probe-confirmed); please remove the licence exception after the fix and confirm both tests go red again.
中文说明
新的 fix-audit plan 臂在 floorResolvesCritical 中不带 contextUnavailable 门槛地把 auto 下限解析为 critical,floorEnforcedReroute 随即将起草的 Suggestion 移入延后列表——但 composeReviewBody(~3371-3381,本 PR 未触及)中的延后许可块仍把 auto + contextUnavailable 下的任何延后判为"无许可"。于是同一篇发布正文会同时出现"Findings below Critical were recorded and deferred, never posted."与 unlicensed-deferral cap——违反了本文件自己写明的不变量"Enforcement fires only under conditions where the deferral licence below already holds"。
具体触发:一个 pr-context 拉取失败的 fix-audit 轮(contextUnavailable: true、floor 为 auto 或缺省折叠为 auto、plan 带姿态记录——正是本 PR 新测试 "the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)" 的旗舰场景)会发布一篇既断言姿态已知(许可延后 + 轮次形态披露)又断言姿态不可知(prevRound === 0——即该臂理由中点名的"side file 在 capture 与 compose 之间被改写")下,这个虚假 cap 是唯一的 cap:它会翻转合成事件并扣下增量锚点。
证据(对真实 composeReview 的 probe):旗舰状态 floorEnforced: [0]、cappedBy: ["context-unavailable","unlicensed-deferral"],正文同时含许可句与 cappedBy: ["unlicensed-deferral"] 单独成立。PR 自己的 8 个 #10104 测试全绿——它们只断言 floorEnforced 与许可句,从不断言警告或 cappedBy,因此该矛盾可以全绿通过。
建议:让许可块读取下限决议已经信任的 plan 记录——把 fixAuditShapeFacts(input.planPath) 的读取上提(同一函数后面已为披露读过),或把 composeReview 算出的 fixAuditPlan 传进来,使 auto + contextUnavailable(以及 prevRound === 0 臂)在 plan 带 fix-audit 记录时判为有许可。
修复验收:给上述测试补两条断言(cappedBy 不含 unlicensed-deferral、正文不含 'without a posture licence')——当前均为红;修复后请移除许可例外并确认两条测试再次变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| convergence?.criticalFloorKind === undefined | ||
| ? '(the operator turned the posture off)' |
There was a problem hiding this comment.
[Suggestion] R2-2: The open-floor cause parenthetical added by the R1-2 repair keys on a two-way split (criticalFloorKind === undefined or not), but criticalFloorKind deliberately distinguishes genuine absence (folded to auto) from a present-but-unrecognisable floor value (left undefined) — the compose state is model-written, and normalizeSeverityFloor's own doc names "a model-transcribed spelling drift". A drifted floor ('critcal', 'blocker', '') beside a fix-audit plan therefore posts "(the operator turned the posture off)" — asserting an operator intent that never happened; the zh fold carries the same mislabel. A fix-audit round reaches this state whenever the submit-boundary recordedSeverityFloor recovery yields nothing (no record / unreadable / another PR's record — all documented failure modes that leave the state value standing), and the next round's reader then takes the false claim as an explicit posture-off decision.
Witness (probe on the unmodified PR): severityFloor: 'critcal' + POSTURE plan → floorEnforced=[], operator-off sentence present=true, absent-record sentence present=false; controls (explicit suggestion → operator-off; absent floor → absent-record) behaved as designed; keying the ternary on normalizeSeverityFloor(input.severityFloor) === 'suggestion' flipped the garbled arm to false with both controls intact.
| convergence?.criticalFloorKind === undefined | |
| ? '(the operator turned the posture off)' | |
| normalizeSeverityFloor(input.severityFloor) === 'suggestion' | |
| ? '(the operator turned the posture off)' |
with a third branch for the present-but-unreadable state, e.g. '(the state carried a floor value this module cannot read, and the strict reading cannot act on it)' — same for the zh pair.
Fix witness: add a compose case with fix-audit POSTURE + input.severityFloor = 'blocker' asserting the body contains 'resolved OPEN at compose time' and does NOT contain 'the operator turned the posture off'; removing the new branch must turn it red.
中文说明
R1-2 修复新增的开放下限原因括注按两分支(criticalFloorKind === undefined 与否)取值,但 criticalFloorKind 刻意区分"真缺失"(折叠为 auto)与"存在但无法识别的下限值"(保持 undefined)——compose 状态由模型书写,normalizeSeverityFloor 的注释明确点名"模型转写的拼写漂移"。于是 fix-audit plan 旁若带着漂移的 severityFloor('critcal'、'blocker'、''),正文会发布"(the operator turned the posture off)"——断言了一个从未发生的操作者意图;中文折叠块同样误标。只要 submit 边界的 recordedSeverityFloor 恢复不出任何值(无记录/不可读/属于另一个 PR——均为文档列明的失败模式,状态值原样保留),fix-audit 轮就会落入该状态,下一轮的读者会把这条错误断言当作明确的"姿态已关闭"决定。
证据(未改动 PR 上的 probe):severityFloor: 'critcal' + POSTURE plan → floorEnforced=[]、operator-off 句出现、absent-record 句不出现;两个对照臂行为符合预期;把三元条件改为按 normalizeSeverityFloor(input.severityFloor) === 'suggestion' 取键后,乱码臂翻转为 false 且对照不变。
建议按 suggestion 改为三分支:显式 suggestion → 操作者关闭;记录缺失 → 现有缺省句;其余(存在但不可读)→ 新增第三种措辞。中文对同步修改。
修复验收:新增 POSTURE + severityFloor = 'blocker' 用例,断言正文含 'resolved OPEN at compose time' 且不含 'the operator turned the posture off';移除新分支应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| scope.anchor !== '' && | ||
| Array.isArray(scope.deltaFiles) && | ||
| scope.deltaFiles.length > 0 && | ||
| scope.deltaFiles.every((p) => typeof p === 'string' && p !== '') |
There was a problem hiding this comment.
[Suggestion] R2-3: The strengthened delta-list bar is all-or-nothing (.every(p => typeof p === 'string' && p !== '')), but incrementalScopeOf — the paired reader this bar's comment claims parity with — rejects only NON-STRING elements and filters '' via strings() AFTER admission. A delta list mixing a valid path with an empty string (['src/a.ts', '']) is therefore accepted by the brief builder (the incremental frame renders, and the interaction briefs still carry SEAM-BOUNDED clauses) while every isFixAuditRound reader goes full: fixAuditShapeFacts returns null, fixAuditPlan is false, and the floor's plan arm disengages. On a rounds-2-5 auto floor without the flat-trend signal — or a context-unavailable compose — no other arm engages, so drafted Suggestions post inline in a round that ran the narrowed critical-posture shape, and the shape disclosure is silent — the exact two-reader disagreement the R1-1 repair was built to eliminate. The other readers degrade toward more auditing (Agent 0 returns, full waves, small-tier cap), so coverage is not the loss — the floor/disclosure alignment is. The trigger is a corrupt/hand-edited plan (capture never writes empty-string paths) — this module's stated threat model.
Witness (probe on the unmodified PR): mixed list plan → isFixAuditRound: false while briefIncrementalFrame: true; aligning the bar (filter '' then require a non-empty remainder) flips to isFixAuditRound: true / briefFixAuditFrame: true with controls (clean list, non-string element, both-empty scope) unchanged.
| scope.deltaFiles.every((p) => typeof p === 'string' && p !== '') | |
| scope.deltaFiles.filter((p): p is string => typeof p === 'string' && p !== '').length > 0 |
(filter first, then require a non-empty remainder — matching strings() in incrementalScopeOf; aligning the builder the other way would change a pre-existing reader's degrade behaviour, so the new reader should meet it).
Fix witness: inside budget.test.ts 'refuses the scopes the brief builder refuses — one bar across readers', add an accept case — isFixAuditRound with deltaFiles: ['x.ts', ''] must be true; it is red while the strict .every() stands.
中文说明
收紧后的 delta 列表校验是全有或全无(.every(p => typeof p === 'string' && p !== '')),但其注释声称对齐的配对读取器 incrementalScopeOf 只拒绝非字符串元素,并在准入之后才经 strings() 过滤 ''。于是混有空字符串的列表(['src/a.ts', ''])会被 brief 构建器接受(增量框架照常渲染,interaction brief 仍带 SEAM-BOUNDED 子句),而所有 isFixAuditRound 读取端退回全量:fixAuditShapeFacts 返回 null、fixAuditPlan 为 false、下限的 plan 臂不生效。在第 2-5 轮的 auto 下限(无 flat 信号)或 context-unavailable compose 下,没有其他臂生效,起草的 Suggestion 会在一个实际跑了收窄 critical 形态的轮次里原样发布,且形态披露沉默——正是 R1-1 修复要消除的两读取器分歧。其余读取端都朝更多审计退化(Agent 0 回归、全宽波次、小档上限),所以损失不是覆盖面,而是形态与发布口径的一致性。触发条件是损坏/手工编辑的 plan(capture 从不写空字符串路径)——即本模块声明的威胁模型。
证据(未改动 PR 上的 probe):混合列表 → isFixAuditRound: false 而 briefIncrementalFrame: true;把校验改为先过滤 '' 再要求非空后翻转为 true/true,对照臂不变。
修复验收:在 budget.test.ts 的 'one bar across readers' 块中补一个接受用例——deltaFiles: ['x.ts', ''] 必须为 true;保留现有 .every() 时该用例为红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| ? '(操作者关闭了该姿态)' | ||
| : '(下限记录缺失,强制读取按开放放行)'; | ||
| const fixAuditFloorEn = fixAuditFloorEngaged | ||
| ? 'Findings below Critical were recorded and deferred, never posted.' |
There was a problem hiding this comment.
[Suggestion] R2-4 (1 of 4 sites): The claim "everything below Critical is recorded and deferred, never posted" is false at every site where this round states it: floorEnforcedReroute deliberately leaves deterministic [build]/[test]/[probe] Suggestions inline at ANY floor (the DETERMINISTIC_TAG_RE carve-out at ~640-654), and SKILL.md's floor paragraph states the floor excludes deterministic findings "by its source field". This site is the posted engaged-floor sentence itself. The same claim also stands in the fix-audit brief banner (agent-prompt.ts:782 — see the sibling comment), SKILL.md:709, and SKILL.md:299.
On a critical-posture fix-audit round a [test]-tagged Suggestion drafted inline stays posted beside this sentence — a universal the same body falsifies. Probe witness at an engaged floor (POSTURE plan, severityFloor: 'auto') with a drafted **[Suggestion]** [test] mutation survivor on the retry guard: floorEnforced: [] — the [test] Suggestion stays inline, engaged sentence present, nothing deferred; the control arm with a non-deterministic Suggestion: floorEnforced: [0], deferredCount 1.
Beyond the posted record, the recall the narrowing prices as "already paid" genuinely includes postable findings: a cold check that never runs on a narrowed-out chunk could have surfaced a deterministic Suggestion the floor keeps inline.
Suggested fix: carve the deterministic class out of the claim — "everything below Critical is recorded and deferred, never posted — except pre-confirmed [build]/[test]/[probe] findings, which stay inline at any floor" — at all four sites (en + zh).
Fix witness: compose-review.test.ts — POSTURE + one drafted [test]-tagged Suggestion: assert it stays inline AND the body does not carry the unqualified universal; removing the carve-out wording turns it red.
中文说明
R2-4(4 处之 1):"低于 Critical 的一切都被记录延后、从不发布"这一断言在本轮写下它的所有位置都不成立:floorEnforcedReroute 在任何下限下都会刻意让确定性 [build]/[test]/[probe] Suggestion 留在行内(~640-654 的 DETERMINISTIC_TAG_RE 豁免),SKILL.md 的下限段落也写明下限按 source 字段排除确定性发现。本处是发布正文中的 engaged 句;同样的断言还在 fix-audit brief 横幅(agent-prompt.ts:782,见姊妹评论)、SKILL.md:709、SKILL.md:299。
critical 姿态的 fix-audit 轮中,一个行内起草的 [test] 标签 Suggestion 会与这句话同篇发布——正文自己证伪了这句全称断言。证据:在生效下限下(POSTURE plan、severityFloor: 'auto')起草一条 [test] Suggestion,probe 显示 floorEnforced: []——该 Suggestion 留在行内、engaged 句出现、延后数为 0;非确定性对照臂 floorEnforced: [0]、延后 1 条。
除发布记录外,收窄定价为"已支付"的召回确实包含可发布发现:被收窄掉的 chunk 不再冷检,而冷检本可能产出下限会保留行内的确定性 Suggestion。
建议:在四处(中英)把确定性类别从断言中挖出——"…从不发布——除了预确认的 [build]/[test]/[probe] 发现,它们在任何下限下都留在行内"。
修复验收:POSTURE + 一条 [test] Suggestion 的用例断言其留在行内且正文不含未加限定的全称句;移除豁免措辞应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| 0, | ||
| `**Fix-audit round (critical posting posture).** The commits since the anchor ` + | ||
| `answer earlier rounds' findings, and this round's posting floor is Critical — ` + | ||
| `everything below it is recorded and deferred, never posted. Spend your walk ` + |
There was a problem hiding this comment.
[Suggestion] R2-4 (2 of 4 sites): The fix-audit brief banner's "everything below it is recorded and deferred, never posted" is false in the same way as the posted-body sentence (compose-review.ts:4846 — see the sibling comment): floorEnforcedReroute leaves deterministic [build]/[test]/[probe] Suggestions inline at any floor (DETERMINISTIC_TAG_RE carve-out). The audience here makes the cost distinct: every territory auditor reads this banner, and one trusting "never posted" may drop a deterministic finding it just proved — a never-drafted finding is lost from the round entirely, since only drafted comments are rerouted to the deferral channel — or inflate it to Critical against the banner's own "never inflate one to clear the floor" sentence. Probe witness (sibling comment): a [test]-tagged Suggestion stays inline at an engaged floor. Sibling sites: SKILL.md:709 and SKILL.md:299.
Suggested fix: carve the deterministic class out of the banner, e.g. "everything below it is recorded and deferred, never posted — except pre-confirmed [build]/[test]/[probe] findings, which stay inline at any floor".
Fix witness: extend agent-prompt.test.ts:6941 ('a fix-audit round frames the brief and discloses the seam bound (#10104)') to assert the carve-out sentence — it goes red if the carve-out is removed from the banner.
中文说明
R2-4(4 处之 2):fix-audit brief 横幅中的"everything below it is recorded and deferred, never posted"与发布正文那句(compose-review.ts:4846,见姊妹评论)以同样方式失真:floorEnforcedReroute 在任何下限下都让确定性 [build]/[test]/[probe] Suggestion 留在行内(DETERMINISTIC_TAG_RE 豁免)。此处的受众使代价更具体:每个领地审计 agent 都会读到横幅,若其相信"从不发布",可能丢掉自己刚证明的确定性发现——从未起草的发现会彻底从本轮丢失(只有起草的评论才会被改道进延后渠道)——或者违反横幅自己"不要为清下限而拔高严重度"的指示把它拔成 Critical。证据见姊妹评论:生效下限下 [test] Suggestion 留在行内。姊妹位置:SKILL.md:709、SKILL.md:299。
建议:把确定性类别从横幅中挖出(措辞示例见英文部分)。
修复验收:扩展 agent-prompt.test.ts:6941 断言豁免句;移除豁免措辞应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| - **Small diffs (Step 3A path):** one reverse audit agent per round, reading the whole diff — except rounds 1 and 2, which are **the convergence pair** and launch together (below). | ||
| - **Large diffs (Step 3B path):** one reverse audit agent **per chunk** per round, launched together in a single response — and rounds 1 and 2 are **the convergence pair** here too, their per-chunk auditors launched together (below). A single agent asked to re-read a 5 800-line diff with a growing finding list appended is the most context-starved agent in the pipeline — precisely on the PRs where the reverse audit matters most. Each per-chunk auditor gets the same territory as its Step 3B counterpart, plus the cumulative finding list for the **whole** diff (so it knows what is already covered elsewhere). | ||
| - **The builder schedules the 3B fan-out; you do not.** Rounds 1 and 2 audit every chunk — they are what establishes each territory's record. From round 3 on, `--all-chunks` reads the harness transcripts and **retires** any chunk whose own last two audits were substantively dry (the receipt named what it examined AND the transcript shows the diff was opened): a retired chunk is cold-checked on alternating rounds instead of every round, and a cold check that yields anything returns it to every-round auditing. The savings land on the odd rounds — every retired chunk cold-checks together on the even ones, so an even round's fan-out is unchanged; expect the odd rounds to shrink, not the even ones (under the 3-round huge-diff cap — the reduction a run earns only when it has a deadline — only round 3 can shrink, because the cap ends the loop before round 5). The blocks it prints are the round; the `retirement:` note after the `end of round` line names each skipped chunk and its certificate — relay that note in your narration, and do not hand-build an auditor for a chunk the builder skipped. Why, measured: on a real 6-chunk run, two chunks were dry in **all five rounds** — a third of the loop's auditors re-certifying territories that had already converged, while the three hot chunks were where every finding came from. Attention follows evidence; the certificate a retired chunk holds (two consecutive substantive dry audits) is exactly the one the whole loop used to end on. | ||
| - **The builder schedules the 3B fan-out; you do not.** Rounds 1 and 2 audit every chunk — they are what establishes each territory's record. From round 3 on, `--all-chunks` reads the harness transcripts and **retires** any chunk whose own last two audits were substantively dry (the receipt named what it examined AND the transcript shows the diff was opened): a retired chunk is cold-checked on alternating rounds instead of every round, and a cold check that yields anything returns it to every-round auditing. The savings land on the odd rounds — every retired chunk cold-checks together on the even ones, so an even round's fan-out is unchanged; expect the odd rounds to shrink, not the even ones (under the 3-round huge-diff cap — the reduction a run earns only when it has a deadline — only round 3 can shrink, because the cap ends the loop before round 5). The blocks it prints are the round; the `retirement:` note after the `end of round` line names each skipped chunk and its certificate — relay that note in your narration, and do not hand-build an auditor for a chunk the builder skipped. On a **fix-audit round** the schedule additionally narrows the wave (#10104): from round 3, a chunk holding no delta file leaves the schedule after **one** substantive dry audit and takes no cold checks — the wave re-launches only the delta territories and whatever the previous wave surfaced findings in, which trades the cold-check recall the posture has already priced (everything below Critical defers) for waves that keep running to the same cap over a shrinking front. The `posture narrowing:` note after the end-of-round line names each narrowed chunk; relay it exactly as you relay the retirement note, and hand-build nothing it skipped. Why, measured: on a real 6-chunk run, two chunks were dry in **all five rounds** — a third of the loop's auditors re-certifying territories that had already converged, while the three hot chunks were where every finding came from. Attention follows evidence; the certificate a retired chunk holds (two consecutive substantive dry audits) is exactly the one the whole loop used to end on. |
There was a problem hiding this comment.
[Suggestion] R2-4 (3 of 4 sites): The narrowing bullet's justification parenthetical "(everything below Critical defers)" repeats the universal claim already shown false at compose-review.ts:4846 and agent-prompt.ts:782 (see the sibling comments): deterministic [build]/[test]/[probe] findings are excluded from the critical floor by their source field and stay posted — the same file states this a few paragraphs down ("the floor excludes it — by its source field"). The recall this bullet prices as already paid genuinely includes such postable findings: a cold check that never runs on a narrowed-out chunk could have surfaced a deterministic Suggestion the floor keeps inline. (The sentence's exclusivity clause — "re-launches only the delta territories and whatever the previous wave surfaced findings in" — is the separate, still-standing R1-16 class.)
Suggested fix: "(everything below Critical defers, except the pre-confirmed deterministic findings the floor excludes by their source field)".
Fix witness: N/A — prose in the bundled skill doc; the carve-out behaviour is already pinned by the compose suite's deterministic-tag tests.
中文说明
R2-4(4 处之 3):收窄要点的理由括注"(everything below Critical defers)"重复了已在 compose-review.ts:4846 与 agent-prompt.ts:782 证明为假的断言(见姊妹评论):确定性 [build]/[test]/[probe] 发现按下限按 source 字段排除、仍会发布——同一文件下方几段就写着"the floor excludes it — by its source field"。该要点定价为"已支付"的召回确实包含这类可发布发现:被收窄掉的 chunk 不再冷检,而冷检本可能产出下限保留行内的确定性 Suggestion。(句中的排他性子句"re-launches only..."是另一问题,属仍有效的 R1-16 类别。)
建议:把括注改为"(everything below Critical defers, except the pre-confirmed deterministic findings the floor excludes by their source field)"。
修复验收:N/A——技能文档措辞;豁免行为已由 compose 测试套件的确定性标签测试钉住。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| **Choose the topology from `srcDiffLines`, not from `diffLines`.** | ||
|
|
||
| - **the plan carries `incremental.posture: "critical"`** — a **fix-audit round** (#10104): use Step 3B whatever the sizes say. The narrowed delta is usually 3A-sized, but the posture defers everything below Critical, so the round owes one accountable reader per territory of the fix commits — not fourteen dimension lenses re-walking a delta whose sub-Critical yield is deferred wholesale. The CLI's own gate reads the same plan field, so the roster, the round-cap tier (the 3B tier of 5) and the #9242 stderr note all agree with this routing; the roster the plan builds already reflects the shape (no Agent 0 — issue fidelity was ruled by the full rounds before the posture engaged, and a fix commit that removes required behaviour is the removed-behavior audit's territory, which the round keeps). Tell the user: "Critical posture (<postureCause>): fix-audit round over the commits since the last round." |
There was a problem hiding this comment.
[Suggestion] R2-4 (4 of 4 sites): The topology bullet rewritten by the current round states "the posture defers everything below Critical" and "a delta whose sub-Critical yield is deferred wholesale" — the universal claim shown false at the three sibling sites (compose-review.ts:4846, agent-prompt.ts:782, SKILL.md:709; see the sibling comments): floorEnforcedReroute's DETERMINISTIC_TAG_RE carve-out keeps [build]/[test]/[probe] Suggestions inline at any floor, and the same file's floor paragraph says the floor excludes deterministic findings "by its source field". The bullet prices the dropped dimension fan-out's entire sub-Critical yield as deferred to justify the territory shape — but a dropped lens could have surfaced a deterministic Suggestion that would have posted, so the yield is not deferred wholesale. When the three known sites get repaired, this newly added bullet would still assert the false universal.
Suggested fix: "the posture defers everything below Critical that the floor takes — deterministic [build]/[test]/[probe] findings are excluded from the floor by their source field and post as usual", and change "deferred wholesale" to match.
Fix witness: N/A — prose in the bundled skill doc.
中文说明
R2-4(4 处之 4):本轮改写的拓扑要点写有"the posture defers everything below Critical"与"a delta whose sub-Critical yield is deferred wholesale"——即在三个姊妹位置(compose-review.ts:4846、agent-prompt.ts:782、SKILL.md:709,见姊妹评论)已证伪的全称断言:floorEnforcedReroute 的 DETERMINISTIC_TAG_RE 豁免让 [build]/[test]/[probe] Suggestion 在任何下限下留在行内,同一文件的下限段落也写明按 source 字段排除。该要点把被砍维度扇出的全部 sub-Critical 产出定价为"已延后"以论证领地形态——但被砍的视角本可能产出会被发布的确定性 Suggestion,产出并非整体延后。若只修已知三处,这条新增要点仍会断言该假全称。
建议:改为"the posture defers everything below Critical that the floor takes — deterministic [build]/[test]/[probe] findings are excluded from the floor by their source field and post as usual",并把"deferred wholesale"改为一致措辞。
修复验收:N/A——技能文档措辞。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| **Choose the topology from `srcDiffLines`, not from `diffLines`.** | ||
|
|
||
| - **the plan carries `incremental.posture: "critical"`** — a **fix-audit round** (#10104): use Step 3B whatever the sizes say. The narrowed delta is usually 3A-sized, but the posture defers everything below Critical, so the round owes one accountable reader per territory of the fix commits — not fourteen dimension lenses re-walking a delta whose sub-Critical yield is deferred wholesale. The CLI's own gate reads the same plan field, so the roster, the round-cap tier (the 3B tier of 5) and the #9242 stderr note all agree with this routing; the roster the plan builds already reflects the shape (no Agent 0 — issue fidelity was ruled by the full rounds before the posture engaged, and a fix commit that removes required behaviour is the removed-behavior audit's territory, which the round keeps). Tell the user: "Critical posture (<postureCause>): fix-audit round over the commits since the last round." |
There was a problem hiding this comment.
[Suggestion] R2-5: The bullet's tier clause — "the round-cap tier (the 3B tier of 5) ... all agree with this routing" — is false for a fix-audit round whose narrowed delta is itself huge: reverseAuditRoundTier checks the huge gate (effective ≥ 3000) BEFORE the posture-aware topology gate, so such a round under QWEN_REVIEW_DEADLINE_EPOCH records budget.reverseAuditRounds: 3, not 5. Reachable on any posture arm (round ≥ 6, latched flatRounds, or explicit critical on a later incremental round — none carries a delta-size clamp). This is a second instance of the still-standing R1-19's root cause at a sentence R1-19's anchor (SKILL.md:242) does not cover; the roster and #9242 halves of the same "all agree" sentence hold — only the tier clause is false.
Witness: gate order at HEAD — if (effective >= HUGE_DIFF_FLOOR) { return hasDeadline ? HUGE_REVERSE_AUDIT_ROUNDS : LARGE_REVERSE_AUDIT_ROUNDS; } executes before the posture gate; budget.test.ts pins the corner (reverseAuditRoundTier({srcDiffLines: 4000, diffLines: 5000, ...POSTURE}, true)).toBe(3), "The huge finishability ruling still wins where there is a wall") — ran green in this review's budget.test.ts execution (81/81). The behaviour is deliberate and test-pinned; only the prose is wrong.
Suggested fix: "the round-cap tier (the 3B tier of 5, or the huge tier's 3 where a deadline-bound run's delta is itself huge — the huge gate is checked first)" — or fix both sites together with R1-19.
Fix witness: N/A — prose correction; the behaviour is already pinned by the budget.test.ts huge-tier case.
中文说明
R2-5:该要点的档位子句——"the round-cap tier (the 3B tier of 5) ... all agree with this routing"——对收窄后增量本身为 huge 的 fix-audit 轮不成立:reverseAuditRoundTier 先检查 huge 门(effective ≥ 3000),再检查姿态感知的拓扑门,因此在带 QWEN_REVIEW_DEADLINE_EPOCH 的该轮会记录 budget.reverseAuditRounds: 3 而非 5。三个姿态臂均可达(round ≥ 6、锁存的 flatRounds、后续增量轮的显式 critical——均无增量尺寸钳制)。这是仍有效的 R1-19 根因的第二处实例,位于 R1-19 锚点(SKILL.md:242)未覆盖的句子;同一"all agree"句的 roster 与 #9242 部分成立——只有档位子句为假。
证据:HEAD 的门序——huge 门在姿态门之前执行;budget.test.ts 已钉住该角(...toBe(3),"The huge finishability ruling still wins where there is a wall"),本轮 budget.test.ts 运行 81/81 全绿。行为是刻意且已被测试钉住的;错的只是措辞。
建议:把括注改为"(the 3B tier of 5, or the huge tier's 3 where a deadline-bound run's delta is itself huge — the huge gate is checked first)",或与 R1-19 一并修复两处。
修复验收:N/A——措辞修正;行为已由 budget.test.ts 的 huge 档用例钉住。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| - **Incremental review check** (high effort only — neither low nor medium consults or updates the cache): read `.qwen/review-cache/pr-<n>.json` **before** `fetch-pr` (it is a local file; nothing about it needs the fetch) and, when it holds a `lastCommitSha`, pass BOTH fields to the fetch verbatim: `--since <lastCommitSha> --since-model <lastModelId>` (omit `--since-model` when the cache has no `lastModelId`; do not substitute anything for it). **Copy them; do not compare them to anything.** The same-model gate is ruled inside `fetch-pr`, over the identity the runtime published — "clean up to `lastCommitSha`" is the recorded identity's verdict, and the command validates an anchor against the HISTORY, never against who certified it, so an anchor from another identity is ancestrally perfect and would scope this round past code it never reviewed. A hand-applied version of that gate was wrong every time it was written, because `{{model}}` interpolates the BARE model id while every identity the CLI records is provider-qualified: two provider configurations exposing one model name compared equal and passed each other's gate. When the gate refuses, the report says `cross-model-anchor` and the round reviews the full diff. Read the cache's `findings` ledger either way (Step 6 owes each entry a ruling; the work list carries across models, only the anchor does not). **You never run `git` against an anchor yourself** — no `git diff <sha>..HEAD`, no `cat-file`, no `merge-base --is-ancestor`: the command validates the anchor against the fetched history and computes the scoped diff and chunk plan in one pass, because a hand-run check is one a run can skip, and the hand-computed delta was exactly the shape this skill forbids everywhere else (the diff is a file the CLI writes, never a command you run). The report's `incremental` field is the decision; act on it with `lastModelId` from the cache and the current model ID (`{{model}}`): | ||
| - `effective: true` (no `upToDate`) → the report's diff and plan ARE the incremental scope (`since..head`); continue with them exactly as with a full plan. The file set is **widened by one import hop**: a still-clean source file that imports a changed one re-enters the scope with its own full-range hunks, because the round before cleared it against the callee's OLD shape. `incremental.scope` names each file's class — `deltaFiles` (touched since the anchor), `interaction[]` (widened back in, each with the edges that did it), `contextFileCount` (weighed and passed over) — and a chunk brief built for an interaction file points its agent at that seam instead of a from-scratch re-review. **Also read the cache's `findings` ledger** (older caches have none — then there is nothing to track): these are the previous round's findings with their ids, and Step 6 owes each of them a ruling this round. (Reachable only under a matching identity: the gate inside the command is what keeps a cross-model anchor from scoping anything.) | ||
| - `effective: true` (no `upToDate`) → the report's diff and plan ARE the incremental scope (`since..head`); continue with them exactly as with a full plan. The file set is **widened by one import hop**: a still-clean source file that imports a changed one re-enters the scope with its own full-range hunks, because the round before cleared it against the callee's OLD shape. `incremental.scope` names each file's class — `deltaFiles` (touched since the anchor), `interaction[]` (widened back in, each with the edges that did it), `contextFileCount` (weighed and passed over) — and a chunk brief built for an interaction file points its agent at that seam instead of a from-scratch re-review. On a round the capture resolved to the **critical posting posture** the report also carries `incremental.posture: "critical"` with its `postureCause` (`round`, `flat-trend`, or `explicit` — the same facts Step 6's floor resolution reads, predicted from the side file and the CLI-recorded invocation), and the round runs the **fix-audit shape**: see Step 1's topology note and Step 5's posture narrowing. On such a round the interaction files re-enter **seam-bounded** — each `interaction[]` entry then carries a `seam: {kept, total}` census of the hunks republished (the ones displaying a line that imports or uses what changed; the rest were cleared by an earlier round and are not re-shown), and a file whose census is `kept: 0` arrives as a header-only section that still lands in a chunk, so its agent is still briefed to answer the seam question from the worktree. **Also read the cache's `findings` ledger** (older caches have none — then there is nothing to track): these are the previous round's findings with their ids, and Step 6 owes each of them a ruling this round. (Reachable only under a matching identity: the gate inside the command is what keeps a cross-model anchor from scoping anything.) |
There was a problem hiding this comment.
[Suggestion] R2-6: The seam-bounded sentence's universal claim — "each interaction[] entry then carries a seam: {kept, total} census of the hunks republished" — is falsified by widenScope's own doubt states, which leave the entry with NO seam field and republish the file in full: an unreadable worktree source (readWorktree null → continue, no seams.set) and a zero-hunk section (section.hunks.length === 0 guard) — exactly the states its comment documents ("Every doubt state republishes in full"). All five consumers treat an absent seam as benign silence (the brief builder and chunkScopeBullets render (e.seam ? … : ''), incrementalScopeOf validates and omits, fixAuditShapeFacts skips non-object seams, fetch-pr's stderr census filters to entries with a seam), so only this doc overstates: a critical-posture round hitting either doubt state produces an entry with no census whose hunks republish whole, beside a skill text asserting every entry carries one. The code direction is safe (doubt republishes in full); the doc is what is wrong. Distinct from the carried R1-9, which anchors this same sentence's "rest were cleared" clause.
Witness: incremental-scope.ts doubt paths quoted at HEAD (if (!section || section.hunks.length === 0) continue; and if (source === null) continue; before any seams.set); incremental-scope.test.ts pins the no-census outcome — expect(widened.scope.interaction[0].seam).toBeUndefined() (line 255) and expect(widened.hunkKeep).toBeUndefined() (256, 275).
Suggested fix: "each interaction[] entry that the seam scan could run carries a seam: {kept, total} census …; a file whose worktree source could not be read (or whose section holds no hunks) re-enters with its full-range hunks and no census — every doubt state fails toward full republication."
Fix witness: N/A — prose-only fix; the behaviour is already pinned by incremental-scope.test.ts's doubt-state cases.
中文说明
R2-6:接缝限宽句的全称断言——"each interaction[] entry then carries a seam: {kept, total} census of the hunks republished"——被 widenScope 自身的疑态证伪:这两种疑态会让条目不带任何 seam 字段、文件按全量重发——工作树源不可读(readWorktree 返回 null → continue,不 seams.set)与零 hunk 段(section.hunks.length === 0 守卫)——正是其注释文档化的状态("Every doubt state republishes in full")。五个消费端都把缺失的 seam 当作良性沉默(brief 构建器与 chunkScopeBullets 渲染 (e.seam ? … : '')、incrementalScopeOf 校验后省略、fixAuditShapeFacts 跳过非对象 seam、fetch-pr 的 stderr 统计只过滤带 seam 的条目),因此只有本文档过度断言:critical 姿态轮一旦命中任一疑态,就会产出一条无统计、全量重发的条目,而技能文本却断言每条都带统计。代码方向安全(疑态全量重发);错的是文档。与仍有效的 R1-9 不同——后者锚定的是同句的"rest were cleared"子句。
证据:HEAD 处的 incremental-scope.ts 疑态路径(if (!section || section.hunks.length === 0) continue; 与 if (source === null) continue;,均先于任何 seams.set);incremental-scope.test.ts 已钉住无统计结果(255 行 seam 为 undefined、256/275 行 hunkKeep 为 undefined)。
建议:把句子限定为"each interaction[] entry that the seam scan could run carries a seam: {kept, total} census …; a file whose worktree source could not be read (or whose section holds no hunks) re-enters with its full-range hunks and no census — every doubt state fails toward full republication."。
修复验收:N/A——纯措辞修正;行为已由 incremental-scope.test.ts 的疑态用例钉住。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
11 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R2-2 open-floor cause parenthetical mislabel — already reported (comment 3866310301)
- R2-3 delta-list bar all-or-nothing parity notch — already reported (comment 3866310332)
- R2-4 'everything below Critical is recorded and deferred, never posted' (4 sites) — already reported (comment 3866310340)
- R2-5 brief banner twin of the universal claim — already reported (comment 3866310349)
- R2-6 seam-census universal claim — already reported (comment 3866310356)
- R2-7 'the posture defers everything below Critical' — already reported (comment 3866310362)
- R2-8 tier clause at SKILL.md:299 — already reported (comment 3866310373)
- R2-9 seam-bounded universal claim at SKILL.md:166 — already reported (comment 3866310381)
- tier parenthetical overclaim at SKILL.md:242 — already reported as R1-15 (comment 3864214093)
- plan-arm sentence contradicts the context-unavailable sentence at SKILL.md:852 — already reported as R1-11 (comment 3864214055)
- enforcement-arm enumeration omits the plan arm at SKILL.md:852 — already reported as R1-11 (comment 3864214055)
Not reviewed: build-and-test — "Integration Tests (CLI, No Sandbox)" was skipped in CI and its suite did not run locally.
Not explored to full depth (tool budget reached): chunk 2: executing compose-review.test.ts under vitest — the worktree has no node_modules and no built workspace dist/ outputs, and a full install+build exceeded t…; "agent reverse-audit (round 2)": running packages/cli/src/commands/review/lib/incremental-scope.test.ts to confirm the suite is green — the review worktree and the parent checkout both lack nod….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 3, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/lib/roster.ts:222 — [review] Agent-0 drop rationale omits modification-shaped breakage of issue-required behaviourpackages/cli/src/commands/review/agent-prompt.ts:776 — [probe] fix-audit frame absent from reverse-audit role briefspackages/core/src/skills/bundled/review/SKILL.md:852 — [review] 'the posting bar can never disagree' falsified by two named divergencesdocs/users/features/code-review.md:370 — [review] late-waves clause falsified for a huge narrowed deltapackages/cli/src/commands/review/lib/posture.ts:44 — [review] header guarantee false for absent/unrecognised floor statespackages/cli/src/commands/review/compose-review.ts:579 — [probe] plan-arm floor engagement has no cause on the untrimmable deferral surfacespackages/cli/src/commands/review/compose-review.ts:4845 — [probe] engaged-floor sentence fabricates a deferral when nothing was deferredpackages/cli/src/commands/review/compose-review.test.ts:2180 — [probe] plan-arm engagement with context available is pinned by no test
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 11 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — "Integration Tests (CLI, No Sandbox)" was skipped in CI and its suite did not run locally。
未探索到全部深度(达到工具调用预算):chunk 2:executing compose-review.test.ts under vitest — the worktree has no node_modules and no built workspace dist/ outputs, and a full install+build exceeded t…;"agent reverse-audit (round 2)":running packages/cli/src/commands/review/lib/incremental-scope.test.ts to confirm the suite is green — the review worktree and the parent checkout both lack nod…。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 3 轮,非阻断)——已记录,本轮不要求修改:共 8 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| // disclosure describing the posture it did not run. Gated on `auto` | ||
| // exactly like the other arms: an explicit `suggestion` is the operator | ||
| // turning the posture off, and it wins over a stale plan record. | ||
| if (floor === 'auto' && fixAuditPlan === true) return 'auto-resolved'; |
There was a problem hiding this comment.
[Critical] R2-1: Still stands — no fix commit has landed since round 2 (the branch head moved only by a merge of main). The new fix-audit plan arm resolves the auto floor to critical without the contextUnavailable gate its two sibling arms carry, and floorEnforcedReroute then moves drafted Suggestions into the deferral list — but the deferral-licence block (~3371-3383, untouched by this PR) still treats ANY deferral under auto + contextUnavailable as unlicensed. One posted body therefore pairs "Findings below Critical were recorded and deferred, never posted." with the unlicensed-deferral cap is stamped onto the ledger marker and the run report — falsifying this file's own documented invariant "Enforcement fires only under conditions where the deferral licence below already holds". The sibling prevRound === 0 arm of the same licence block is the same root defect (named in this finding's round-2 body).
Witness (round-3 probe through the real composeReview at this commit): a fix-audit plan with contextUnavailable: true and one rerouted Suggestion fires the auto && contextUnavailable licence arm — the body carries BOTH the floor-enforcement note and "cappedBy gains unlicensed-deferral, beside the same body's shape block asserting the posture engaged. Concretely: a fix-audit round whose pr-context fetch failed (the flagship scenario of this PR's own test 'the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)') posts the contradiction; in the sibling state (same plan, side file lost before compose → prevRound === 0, context available) the false cap is the ONLY cap — it flips the composed event and withholds the incremental anchor.
Suggested fix: teach the licence block about the plan record the floor resolution already trusts — hoist the fixAuditShapeFacts(input.planPath) read (already performed later in the same function for the disclosure) or pass the fixAuditPlan flag composeReview computes, and let severityFloor === 'auto' && contextUnavailable (and the prevRound === 0 arm) resolve licensed when the plan's fix-audit record is present; update floorEnforcedReroute's arm enumeration to name it.
Fix witness: extend compose-review.test.ts 'the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)' with expect(r.cappedBy).not.toContain('unlicensed-deferral') and expect(r.body).not.toContain('without a posture licence') — both are red today (probe-confirmed); please remove the licence exception after the fix and confirm both tests go red again.
中文说明
仍然成立——第 2 轮之后没有任何修复 commit(分支头仅移动过一次 main 合并)。新的 fix-audit plan 臂在 floorResolvesCritical 中不带 contextUnavailable 门槛地把 auto 下限解析为 critical(它的两个兄弟臂都带此门槛),floorEnforcedReroute 随即将起草的 Suggestion 移入延后列表——但 composeReviewBody(~3371-3383,本 PR 未触及)中的延后许可块仍把 auto + contextUnavailable 下的任何延后判为"无许可"。于是同一篇发布正文会同时出现"Findings below Critical were recorded and deferred, never posted."与 unlicensed-deferral cap——违反了本文件自己写明的不变量"Enforcement fires only under conditions where the deferral licence below already holds"。同一许可块的 prevRound === 0 兄弟臂是同一根因缺陷(第 2 轮正文已点名)。
证据(第 3 轮对本 commit 真实 composeReview 的 probe):fix-audit plan + contextUnavailable: true + 一条被改道的 Suggestion 会触发 auto && contextUnavailable 许可臂——正文同时含强制 note 与 cappedBy 新增 unlicensed-deferral,而同一篇正文的形态块却断言姿态已生效。具体触发:pr-context 拉取失败的 fix-audit 轮(正是本 PR 新测试 'the plan posture is a floor-resolution arm: a context-unavailable round still defers (#10104)' 的旗舰场景)会发布该矛盾;兄弟状态(同一 plan、compose 前 side file 丢失 → prevRound === 0、context 可用)下这个虚假 cap 是唯一的 cap:翻转合成事件并扣下增量锚点。
建议:让许可块读取下限决议已经信任的 plan 记录——把 fixAuditShapeFacts(input.planPath) 的读取上提(同一函数后面已为披露读过),或把 composeReview 算出的 fixAuditPlan 传进来,使 auto + contextUnavailable(以及 prevRound === 0 臂)在 plan 带 fix-audit 记录时判为有许可;同时在 floorEnforcedReroute 的臂列举中补上它。
修复验收:给上述测试补两条断言(cappedBy 不含 unlicensed-deferral、正文不含 'without a posture licence')——当前均为红(probe 确认);修复后请移除许可例外并确认两条测试再次变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
8 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- one-dry-receipt narrowing bar isolated by no test — already reported as R1-4 (comment 3864213983)
- role-brief seam-bounded bullet asserted by no test — already recorded in the round-4 deferral list (review 5037286144)
- explicit-cause branch and null fallback of the round-shape disclosure untested — already recorded in the round-2 deferral list (review 5034611317)
- capture-time recordedFloor wiring untested in either direction — already reported as R1-5 (comment 3864213990)
- plan-arm sentence contradicts the context-unavailable sentence at SKILL.md:852 — already reported as R1-11 (comment 3864214055)
- round-shape "re-launched only" universal omits unknown-outcome chunks — already reported as R1-13 (comment 3864214070) and recorded in the round-4 deferral list (review 5037286144)
- capture-time host axis weaker than submit's four-arm chain — already reported as R1-12 (comment 3864214058)
- enforced-floor enumeration omits the plan arm — already carried under R1-11's accepted scope (comment 3864214055, reply 3864982647)
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory.
Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/compose-review.ts:602 — [review] floorEnforcedReroute docblock's fail-open enumeration contradicts the new plan armpackages/core/src/skills/bundled/review/SKILL.md:852 — [review] round-decision parenthetical "(no recovered ledger → round 1 → no posture)" contradicts the inserted plan-record arm
中文说明
本轮确认的 8 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory。
收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| **Whole-diff agents — launched alongside the chunk agents, in the same response.** | ||
|
|
||
| **Their blocks are already in the `--roster` output above — you have them.** Roles there: `0` (PR reviews), `1b` (when the diff removes anything, or a repository context requires it), `1c`, `test-matrix`, `7` (same-repo), and for a **heavy** file three more, one per checklist slice (their blocks are labelled `Invariant agent A|B|C: … — <path>`). Pass each **verbatim**. To rebuild one for a relaunch: `--role <role>` (an invariant agent adds `--file <path>`). `check-coverage` derives the same list from the plan and will name any role that did not run. | ||
| **Their blocks are already in the `--roster` output above — you have them.** Roles there: `0` (PR reviews — but not on a fix-audit round, whose roster deliberately omits it; see Step 1's topology note), `1b` (when the diff removes anything, or a repository context requires it), `1c`, `test-matrix`, `7` (same-repo), and for a **heavy** file three more, one per checklist slice (their blocks are labelled `Invariant agent A|B|C: … — <path>`). Pass each **verbatim**. To rebuild one for a relaunch: `--role <role>` (an invariant agent adds `--file <path>`). `check-coverage` derives the same list from the plan and will name any role that did not run. |
There was a problem hiding this comment.
[Critical] R6-1: This sentence says the fix-audit roster "deliberately omits" Agent 0 (Issue Fidelity), but this same PR's code, tests, and design record keep it. roster.ts's add('0') is unconditional for a PR plan — no posture gate; the comment this PR adds right above it exists to explain the probe that disproved dropping it. roster.test.ts adds "keeps Agent 0 and the territory shape on a small delta" and "keeps Agent 0 on a fix-audit round whose published scope shows no deletion", both asserting expect(keys).toContain('0') under the posture'd plan. DESIGN.md states the roster keeps every agent the full shape runs because issue fidelity is the one auditor that can still see the posture's signature Critical class. The cross-reference "see Step 1's topology note" no longer supports the claim: the HEAD commit removed the Agent-0 exclusion claim from that note, which now reads "the roster the plan builds already reflects the shape". If Agent 0's launch fails or whiffs twice on a fix-audit round, this same paragraph instructs rebuilding via --role <role> — an orchestrator told role 0 is deliberately omitted reads the surviving block as stale and skips the rebuild, and the round completes without the issue-fidelity pass. By this diff's own roster comment, the seam-bounded base..head scope makes a fix commit removing behaviour the issue required invisible to every other auditor (absent at the merge base, absent at head, removedLines stays 0, hasDeletions drops 1b, no chunk territory displays it) — so that regression ships unflagged on exactly the rounds this PR introduces. This is the still-open sibling entrance of the R4-1 family: the roster gate itself is fixed (R4-1's mechanism can no longer fire), this doc claim survived the fix commit.
Witness (probe at the reviewed commit): roster.test.ts's fix-audit block green — both named tests pass, i.e. requiredAgents contains role 0 under posture: 'critical' while this line says the roster omits it; roster.ts at HEAD reads if (isPositivePrNumber(plan.prNumber) && typeof plan.ownerRepo === 'string') { add('0'); } with no posture condition.
Rewrite the parenthetical to match the code, e.g. "0 (PR reviews — kept on a fix-audit round too: issue fidelity re-checks head against the issue whatever the diff displays, and it is the one auditor that can see a fix commit removing behaviour the issue required when the removal appears on neither side of base..head)", or delete it and the dangling cross-reference. Please also fix the same-class stale claim at docs/users/features/code-review.md:370 ("no issue-fidelity agent, which the full rounds already answered") in the same pass.
Fix witness: the two new roster.test.ts tests named above pin the behaviour the corrected sentence must describe — removing Agent 0 from the fix-audit roster turns both red. The prose itself is pinned by no test.
中文说明
本句称 fix-audit 轮的 roster"刻意省略" Agent 0(Issue Fidelity),但同一 PR 的代码、测试与设计记录都保留它:roster.ts 的 add('0') 对 PR plan 无条件执行(无姿态门槛;本 PR 在其上方新增的注释正是为了解释证伪"丢弃 Agent 0"的 probe);roster.test.ts 新增 "keeps Agent 0 and the territory shape on a small delta" 与 "keeps Agent 0 on a fix-audit round whose published scope shows no deletion" 两个用例,均在带姿态的 plan 下断言 expect(keys).toContain('0');DESIGN.md 写明 roster 保留全量形态运行的所有 agent,因为 issue fidelity 是唯一仍能看到该姿态标志性 Critical 类别的审计者。交叉引用"see Step 1's topology note"已不再支持该声称:HEAD commit 刚从该注释中移除了 Agent-0 排除声称(现在读作"the roster the plan builds already reflects the shape")。若在 fix-audit 轮中 Agent 0 启动失败或连续两次无实质返回,同一段落指示用 --role <role> 重建——一个被告知 role 0 被"刻意省略"的编排者会把幸存的块当作陈旧内容跳过重建,该轮便在没有 issue-fidelity 审计的情况下完成。按本 diff 自己的 roster 注释,接缝限宽的 base..head 范围使"修复 commit 删除了 issue 要求的行为"对其他所有审计者不可见(merge base 处不存在、head 处也不存在,removedLines 保持 0,hasDeletions 丢掉 1b,没有任何 chunk 领地显示该删除)——于是该回归恰好在本 PR 引入的这些轮次中悄无声息地合入。这是 R4-1 家族仍然敞开的兄弟入口:roster 门本身已修复(R4-1 的机制不会再触发),此文档声称在修复 commit 后幸存。
证据(在受审 commit 上的 probe):roster.test.ts 的 fix-audit 块全绿——上述两个用例均通过,即 posture: 'critical' 下 requiredAgents 含 role 0,而本行却称 roster 省略它;HEAD 处 roster.ts 为 if (isPositivePrNumber(plan.prNumber) && typeof plan.ownerRepo === 'string') { add('0'); },无姿态条件。
建议把该括注改写为与代码一致,例如 "0 (PR reviews — kept on a fix-audit round too: issue fidelity re-checks head against the issue whatever the diff displays, and it is the one auditor that can see a fix commit removing behaviour the issue required when the removal appears on neither side of base..head)",或直接删除该括注及悬空交叉引用;请在同一修复中一并改正 docs/users/features/code-review.md:370 处同类的陈旧声称("no issue-fidelity agent, which the full rounds already answered")。
修复验收:上述两个新增 roster.test.ts 用例钉住了修正后句子必须描述的行为——若把 Agent 0 从 fix-audit roster 中移除,两者都会变红;该散文本身无任何测试钉住。
— qwen3.8-max via Qwen Code /review (v0.22.2)
Conflicts resolved by keeping both sides: - compose-review.ts: union of the md-field and posture imports - SKILL.md: the branch's fix-audit 'effective' bullet with main's stop-sidecar 'upToDate' bullet - DESIGN.md: main's local-flow anchoring paragraph closing the import-hop section, then the branch's #10104 posture section Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…0136) The fix-audit roster keeps Agent 0 unconditionally for PR plans — the probe the roster comment records disproved dropping it — but three prose claims survived saying otherwise. Rewrite the Step 3B role-0 parenthetical and the user-docs fix-audit sentence to say the round keeps issue fidelity, and qualify the Step 6 floor paragraph and the floorEnforcedReroute docblock fail-open enumeration with the plan record arm they contradict. Also normalises pre-existing prettier markers on the edited docs line. Prose only; no behaviour change. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下: Address-review summary — PR #10136 (round 6)Dispositions[rc:3872893476] Critical R6-1 — SKILL.md says the fix-audit roster "deliberately omits" Agent 0 → FixedReproduced by inspection at the reviewed commit: Witness probe before editing: negating the Changes (commit
The prose itself is pinned by no test (as the finding noted); the two named [rv:5042213052] CHANGES_REQUESTED review body
Conflict resolution (
|
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
12 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-4 one-dry narrowing discriminating test — still standing at HEAD; already reported (comment 3864213983)
- role-brief seam-census clause untested — still standing at HEAD; already recorded in the round-4 deferral list (review 5037286144)
- R1-5 capture-time recorded-floor wiring tests — still standing at HEAD; already reported (comment 3864213990)
- SKILL.md exit-5/CONVERGED two-dry criterion stale (+ agent-prompt yargs help strings) — still standing at HEAD; already recorded in the round-4 deferral list (review 5037286144)
- fix-audit posture frame absent from reverse-audit role briefs — still standing at HEAD; already recorded in the round-3 deferral list (review 5036120762)
- explicit-cause branch and null fallback of the round-shape disclosure untested — still standing at HEAD; already recorded in the round-2 deferral list (review 5034611317)
- runAllChunks header tail grammar names only the retirement note — still standing at HEAD; already reported as R1-17 (comment 3864214106)
- round-shape disclosure wave-clause overclaims (round-2 full-waves case and unknown-exclusivity) — still standing at HEAD; already recorded in the round-4 deferral list (review 5037286144) and as R1-13 (comment 3864214070)
- SKILL.md:756 / narrowing-note 're-launches only' excludes the unknown-stays-hot class — still standing at HEAD; already reported as R1-13 (comment 3864214070)
- floorEnforcedReroute docblock fail-open enumeration contradicts the plan arm — still standing at HEAD; already recorded in the round-6 deferral list (review 5042213052)
- capture-time host axis weaker than submit's four-arm chain — still standing at HEAD at its original Suggestion severity; already reported as R1-12 (comment 3864214058)
- posture.ts header closure guarantee false for absent/unrecognised floor states — still standing at HEAD; already recorded in the round-3 deferral list (review 5036120762)
Not explored to full depth (tool budget reached): chunk 7: run posture.test.ts and retirement.test.ts to confirm they pass (blocked: no node_modules installed in the review worktree); chunk 8: execute roster.test.ts to confirm the four new tests are green — the review worktree has no node_modules (vitest unresolvable) and a monorepo npm ci plus ….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 7, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/lib/roster.ts:225 — [review] PR description still claims the fix-audit roster drops Agent 0 (four sites)packages/cli/src/commands/review/lib/import-graph.ts:307 (+3 locations) — [probe] three untested seam-oracle branches: default-import arm :307, whole-module require arm :387, side-effect/dynamic-import alternative :370packages/cli/src/commands/review/agent-prompt.ts:2830 — [probe] postureNarrowing classifies a malformed chunk entry as non-delta (fails toward less coverage)packages/core/src/skills/bundled/review/SKILL.md:756 — [review] convergence-pair bullet ('stays under every-round audit') contradicted by the narrowingpackages/cli/src/commands/review/lib/incremental-scope.ts:153 — [probe] hunk-containment boundaries pinned by no discriminating test (strict-inequality mutant survives 7/7)packages/core/src/skills/bundled/review/SKILL.md:900 — [probe] 'the posting bar can never disagree' falsified by the absent-floor divergence
Convergence: round 7 posted 1 inline comment(s), 1 of them reported for the first time; the previous round posted 1 (1 new). The rate of new findings is not falling. Batching the remaining fixes and verifying them before the next push keeps the loop from re-deriving the same set; this PR's reviews already resolve to a critical posting floor. (Observation only — nothing was withheld from this review because of this observation.)
Residual risk: this loop is persistently critical — Criticals stood in the previous round's work-list and stand again this round (1 Critical(s)), the rate of first-time findings is not falling (this round 1, previous 1), and the standing Critical backlog is not shrinking. The severity floor will not converge it. Recommendation: land-with-residual-risk — the exit is a maintainer risk-acceptance decision (merge, carrying the residual risk), not another review round. Residual-risk inventory for that decision (maintainer to complete):
| standing Critical | attack surface | attacker-dependency | blast radius |
|---|---|---|---|
| (each standing Critical) | … | … | … |
Advisory only — it does not block this review.
中文说明
本轮确认的 12 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):chunk 7:run posture.test.ts and retirement.test.ts to confirm they pass (blocked: no node_modules installed in the review worktree);chunk 8:execute roster.test.ts to confirm the four new tests are green — the review worktree has no node_modules (vitest unresolvable) and a monorepo npm ci plus …。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 7 轮,非阻断)——已记录,本轮不要求修改:共 6 条(原文未翻译,列表见上方英文部分)。
收敛情况:第 7 轮发布了 1 条行内评论,其中 1 条是首次提出;上一轮发布了 1 条(其中 1 条首次提出)。新发现的产出速度没有下降。把剩余修复攒成一批、验证后再推送,可以避免循环反复推导同一组发现;本 PR 的评审已解析为 critical 发布下限。(仅为观察——本轮评审未因此扣留任何内容。)
残余风险:本循环处于 persistently-critical 形态——上一轮工作清单中的 Critical 本轮依然存在(本轮 1 条 Critical),首次发现的速率没有下降(本轮 1,上一轮 1),且未决 Critical 积压没有减少。severity floor 无法使其收敛。建议:land-with-residual-risk——出口是 maintainer 的风险接受决定(合入并承担残余风险),而非再开一轮评审。供该决定使用的残余风险清单(maintainer 填写):按每条未决 Critical 列出「攻击面 · 攻击者依赖性 · 影响范围」三栏。仅为建议——不阻断本次评审。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| What deliberately did not change: the floor's own resolution and enforcement (compose-time, marker-stamped, exactly as before — the plan-time half only predicts it), finding severities (the posture governs posting, never finding, and the fix-audit brief says so), the standing-blocker re-check and the ledger rulings Step 6 owes, the two-consecutive-dry stop rule, and the verdict semantics. The disclosures are the price of every reduction: the plan records posture, cause and census; the chunk brief names its file's bound; the round output carries a `posture narrowing:` note beside the retirement note; and `compose-review` puts one round-shape sentence in the posted body, so the reduced coverage is a fact on the record rather than a diff of agent counts. | ||
|
|
||
| One known widening of an existing gap, named rather than discovered: the backward base-move smuggle (see the roster's heavy-interaction-file comment) already relies on hunks arriving inside a republished full-range slice; a seam-bounded round republishes less, so smuggled hunks outside the seam go unread on exactly these rounds. The exposure is bounded by the posture's own preconditions — a long-lived PR whose base is retargeted mid-loop, in the same window a round is running critical-only — and the heavy-file invariant agents, which read whole files from the worktree, keep their coverage regardless. |
There was a problem hiding this comment.
[Critical] R7-1: The bounding claim this paragraph adds for the acknowledged backward base-move smuggle — "the heavy-file invariant agents ... keep their coverage regardless" — is falsified by the seam-bounding this same PR adds.
Heaviness is classified from the PUBLISHED slice: publish(narrowed) makes the seam-bounded bytes the diff, buildDiffPlan/buildPlanReport compute changedLines from that slice, and classifyHeavy (ratio ≥ 0.4 or changedLines ≥ 800, preLines ≥ 300) then rules on it. Seam-bounding shrinks exactly that slice for interaction files, so a file that is heavy on its full-range slice flips non-heavy, heavyFiles() drops it, and invariant-a/b/c never launch — on exactly the seam-bounded rounds this paragraph is about. The roster comment names these three agents as the only ones that would have walked the smuggled newBase..anchor hunks; a clean verdict then re-anchors past them permanently.
Witness (probe through the real capture path, scratch tree — a 1800-line interaction file with 900 changed lines in 9 hunks, seam line outside every hunk):
BASE (full widening): "changedLines": 900, "rewriteRatio": 0.5, "heavy": true
PR (seam-bounded): census {"kept":0,"total":9}; published hunks: none
"changedLines": 0, "rewriteRatio": 0, "heavy": false
Suggested fix: classify interaction-file heaviness from the full-range capture — fetch-pr already holds fullText; derive per-file added/removed counts for incremental.scope.interaction[] paths from the full-range parse and carry them into buildPlanReport, so the invariant agents keep running on seam-bounded rounds. If the flip is an accepted trade instead, rewrite this sentence to name the lapse rather than claiming coverage is kept "regardless".
Fix witness: please add a fetch-pr.test.ts case beside the existing seam fixture — a posture capture where an interaction file's full-range slice clears the heavy bar while its seam-bounded slice keeps one hunk or none, asserting heavy: true survives for that path (so requiredAgents demands invariant-a/b/c--<path>); removing the full-range carry must turn it red.
中文说明
本段为已知的 backward base-move 夹带所加的边界声明——"heavy-file invariant agents……无论如何保留覆盖"——被同一 PR 新增的接缝限宽证伪。重度分类基于发布后的切片(publish(narrowed) 的字节 → buildDiffPlan/buildPlanReport 的 changedLines → classifyHeavy),而接缝限宽恰好收缩 interaction 文件的该切片:一个在全量范围切片上为 heavy 的文件,在接缝限宽轮翻转为非 heavy,heavyFiles() 丢掉它,invariant-a/b/c 不会启动——而那正是本段描述的轮次。roster 注释称这三个 agent 是唯一会审计夹带 newBase..anchor hunks 的审计者;干净的判定会越过它们永久重新落锚。证据(对真实捕获路径的 probe,1800 行、900 行改动、9 个 hunks、接缝行在所有 hunk 之外):全量加宽下 heavy: true;接缝限宽下(缝合计数 0/9、发布 hunks 为空)heavy: false。修复:用全量捕获计算 interaction 文件的重度(fetch-pr 已持有 fullText,对 incremental.scope.interaction[] 路径从全量解析派生增删行数并带入 buildPlanReport);若该翻转属已知取舍,请改写本句如实声明,而不是声称覆盖"无论如何保留"。修复验收:请在现有接缝 fixture 旁新增 fetch-pr.test.ts 用例——一次姿态捕获中,某 interaction 文件的全量切片达到 heavy 栏而其接缝限宽切片只保留 0-1 个 hunk,断言该路径仍为 heavy: true(即 requiredAgents 要求 invariant-a/b/c--<path>);移除全量携带后该测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x), Post Coverage Comment (ubuntu-latest, 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x), Post Coverage Comment (ubuntu-latest, 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
12 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- narrowing one-dry bar discriminating test ([YIELD, DRY] history) — already reported as R1-4 (comment 3864213983)
- exit-5/CONVERGED two-dry criterion stale in agent-prompt yargs help strings — already recorded in the round-4 deferral list (review 5037286144)
- SKILL.md exit-5/CONVERGED paragraph stale for the one-dry narrowed exit — already recorded in the round-4 deferral list (review 5037286144)
- capture-time recorded-floor host axis weaker than submit's four-arm chain — already reported as R1-12 (comment 3864214058)
- fetch-pr capture-time recorded-floor wiring untested — already reported as R1-5 (comment 3864213990)
- SKILL.md tier parenthetical contradicts the huge gate checked first — already reported as R1-15 (comment 3864214093)
- launch-preamble tail grammar names only the retirement note — already reported as R1-17 (comment 3864214106)
- role-brief seam-census clause untested — already recorded in the round-4 deferral list (review 5037286144)
- seamLines default-import / whole-module-require / side-effect branches untested — already recorded in the round-7 deferral list (review 5048223579)
- compose-side seam-census admission guard untested — already recorded in the round-2 deferral list (review 5034611317)
- SKILL.md 'the posting bar can never disagree' absolute — already recorded in the round-3 and round-7 deferral lists (reviews 5036120762, 5048223579)
- narrowing-note 're-launches only' excludes the unknown-stays-hot class — already reported as R1-13 (comment 3864214070)
Not explored to full depth (tool budget reached): chunk 5: could not execute import-graph.test.ts / budget.test.ts / incremental-scope.test.ts — no node_modules in this worktree or its parent checkout; verificat….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 8, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/lib/incremental-scope.ts:148 — [review] hunk-less-section doubt state of the seam bound has no testpackages/cli/src/commands/review/compose-review.ts:2895 — [review] posted seam census understates republication from a doubt state
Convergence: round 8 posted 3 inline comment(s), 2 of them reported for the first time; the previous round posted 1 (1 new). The rate of new findings is not falling. Batching the remaining fixes and verifying them before the next push keeps the loop from re-deriving the same set; this PR's reviews already resolve to a critical posting floor. (Observation only — nothing was withheld from this review because of this observation.)
Residual risk: this loop is persistently critical — Criticals stood in the previous round's work-list and stand again this round (3 Critical(s)), the rate of first-time findings is not falling (this round 2, previous 1), and the standing Critical backlog is not shrinking. The severity floor will not converge it. Recommendation: land-with-residual-risk — the exit is a maintainer risk-acceptance decision (merge, carrying the residual risk), not another review round. Residual-risk inventory for that decision (maintainer to complete):
| standing Critical | attack surface | attacker-dependency | blast radius |
|---|---|---|---|
| (each standing Critical) | … | … | … |
Advisory only — it does not block this review.
中文说明
本轮确认的 12 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):chunk 5:could not execute import-graph.test.ts / budget.test.ts / incremental-scope.test.ts — no node_modules in this worktree or its parent checkout; verificat…。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 8 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
收敛情况:第 8 轮发布了 3 条行内评论,其中 2 条是首次提出;上一轮发布了 1 条(其中 1 条首次提出)。新发现的产出速度没有下降。把剩余修复攒成一批、验证后再推送,可以避免循环反复推导同一组发现;本 PR 的评审已解析为 critical 发布下限。(仅为观察——本轮评审未因此扣留任何内容。)
残余风险:本循环处于 persistently-critical 形态——上一轮工作清单中的 Critical 本轮依然存在(本轮 3 条 Critical),首次发现的速率没有下降(本轮 2,上一轮 1),且未决 Critical 积压没有减少。severity floor 无法使其收敛。建议:land-with-residual-risk——出口是 maintainer 的风险接受决定(合入并承担残余风险),而非再开一轮评审。供该决定使用的残余风险清单(maintainer 填写):按每条未决 Critical 列出「攻击面 · 攻击者依赖性 · 影响范围」三栏。仅为建议——不阻断本次评审。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| What deliberately did not change: the floor's own resolution and enforcement (compose-time, marker-stamped, exactly as before — the plan-time half only predicts it), finding severities (the posture governs posting, never finding, and the fix-audit brief says so), the standing-blocker re-check and the ledger rulings Step 6 owes, the two-consecutive-dry stop rule, and the verdict semantics. The disclosures are the price of every reduction: the plan records posture, cause and census; the chunk brief names its file's bound; the round output carries a `posture narrowing:` note beside the retirement note; and `compose-review` puts one round-shape sentence in the posted body, so the reduced coverage is a fact on the record rather than a diff of agent counts. | ||
|
|
||
| One known widening of an existing gap, named rather than discovered: the backward base-move smuggle (see the roster's heavy-interaction-file comment) already relies on hunks arriving inside a republished full-range slice; a seam-bounded round republishes less, so smuggled hunks outside the seam go unread on exactly these rounds. The exposure is bounded by the posture's own preconditions — a long-lived PR whose base is retargeted mid-loop, in the same window a round is running critical-only — and the heavy-file invariant agents, which read whole files from the worktree, keep their coverage regardless. |
There was a problem hiding this comment.
[Critical] R7-1: Still stands — re-verified at this commit (HEAD moved only via a merge of main; DESIGN.md is unchanged since round 7). The bounding claim this paragraph adds for the acknowledged backward base-move smuggle — "the heavy-file invariant agents ... keep their coverage regardless" — is falsified by the seam-bounding this same PR adds. Heaviness is classified from the PUBLISHED slice: publish(narrowed) makes the seam-bounded bytes the diff, buildDiffPlan/buildPlanReport compute changedLines from that slice, and classifyHeavy (ratio ≥ 0.4 or changedLines ≥ 800, preLines ≥ 300) rules on it. Seam-bounding shrinks exactly that slice for interaction files, so a file that is heavy on its full-range slice flips non-heavy, heavyFiles() drops it, and invariant-a/b/c never launch — on exactly the seam-bounded rounds this paragraph is about. The roster comment names these three agents as the only ones who would have walked the smuggled newBase..anchor hunks; a clean verdict then re-anchors past them permanently. Witness (probe through the real plan builder at this commit):
BASE (full widening): {"changedLines":900,"rewriteRatio":0.33,"heavy":true}
PR (seam-bounded): {"changedLines":0,"rewriteRatio":0,"heavy":false}
Either classify interaction-file heaviness from the full-range capture — fetch-pr already holds fullText; derive per-file added/removed counts for incremental.scope.interaction[] paths from the full-range parse and carry them into buildPlanReport, so the invariant agents keep running on seam-bounded rounds — or rewrite this sentence to name the lapse rather than claiming coverage is kept "regardless". Fix witness: please add a fetch-pr.test.ts case beside the existing seam fixture — a posture capture where an interaction file's full-range slice clears the heavy bar while its seam-bounded slice keeps one hunk or none, asserting heavy: true survives for that path (so requiredAgents demands invariant-a/b/c--<path>); removing the full-range carry must turn it red.
中文说明
仍然成立——已在本 commit 复核(HEAD 仅为一次 main 合并;DESIGN.md 自第 7 轮起未变)。本段为已知的 backward base-move 夹带所加的边界声明——"heavy-file invariant agents……无论如何保留覆盖"——被同一 PR 新增的接缝限宽证伪。重度分类基于发布后的切片:publish(narrowed) 的字节成为 diff,buildDiffPlan/buildPlanReport 从该切片计算 changedLines,classifyHeavy(ratio ≥ 0.4 或 changedLines ≥ 800、preLines ≥ 300)据此判定。接缝限宽恰好收缩 interaction 文件的该切片:全量切片上为 heavy 的文件翻转为非 heavy,heavyFiles() 丢掉它,invariant-a/b/c 不会启动——而那正是本段描述的轮次。roster 注释称这三个 agent 是唯一会审计夹带 newBase..anchor hunks 的审计者;干净的判定会越过它们永久重新落锚。证据(在本 commit 上对真实 plan 构建路径的 probe):全量加宽 {"changedLines":900,"rewriteRatio":0.33,"heavy":true};接缝限宽 {"changedLines":0,"rewriteRatio":0,"heavy":false}。修复:用全量捕获计算 interaction 文件的重度(fetch-pr 已持有 fullText,对 incremental.scope.interaction[] 路径从全量解析派生增删行数并带入 buildPlanReport);若该翻转属已知取舍,请改写本句如实声明,而不是声称覆盖"无论如何保留"。修复验收:请在现有接缝 fixture 旁新增 fetch-pr.test.ts 用例——一次姿态捕获中,某 interaction 文件的全量切片达到 heavy 栏而其接缝限宽切片只保留 0-1 个 hunk,断言该路径仍为 heavy: true(即 requiredAgents 要求 invariant-a/b/c--<path>);移除全量携带后该测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| : severityFloor === 'suggestion' | ||
| ? 'the operator turned the posture off (`--severity-floor suggestion`)' | ||
| : severityFloor === 'auto' && contextUnavailable | ||
| : severityFloor === 'auto' && contextUnavailable && fixAudit === null |
There was a problem hiding this comment.
[Critical] The licence chain's floorAbsent arm — directly above this line — short-circuits to unlicensed-deferral before consulting fixAudit, unlike the two sibling doubt arms here, which this diff gave && fixAudit === null. A fix-audit round whose compose state omits severityFloor — a state this module's own comment calls reachable (the field is model-written, "omission is fail-closed"; an unrecognisable spelling folds to the same arm) — with model-side deferredSuggestions gains a false cap: cappedBy gains unlicensed-deferral, the verdict is capped, the incremental anchor withheld, and the posted body pairs "deferred without a posture licence — the state carried no recognisable severityFloor, so the licence cannot be checked" with the same body's round-shape disclosure asserting the round ran as a fix-audit round under the critical posting posture — off the very plan record that IS the licence. The arm's own rationale cannot hold here: "the licence cannot be checked" is false (the plan record is checkable and is the licence), and "the channel ships in the same PR as the field" cannot apply, because a plan carrying the fix-audit record is necessarily a round of this PR's era. Enforcement facet of the same root: an absent state floor normalises to undefined, so the enforcement leg's fix-audit arm (gated on floor === 'auto') never fires — drafted Suggestions post inline in full beside a marker that stamps floor c (the reporting leg folds absence to auto), falsifying posture.ts's header claim and DESIGN.md's "the one combination nothing licenses — narrowed coverage posting in full — is unreachable on the auto path". Witness (probe through the real composeReview, scratch tree):
P1 (postured plan, severityFloor omitted, one model-side deferral):
cappedBy=["unlicensed-deferral"], event capped APPROVE→COMMENT, body carries the
unlicensed warning + shape disclosure + open sentence together,
marker={...,"floor":"c"} with no sha (anchor withheld)
P2 (same plan, drafted inline Suggestion): floorEnforced=[], Suggestion posts, marker stamps "c"
P3 (control, severityFloor 'auto' present): cappedBy=[], marker rides with sha
Flip: with `floorAbsent && fixAudit === null`, P1 flips to APPROVE, warning gone, sha present
Gate the arm like its siblings — floorAbsent && fixAudit === null — so with the plan record present the chain falls through to the already fixAudit-aware arms and resolves licensed; for the enforcement facet, fire the fix-audit arm whenever fixAuditPlan === true && floor !== 'suggestion' (an explicit operator suggestion still wins), or fold absent/unrecognisable floors to auto before both legs. Fix witness: a compose-review.test.ts case — rcInput(POSTURE) with severityFloor omitted and one valid model-side deferredSuggestions entry; assert r.cappedBy does not contain 'unlicensed-deferral' and r.body does not contain 'without a posture licence'; removing the bypass must turn it red.
中文说明
许可链的 floorAbsent 臂(就在本行上方)在查询 fixAudit 之前即短路为 unlicensed-deferral,而本 diff 给它的两个兄弟疑态臂都加了 && fixAudit === null。一个 compose 状态省略 severityFloor 的 fix-audit 轮(本模块注释称该状态可达:字段为模型所写、"省略按 fail-closed 处理";无法识别的拼写折叠到同一臂),只要带有模型侧 deferredSuggestions,就会获得虚假 cap:cappedBy 新增 unlicensed-deferral,判定被封顶、增量锚点被扣留,且同一篇发布正文既出现 "deferred without a posture licence — the state carried no recognisable severityFloor, so the licence cannot be checked",又出现断言本轮以 critical 发布姿态运行了 fix-audit 形态的 round-shape 披露——而该 plan 记录本身就是许可。该臂自己的理由在此不成立:"许可无法检查"是假的(plan 记录可查且就是许可);"通道与字段同 PR 发布"也不适用,因为带 fix-audit 记录的 plan 必然属于本 PR 时代的轮次。同根的强制侧:缺失的状态下限归一化为 undefined,强制腿的 fix-audit 臂(门控 floor === 'auto')永不触发——起草的 Suggestion 原样内联发布,而 marker 却盖 floor: 'c'(报告腿把缺失折叠为 auto),证伪 posture.ts 头部声明与 DESIGN.md "narrowed coverage posting in full 这一组合在 auto 路径上不可达"的说法。证据(对真实 composeReview 的 probe):P1 cappedBy=["unlicensed-deferral"]、事件由 APPROVE 封顶为 COMMENT、正文同时含无许可警告+形态披露+开放句、marker floor:"c" 且无 sha;P2 floorEnforced=[]、Suggestion 照发、marker 盖 c;P3(对照,severityFloor:'auto' 存在)cappedBy=[]、marker 带 sha;翻转:加 floorAbsent && fixAudit === null 后 P1 回到 APPROVE、警告消失、sha 恢复。修复:把该臂改为与兄弟一致的 floorAbsent && fixAudit === null,使 plan 记录存在时链条落入已感知 fixAudit 的臂并判为有许可;强制侧请把 fix-audit 臂放宽为 fixAuditPlan === true && floor !== 'suggestion'(操作者显式 suggestion 仍然获胜),或在两腿之前把缺失/无法识别的下限折叠为 auto。修复验收:新增 compose-review.test.ts 用例——rcInput(POSTURE) 省略 severityFloor 且带一条合法的模型侧 deferredSuggestions,断言 r.cappedBy 不含 'unlicensed-deferral'、r.body 不含 'without a posture licence';移除该旁路后测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| if (narrowing != null && !narrowing.deltaChunkIds.has(chunkId)) { | ||
| const latest = audits[audits.length - 1]; | ||
| if (latest !== undefined && latest.outcome === 'dry') { |
There was a problem hiding this comment.
[Critical] The narrowing arm consults only the latest outcome, and the convergence-pair shape falsifies the re-launch claim this feature documents. Fix-audit rounds are always 3B and run rounds 1+2 as the convergence pair against the SAME findings digest — so a non-delta chunk whose round-1 pair member YIELDED (filed findings) and whose round-2 pair member returned a substantive dry receipt holds [yielded, dry], where the dry receipt predates round 1's findings entering the cumulative list — exactly the staleness SKILL.md names for the pair ("a dry member of a reporting pair is not carried forward as half of that evidence — its dry predates the other member's findings entering the list"). At round 3 this arm rules before retirement (which would see the yield), reads latest.outcome === 'dry', and narrows the chunk out permanently — narrowed chunks never earn cold checks — so every post-finding wave on that territory is lost, priced by a receipt that never saw the finding. The added claim (SKILL.md:756, the posture narrowing: note, DESIGN.md) — "the wave re-launches only the delta territories and whatever the previous wave surfaced findings in" — is falsified: the pair surfaced findings in this territory and it is never re-launched. If all other chunks have also left, the loop exits CONVERGED — a "clean convergence" certified over a territory with a live round-1 finding. Witness (probe through the real scheduleReverseAuditRound, scratch tree):
UNMODIFIED PR, round 3: due=[] narrowed=[{chunkId:14, dryRound:2}] converged=true
UNMODIFIED PR, round 4: chunk 14 still narrowed, no cold check
WITH the digest guard: round 3: due=[14] narrowed=[] converged=false
(149/149 existing retirement tests still pass with the fix)
In the narrowing arm, treat the latest dry as non-decisive when the chunk's history contains a yielded round whose recorded findings digest equals the dry receipt's digest — the pair's shared list; both record keys carry it — and fall through to the ordinary rules there. Serial rounds are unaffected: a round built after a yielded round carries a different merged digest, and dry+dry on one digest has no yield to be stale against. Fix witness: extend the #10104 narrowing test in retirement.test.ts with a non-delta chunk holding record(1) YIELD + record(2) DRY on one shared findings digest and assert it lands in r3.due, not r3.narrowed; removing the guard must turn it red.
中文说明
收窄臂只读取最新一次结果,而收敛对(convergence pair)形态证伪了本特性文档化的重启声明。fix-audit 轮恒为 3B,且第 1+2 轮作为收敛对、基于同一 findings 摘要同时构建——因此一个非 delta chunk 若第 1 轮成员 YIELD(提交了发现)、第 2 轮成员返回实质性干燥收据,其历史为 [yielded, dry],而该干燥收据早于第 1 轮的发现进入累计清单——正是 SKILL.md 为收敛对点名的陈旧性("报告对中干燥成员不作为一半证据携带——它的干燥早于对方成员的发现进入清单")。第 3 轮时本臂先于 retirement 判定(后者会看到 yield),读取 latest.outcome === 'dry',把该 chunk 永久收窄出局——收窄的 chunk 永不获得冷检——于是该领地上所有"发现之后"的波次全部丢失,定价依据是一份从未见过该发现的收据。新增声称(SKILL.md:756、posture narrowing: note、DESIGN.md)——"波次只重启 delta 领地与上一波有发现的领地"——被证伪:收敛对在该领地有过发现,它却永不再被重启。若其他 chunk 也已离场,循环以 CONVERGED 退出——一个"干净收敛"在仍有第 1 轮活发现的领地上被认证。证据(对真实 scheduleReverseAuditRound 的 probe):未修改 PR 第 3 轮 due=[] narrowed=[{chunkId:14,dryRound:2}] converged=true;第 4 轮 chunk 14 仍被收窄、无冷检;加上摘要守卫后第 3 轮 due=[14] narrowed=[] converged=false(149/149 现有 retirement 测试在修复后仍全绿)。修复:在收窄臂中,当该 chunk 的历史包含一个 yielded 轮、且其记录的 findings 摘要与干燥收据的摘要相同(即收敛对共享的清单,两个记录键都携带它)时,视最新干燥为不决定,落入普通规则;串行轮不受影响——yielded 轮之后构建的轮携带不同的合并摘要,同一摘要上的 dry+dry 也没有可被它陈旧的 yield。修复验收:给 retirement.test.ts 的 #10104 收窄测试新增一个非 delta chunk,持有共享同一 findings 摘要的 record(1) YIELD + record(2) DRY,断言它落在 r3.due 而非 r3.narrowed;移除守卫后测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x), Post Coverage Comment (ubuntu-latest, 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x), Post Coverage Comment (ubuntu-latest, 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
10 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-4 narrowing one-dry bar discriminating test — already reported (comment 3864213983)
- R1-5 capture-time recorded-floor wiring tests — already reported (comment 3864213990)
- R1-7 seam census recorded unconditionally (kept===total phantom cleared hunks) — already reported (comment 3864214000)
- R1-12 capture-time recorded-floor identity axes (host chain and skillArgs seam) — already reported (comment 3864214058)
- R1-13 narrowing-note re-launches ONLY omits unknown-stays-hot — already reported (comment 3864214070)
- R1-14 RoundSchedule.converged contract and exit-5 two-dry criterion stale — already reported (comment 3864214075)
- R1-15 SKILL.md tier parenthetical vs huge gate — already reported (comment 3864214093)
- R1-17 launch-preamble tail grammar names only the retirement note — already reported (comment 3864214106)
- engaged-floor sentence fabricates a deferral when nothing was deferred — already recorded in the round-2 and round-3 deferral lists (reviews 5034611317, 5036120762)
- role-brief seam-census clause untested — already recorded in the round-4 deferral list (review 5037286144)
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory.
Deferred under the convergence posture (round 9, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/fetch-pr.ts:1424 — [review] demoted-round posture guard has no testpackages/cli/src/commands/review/lib/posture.ts:103 — [review] honest-maximum flat-streak clamp restated a third time instead of shared
中文说明
本轮确认的 10 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory。
收敛姿态下延后(第 9 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| const at = m.index ?? 0; | ||
| let start = -1; | ||
| for (const km of source | ||
| .slice(0, at) | ||
| .matchAll(/(^|[^\w$])(?:import|export)(?![\w$])/g)) { |
There was a problem hiding this comment.
[Critical] R9-1: seamLines hand-rolls clause parsing over raw source text with regexes that have no comment/string awareness, and widenScope's seamBound arm trusts that oracle with no doubt state for under-collection — so on ordinary code an interaction-file hunk is silently shed from republication while the census and the brief describe the shed as deliberate. A trailing comment inside a multiline import displaces the keyword-bound scan: for import { moved, // TODO: import more } from './changed.js'; followed by moved();, the scan matches the import inside the comment instead of the statement keyword, so seamLines returns [2,3] instead of [2,3,4] and the usage line never marks the hunk that displays it; a second demonstrated entrance is the decl pattern's =\s*$ tail, which never matches const api = await , so awaited dynamic imports never collect their bindings at all. A fix-audit round whose whole point is re-asking the seam question then loses exactly the caller-side hunk, and this diff is already the accumulating-corner pattern ($-escaping, keyword-in-binding, multiline wrap each got their own special case and regression test).
Witness (probe at this commit, flip confirmed):
PR code, commented input : [2,3] <- line 4 (moved();) dropped
PR code, uncommented twin: [2,3,4]
with comment-strip fix : [2,3,4] <- probe flips
Close the class structurally rather than adding the next corner: read the file through an authoritative parser (the TypeScript compiler is already a workspace dependency), or make the clause read fail-closed into widenScope's existing doubt-state arm (republish the file full-range) whenever the bound clause cannot be parsed to bindings consistent with what the statement visibly declares. Fix witness: an import-graph.test.ts case where the multiline clause with a trailing comment must still mark the usage line — it is red today; removing the fix re-drops the line.
中文说明
seamLines 用对注释/字符串无感知的正则在原始源码文本上手工解析子句,而 widenScope 的 seamBound 臂对该预言机的收集不足没有任何疑态——普通代码下,interaction 文件的 hunk 会被悄无声息地从重发中剔除,而计数与 brief 却把这次剔除描述成有意为之。多行 import 中的行尾注释会错位关键词定界扫描:对 import { moved, // TODO: import more } from './changed.js'; 后跟 moved();,扫描命中的是注释里的 import 而不是语句关键词,于是 seamLines 返回 [2,3] 而非 [2,3,4],使用行永远不会标记显示它的 hunk;第二个已证实的入口是声明模式的 =\s*$ 尾部永远匹配不上 const api = await ,await 动态 import 的绑定根本不会被收集。fix-audit 轮的全部意义就是重问接缝问题,却恰好丢掉调用方侧的 hunk;本 diff 已经是"逐角累积"模式($ 转义、绑定名含关键词、多行换行各自都打过补丁和回归测试)。证据(本提交上 probe,翻转已确认):见英文部分。建议结构性关闭该类:改用权威解析器(TypeScript 编译器已是工作区依赖),或在子句无法解析出与语句声明一致的绑定时,让该读取失败闭合到 widenScope 已有的疑态臂(全量重发)。修复验收:新增 import-graph.test.ts 用例——带行尾注释的多行子句必须仍标记使用行;当前为红,移除修复会再次变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| ? 'the round is unknowable in the context-unavailable state' | ||
| : severityFloor === 'auto' && prevRound === 0 | ||
| : severityFloor === 'auto' && prevRound === 0 && fixAudit === null | ||
| ? 'no posture is engaged on round 1 and no age reference exists' |
There was a problem hiding this comment.
[Critical] R8-1: Still stands — re-verified at this commit (the branch head moved only via a merge of main since round 8). The licence chain's floorAbsent arm — directly above this line — short-circuits to unlicensed-deferral before consulting fixAudit, unlike the two sibling doubt arms here, which this diff gave && fixAudit === null. A fix-audit round whose compose state omits severityFloor — a state this module's own comment calls reachable (the field is model-written, and omission is fail-closed): the model defers its drafted Suggestions under the plan-arm floor exactly as the shape intends, but floorAbsent is consulted first in the unlicensedDeferral ternary, so the licence fires, caps the verdict, and withholds the anchor for a deferral that is precisely what the floor arm enforced — falsifying this file's own documented invariant that enforcement fires only under conditions where the licence already holds.
Witness: not run — the misfire needs a model-deferred fix-audit compose beside an absent floor; the arm's precedence was re-read from the code at HEAD this round (the ternary consults floorAbsent before any fixAudit condition), matching round 8's probe-confirmed trace.
Give the floorAbsent arm the same plan-record consultation its two siblings received: when fixAudit is non-null the round's shape was spent on the critical resolution, so its deferrals are licensed. Fix witness: a compose-review.test.ts case — fix-audit plan record + absent severityFloor + one deferred Suggestion must compose without unlicensed-deferral in cappedBy; reverting the gate re-fires the cap and the test goes red.
中文说明
仍未解决——已在当前提交重新验证(第 8 轮之后分支头仅通过 main 的合并移动)。许可链的 floorAbsent 臂——就在本行上方——在咨询 fixAudit 之前就短路到 unlicensed-deferral,而这里的两个兄弟疑态臂本 diff 已加上 && fixAudit === null。一个 compose 状态省略了 severityFloor 的 fix-audit 轮(本模块注释称该状态可达——字段由模型写入,省略按失败闭合处理):模型按形态设计在 plan 臂下限下延后了起草的 Suggestion,但 floorAbsent 在 unlicensedDeferral 三元链中最先被咨询,于是许可触发、封顶判定、扣下锚点——而这次延后恰恰是下限臂强制执行的结果,违反了本文件自己写明的不变量"强制只在许可已成立的状态下触发"。证据:未执行——触发需要一个伴随缺失下限、且模型已延后的 fix-audit compose;本轮已在 HEAD 代码中重读该臂的优先级(三元链先咨询 floorAbsent,再到任何 fixAudit 条件),与第 8 轮 probe 确认的追踪一致。建议:让 floorAbsent 臂获得与两个兄弟相同的 plan 记录咨询——fixAudit 非 null 时,该轮的形态已为 critical 决议付出,其延后应判为有许可。修复验收:新增 compose-review.test.ts 用例——fix-audit plan 记录 + 缺失 severityFloor + 一条延后的 Suggestion,合成结果的 cappedBy 不得包含 unlicensed-deferral;还原该门后测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| if (narrowing != null && !narrowing.deltaChunkIds.has(chunkId)) { | ||
| const latest = audits[audits.length - 1]; | ||
| if (latest !== undefined && latest.outcome === 'dry') { |
There was a problem hiding this comment.
[Critical] R8-2: Still stands — re-verified at this commit (the branch head moved only via a merge of main since round 8). The narrowing arm consults only the latest outcome, and the convergence-pair shape falsifies the re-launch claim this feature documents. Fix-audit rounds are always 3B and run rounds 1+2 as the convergence pair against the SAME findings digest — so a non-delta chunk whose round-1 pair member YIELDED (filed findings) and whose round-2 pair member returned a substantive dry receipt narrows out from wave 3 on latest.outcome === 'dry' alone, although the posted note, the chunk brief, and SKILL.md all promise the wave "re-launches ... whatever the previous wave surfaced findings in". The yield's findings surfaced under the pair's one-round suppression window (the round-2 auditor could not see them as confirmed), and the territory they point at leaves the schedule after one dry audit that post-dates them.
Witness: not run — reproducing it needs a multi-wave round history through the real builder; the arm was re-read at HEAD this round (only audits[audits.length - 1] is consulted; the round-1 yield is invisible to the bar), matching round 8's trace.
Make the bar pair-aware: a non-delta chunk stays hot while any audit inside the convergence-pair window yielded — or treat a yield anywhere in the history as disqualifying for the one-dry exit until a dry receipt post-dates it. Fix witness: a retirement.test.ts case — non-delta chunk with round-1 YIELD and round-2 DRY under a fix-audit narrowing must remain due at round 3; restoring the latest-only bar narrows it out and the test goes red.
中文说明
仍未解决——已在当前提交重新验证(第 8 轮之后分支头仅通过 main 的合并移动)。收窄臂只查询最近一次的结局,而收敛对(convergence pair)形态证伪了本功能文档承诺的重启声明。fix-audit 轮恒为 3B,且第 1+2 轮作为收敛对在同一份发现清单上运行——于是某非 delta chunk 的第 1 轮对成员 YIELDED(提交过发现)、第 2 轮对成员返回实质性干燥收据时,仅凭 latest.outcome === 'dry' 就在第 3 波被收窄出局,而发布 note、chunk brief 与 SKILL.md 都承诺波次"会重启上一波浮现过发现的领地"。该 yield 的发现是在收敛对的一轮抑制窗口内浮现的(第 2 轮审计者看不到它们已被确认),其指向的领地却在一次晚于它们的干燥审计后即退出调度。证据:未执行——复现需要经真实 builder 的多波次轮史;本轮已在 HEAD 重读该臂(只咨询 audits[audits.length - 1],第 1 轮的 yield 对该门槛不可见),与第 8 轮追踪一致。建议:让门槛感知收敛对——收敛对窗口内任何审计 yield 过,非 delta chunk 就保持热态;或在历史中任何位置出现过 yield 时取消其一次干燥即退出的资格,直到有更晚的干燥收据。修复验收:新增 retirement.test.ts 用例——fix-audit 收窄下,第 1 轮 YIELD、第 2 轮 DRY 的非 delta chunk 在第 3 轮必须仍在 due 中;还原"只看最近"的门槛后测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
|
||
| What deliberately did not change: the floor's own resolution and enforcement (compose-time, marker-stamped, exactly as before — the plan-time half only predicts it), finding severities (the posture governs posting, never finding, and the fix-audit brief says so), the standing-blocker re-check and the ledger rulings Step 6 owes, the two-consecutive-dry stop rule, and the verdict semantics. The disclosures are the price of every reduction: the plan records posture, cause and census; the chunk brief names its file's bound; the round output carries a `posture narrowing:` note beside the retirement note; and `compose-review` puts one round-shape sentence in the posted body, so the reduced coverage is a fact on the record rather than a diff of agent counts. | ||
|
|
||
| One known widening of an existing gap, named rather than discovered: the backward base-move smuggle (see the roster's heavy-interaction-file comment) already relies on hunks arriving inside a republished full-range slice; a seam-bounded round republishes less, so smuggled hunks outside the seam go unread on exactly these rounds. The exposure is bounded by the posture's own preconditions — a long-lived PR whose base is retargeted mid-loop, in the same window a round is running critical-only — and the heavy-file invariant agents, which read whole files from the worktree, keep their coverage regardless. |
There was a problem hiding this comment.
[Critical] R7-1: Still stands — re-verified at this commit (DESIGN.md is unchanged since round 7; the branch head moved only via a merge of main). The bounding claim this paragraph adds for the acknowledged backward base-move smuggle — "the heavy-file invariant agents ... keep their coverage regardless" — is falsified by the seam-bounding this same PR adds. Heaviness is classified from the PUBLISHED slice: publish(narrowed) makes the seam-bounded bytes the diff, and buildDiffPlan computes changedLines from seam hunks only. A long-lived PR's hub interaction file whose full incremental slice classifies heavy (≥800 changed lines, or ratio ≥0.4 with ≥300 pre-lines) but whose seam hunks are a small subset computes heavy: false — the roster requires no invariant-a/b/c, check-coverage recomputes from the same plan and flags nothing, and the round-shape disclosure carries only the seam census. Retarget the base backward mid-loop — the smuggle precondition this same paragraph bounds — and smuggled hunks arrive outside the seam, go unread, and the agents this sentence claims "keep their coverage regardless" never ran. Even without the retarget, the fix-audit round silently drops the whole-file invariant pass the same round at full shape would have run, against the PR's own rule that every reduction is a fact on the record.
Witness: not run — the chain (widenScope → assembleSections → publish → buildDiffPlan → classifyHeavy → requiredAgents) was traced in the code at HEAD this round and re-derived independently by the round-3 territory audit; the classification flip needs a heavy interaction file with a small seam set, which no fixture in this PR constructs.
Exempt heavy interaction files from seam-bounding: classify heaviness from the full-range slice (fetch-pr holds the full selection before hunk filtering) and keep all hunks for files it classifies heavy — the same fail-open shape widenScope already applies to its doubt states. If the exemption is rejected, disclose the lost invariant agents in the plan's posture record and the body's round-shape sentence, and remove the "keep their coverage regardless" claim. Fix witness: a pipeline-level test (fetch-pr/widenScope → buildDiffPlan → requiredAgents) where an interaction file with full-slice changedLines ≥ 800 but a one-small-hunk seam set must still require invariant-a--<file>; removing the exemption makes it red.
中文说明
仍未解决——已在当前提交重新验证(DESIGN.md 自第 7 轮以来未变;分支头仅通过 main 的合并移动)。本段为已承认的"base 反向移动走私"补充的兜底声明——"heavy 文件 invariant agents……无论如何保持覆盖"——被本 PR 自己新增的接缝限宽证伪。heavy 判定基于发布后的切片:publish(narrowed) 使接缝限宽后的字节成为 diff,buildDiffPlan 只从接缝 hunks 计算 changedLines。长寿 PR 的枢纽 interaction 文件,其完整增量切片本可判为 heavy(≥800 变更行,或 preLines ≥300 且比例 ≥0.4),但接缝 hunks 只是一小部分时,计算结果为 heavy: false——roster 不再要求 invariant-a/b/c,check-coverage 从同一 plan 重算也发现不了问题,轮次形态披露只带接缝计数。若在循环中途把 base 反向重定——正是本段兜底所针对的走私前提——走私的 hunks 落在接缝之外、无人阅读,而本句声称"无论如何保持覆盖"的 agents 根本没跑。即使不重定,fix-audit 轮也悄无声息地丢掉了全量形态下本会执行的整文件 invariant 检查,违反本 PR 自己"每项收窄都要留档"的规则。证据:未执行——链条(widenScope → assembleSections → publish → buildDiffPlan → classifyHeavy → requiredAgents)本轮已在 HEAD 代码中追踪,并由第 3 轮领地审计独立重推;分类翻转需要一个接缝集很小的 heavy interaction 文件,本 PR 的夹具未构造。建议:把 heavy interaction 文件排除在接缝限宽之外——用全量切片判重(fetch-pr 在 hunk 过滤前持有完整 selection),对判为 heavy 的文件保留全部 hunks,即 widenScope 对其疑态已有的放开形态。若拒绝该豁免,则在 plan 的姿态记录与正文轮次形态句中披露丢失的 invariant agents,并删除"无论如何保持覆盖"的声明。修复验收:流水线级测试(fetch-pr/widenScope → buildDiffPlan → requiredAgents):全切片 changedLines ≥ 800 而接缝集仅为一个小 hunk 的 interaction 文件必须仍要求 invariant-a--<file>;移除豁免后测试应变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
…round-shape # Conflicts: # packages/cli/src/commands/review/compose-review.ts
…#10136) - Licence chain: the unknown-floor arm now consults the plan's fix-audit record like its two sibling doubt arms, so an absent severityFloor beside a posture'd plan licenses the model-side deferral instead of capping it. - Retirement narrowing: a dry receipt sharing its findings digest with a yielded round no longer narrows the chunk out — the convergence pair's dry member predates its pair member's findings entering the list. - Seam oracle: scans run on a comment-stripped view (a keyword inside a comment used to displace the clause bound), and a clause the scan cannot parse to consistent bindings fails closed to the whole file. - Seam bounding: a full-range slice that classifies heavy is exempt — bounding it would flip the plan's heavy flag and drop the invariant agents owed to the file.
|
🤖 Addressed the latest review feedback (round 4/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 4/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #10136 (
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
10 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-4 one-dry narrowing discriminating test — already reported (comment 3864213983)
- R1-17 launch preamble tail grammar — already reported (comment 3864214106)
- R1-12 capture-time recorded-floor identity axes (host chain and skillArgs seam) — already reported (comment 3864214058)
- R1-14 DESIGN.md two-consecutive-dry enumeration twin — already reported (comment 3864214087)
- R1-13 wave relaunch exclusivity claim — already reported (comment 3864214070)
- R1-15 SKILL.md tier parenthetical vs huge gate — already reported (comment 3864214093)
- engaged-floor sentence fabricates a deferral when nothing was deferred — already recorded in the round-2 and round-3 deferral lists (reviews 5034611317, 5036120762)
- posted seam census understates republication from whole/doubt states — already recorded in the round-8 deferral list (review 5050162465)
- R1-5 capture-time recorded-floor wiring tests — already reported (comment 3864213990)
- R1-6 APPROVE-branch disclosure test — already reported (comment 3864213996)
Not reviewed: build-and-test — 'Integration Tests (CLI, No Sandbox)' was skipped in CI and its suite did not run locally.
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 10, not a blocker) — recorded, not requested in this round:
docs/users/features/code-review.md:370 — [review] dangling 'see the convergence posture' cross-referencepackages/cli/src/commands/review/compose-review.ts:1922 — [review] fix-audit plan record trusted without a PR-identity cross-checkpackages/core/src/skills/bundled/review/DESIGN.md:610 (+6 locations) — [review] 'posting bar cannot disagree with the shape the round ran' overclaim at six sitespackages/cli/src/commands/review/fetch-pr.ts:1435 — [probe] capture summary misreports whole-republished interaction files as nonepackages/cli/src/commands/review/lib/retirement.ts:951 — [probe] staleAgainstYield release direction unpinned by any test
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 10 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — 'Integration Tests (CLI, No Sandbox)' was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 10 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.2)
| if (name && IDENT_RE.test(name)) bindings.add(name); | ||
| } | ||
| } | ||
| } else if (/(?:const|let|var)[^=\n]*=\s*\S/.test(before)) { |
There was a problem hiding this comment.
[Critical] R9-1: Still stands — re-verified by probe at this commit, with eight further probe-executed entrances of the same surface found this round. seamLines hand-rolls clause and declaration parsing over raw source text, and its fail-closed net enumerates declaration shapes one at a time, so every unenumerated shape escapes with no doubt and widenScope silently sheds the caller's usage hunks from fix-audit republication while the seam census describes the shed as deliberate. The entrances probe-executed on the unmodified commit this round: (1) prettier-wrapped/split declarations — const api = newline await import('./changed.js'); + api.call(); returns [2] (usage dropped; fail-closed is [1,2,3,4]), lazy-load let api; … api = await import(…) and multiline const {\n moved,\n} = require(…) likewise; (2) keyword-less assignments — import x = require('./changed.js'); + usage returns [1], this.api = require(…) likewise (both the decl read and the doubt net key on const|let|var); (3) nested/array/rest destructuring — const { utils: { format } } = require(…) + format(x); returns [1] (flat control [1,2]), const [moved] = require(…) returns [1], const { moved, ...rest } = require(…) drops rest; (4) declaration-less dynamic imports — import('./changed.js').then((mod) => { mod.moved(); }); returns [1] (the awaited-declaration control fails closed to [1,2,3]), the promise form const p = import(…); p.then((mod) => { mod.moved(); }) returns [1,2] collecting only the promise, and cb(require(…)) with a callback parameter returns [1]; (5) the 2000-char clause cap fails open — a 300-name barrel re-export (keyword-to-from distance 2599) returns [1], and the boundary sweep flips exactly at the cap (234 names/2005 chars → [1], 233/1996 → [1,2]); (6) // inside a string literal — const u = 'https://x'; const { moved } = require('./changed.js'); + moved(); returns [] (the comment regex blanks from the URL's // to end of line, erasing the require); (7) /* inside one string and */ inside a later one blank every line between, deleting a real require with no doubt; (8) destructuring defaults — const { moved = fallback } = require(…) collects fallback and drops moved. Each contradicts the module's own contract ("Under-collection of the oracle is the one error the seam bound must not make") and reproduces the exact regression the round shape exists to catch: on a fix-audit round the interaction file republishes header-only, the census asserts nothing touches the seam, and the round retires a caller broken by the fix without ever re-asking the seam question — the narrowed waves give interaction-only chunks no structural backstop.
Witness (probes against the real seamLines/widenScope at fe8944cd, scratch tree; flips verified; 33/33 existing tests stay green under each partial fix):
wrapped-decl [2] vs fail-closed [1,2,3,4]
import-equals [1], this.api= [1] vs const control [1,2]
nested [1], array [1], rest drops `rest` vs flat control [1,2]
.then-cb [1], split [1], promise-decl [1,2], cb(require) [1]
vs awaited control [1,2,3]
300-name barrel [1]; boundary 234/2005 -> [1], 233/1996 -> [1,2]
string-// input []; cross-string /*...*/ []
widenScope(seamBound): seam {"kept":0,"total":1}, hunk header and use line ABSENT from the republished diff, no doubt
Close the class structurally rather than patching the next corner: route the clause/declaration read through an authoritative parser (the TypeScript compiler is already a workspace dependency), or make every read whose bindings cannot be proven collected fail closed into widenScope's existing doubt arm (republish the file in full). Concretely at minimum: fail closed on any dynamic import( match and on any require(/import( call whose before parses to no declaration; split clause entries at = before the rename parse; fail closed when a brace entry does not parse to an identifier; treat a keyword-bound clause over the 2000-char cap as doubt (distinct from the unbounded-clause continue); and make stripComments string-aware (single-pass quote/template state machine). The over-marking direction is the cost the module header already budgets.
Fix witness: import-graph.test.ts cases per entrance class (the wrapped declaration beside the awaited-import case, import x = require + usage, nested-destructure + usage, a .then((mod) => { mod.moved(); }) case mirroring the awaited test, the 300-name barrel, the two string-blanking shapes, and the destructuring default); removing any one guard must turn its case red.
中文说明
仍未解决——已在当前提交上以 probe 重新验证,且本轮在同一表面上发现了 8 个新的 probe 证实入口。seamLines 用正则在原始源码文本上手工解析子句与声明,其失败闭合网按形状逐个枚举声明形态,凡是未枚举的形状都无声逃逸、不置疑态,于是 widenScope 在 fix-audit 重发中悄悄剔除调用方的使用行 hunks,而接缝计数却把这次剔除描述成有意为之。本轮在未修改提交上 probe 证实的入口:(1) prettier 换行/拆分的声明——const api = 换行 await import('./changed.js'); + api.call(); 返回 [2](使用行丢失;失败闭合应为 [1,2,3,4]),惰性加载 let api; … api = await import(…)、多行 const {\n moved,\n} = require(…) 同样丢失;(2) 无关键词赋值——import x = require('./changed.js'); + 使用行返回 [1],this.api = require(…) 同样(声明读取与疑态网都以 const|let|var 为键);(3) 嵌套/数组/rest 解构——const { utils: { format } } = require(…) + format(x); 返回 [1](平铺对照为 [1,2]),const [moved] = require(…) 返回 [1],const { moved, ...rest } = require(…) 丢掉 rest;(4) 无声明动态 import——import('./changed.js').then((mod) => { mod.moved(); }); 返回 [1](await 声明对照失败闭合成 [1,2,3]),promise 形态 const p = import(…); p.then((mod) => { mod.moved(); }) 返回 [1,2] 只收集 promise,cb(require(…)) 回调参数形态返回 [1];(5) 2000 字符子句上限失败放行——300 个名字的桶式 re-export(关键词到 from 距离 2599)返回 [1],边界扫描恰好在上限处翻转(234 名/2005 字符 → [1],233/1996 → [1,2]);(6) 字符串字面量内的 //——const u = 'https://x'; const { moved } = require('./changed.js'); + moved(); 返回 [](注释正则从 URL 里的 // 一路白化到行尾,抹掉了 require);(7) 一个字符串里的 /* 与另一个字符串里的 */ 把中间所有行白化,无声删除真实 require、不置疑态;(8) 解构默认值——const { moved = fallback } = require(…) 收集 fallback 而丢掉 moved。每一条都违反模块自己的契约("收集不足是接缝限宽绝不能犯的唯一错误"),并且复现了本轮形态本要防住的那类回归:fix-audit 轮里 interaction 文件只重发头部、计数声称没有接缝相关行,于是轮次在一个被修复破坏的调用方上认证干净、重落锚点,而收窄后的波次不为 interaction-only 领地提供任何结构性兜底。
证据(对 fe8944cd 上真实 seamLines/widenScope 的 probe,scratch tree 中进行;翻转已验证;每个局部修复下现有 33/33 测试仍全绿):见英文部分代码块。
请结构性关闭该类,而不是再补下一个角:把子句/声明读取交给权威解析器(TypeScript 编译器已是工作区依赖),或让任何无法证明已收集绑定的读取失败闭合到 widenScope 已有的疑态臂(全量重发)。最小具体修复:对任何动态 import( 匹配失败闭合;对任何 before 解析不出声明的 require(/import( 调用失败闭合;重命名解析前先按 = 拆分子句条目;花括号条目解析不出标识符时失败闭合;关键词定界子句超过 2000 字符上限时置疑(与"无法定界"的 continue 分开);让 stripComments 感知字符串(单趟引号/模板状态机)。过度标记方向是本模块头部早已预算的代价。
修复验收:按入口类别在 import-graph.test.ts 各增一例(换行声明放在 awaited-import 用例旁、import x = require + 使用行、嵌套解构 + 使用行、镜像 awaited 用例的 .then((mod) => { mod.moved(); }) 用例、300 名字桶式导出、两种字符串白化形态、解构默认值);移除任一处守卫必须使对应用例变红。
— qwen3.8-max via Qwen Code /review (v0.22.2)
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
8 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- stale exit-5/CONVERGED two-dry criterion in the agent-prompt yargs help strings — already recorded in the round-4 deferral list (review 5037286144)
- role-brief seam-census clause test gap — already recorded in the round-4 deferral list (review 5037286144)
- R1-5 capture-time recorded-floor wiring tests — already reported (comment 3864213990)
- R1-14 DESIGN.md two-consecutive-dry enumeration twin — already reported (comment 3864214087)
- R1-13 narrowing-note 're-launches only' exclusivity overclaim — already reported (comment 3864214070)
- R1-12 capture-time host-axis asymmetry (Critical escalation rejected by verification; base Suggestion stands) — already reported (comment 3864214058)
- R1-4 one-dry narrowing discriminating-test gap — already reported (comment 3864213983)
- R1-17 launch-preamble tail grammar — already reported (comment 3864214106)
Not reviewed: build-and-test — 'Integration Tests (CLI, No Sandbox)' was skipped in CI and its suite did not run locally.
Not explored to full depth (tool budget reached): chunk 8: running posture.test.ts and retirement.test.ts (worktree has no node_modules/build; install+build exceeds tool budget); chunk 1: executing the four new tests in packages/cli/src/commands/review/agent-prompt.test.ts (the review worktree has no node_modules and no package builds; a full mon….
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more.
Deferred under the convergence posture (round 11, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/agent-prompt.ts:2845 — [review] postureNarrowing engages on a partially-corrupt delta list — the omitted delta file's chunk is misclassified as non-delta and leaves the wave after one dry receiptpackages/cli/src/commands/review/compose-review.ts:3313 — [review] stale fold-doctrine comment still states the unknown floor caps as unlicensed beside a deferral list, although this PR's plan-record exception licences exactly that statepackages/cli/src/commands/review/agent-prompt.ts:819 — [review] seam-census clause renders on the mere presence of a parsed seam field with no isFixAuditRound gate, unlike the compose-side reader of the same censuspackages/core/src/skills/bundled/review/SKILL.md:345 — [review] topology bullet keys fix-audit routing on posture alone; the isFixAuditRound gate it cites additionally requires effective and a valid scopepackages/core/src/skills/bundled/review/SKILL.md:902 — [review] enforcement-backstop arm list overclaims: 'auto' beside the plan's fix-audit record is enforced only when the floor value is literally presentpackages/cli/src/commands/review/lib/budget.ts:321 — [review] isTerritoryFanOut flip makes emit-workflow's fanOutBlocker refuse bounded fix-audit rounds on an unbounded-growth premise that is false for thempackages/cli/src/commands/review/lib/incremental-scope.ts:162 — [review] heavy exemption classifies the full-range slice but buildPlanReport re-derives heaviness from the bounded slice, flipping bounded files to heavy and demanding invarian…
Residual risk: this loop is persistently critical — Criticals stood in the previous round's work-list and stand again this round (4 Critical(s)), the rate of first-time findings is not falling (this round 3, previous 0), and the standing Critical backlog is not shrinking. The severity floor will not converge it. Recommendation: land-with-residual-risk — the exit is a maintainer risk-acceptance decision (merge, carrying the residual risk), not another review round. Residual-risk inventory for that decision (maintainer to complete):
| standing Critical | attack surface | attacker-dependency | blast radius |
|---|---|---|---|
| (each standing Critical) | … | … | … |
Advisory only — it does not block this review.
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 8 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — 'Integration Tests (CLI, No Sandbox)' was skipped in CI and its suite did not run locally。
未探索到全部深度(达到工具调用预算):chunk 8:running posture.test.ts and retirement.test.ts (worktree has no node_modules/build; install+build exceeds tool budget);chunk 1:executing the four new tests in packages/cli/src/commands/review/agent-prompt.test.ts (the review worktree has no node_modules and no package builds; a full mon…。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory; and 2 more。
收敛姿态下延后(第 11 轮,非阻断)——已记录,本轮不要求修改:共 7 条(原文未翻译,列表见上方英文部分)。
残余风险:本循环处于 persistently-critical 形态——上一轮工作清单中的 Critical 本轮依然存在(本轮 4 条 Critical),首次发现的速率没有下降(本轮 3,上一轮 0),且未决 Critical 积压没有减少。severity floor 无法使其收敛。建议:land-with-residual-risk——出口是 maintainer 的风险接受决定(合入并承担残余风险),而非再开一轮评审。供该决定使用的残余风险清单(maintainer 填写):按每条未决 Critical 列出「攻击面 · 攻击者依赖性 · 影响范围」三栏。仅为建议——不阻断本次评审。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| } else if (/(?:const|let|var)[^=\n]*=\s*\S/.test(before)) { | ||
| // A declaration the line-shape read cannot collect — an expression |
There was a problem hiding this comment.
[Critical] R9-1: [certifies-falsely] [new-surface] Still stands — re-verified by probe at this commit, with further probe-executed entrance points of the same class. seamLines hand-rolls clause parsing against raw source text with regexes that have no comment/string recognition, and widenScope's seamBound arm trusts that oracle with no doubt state for under-collection — so an interaction file's usage hunks are silently shed from fix-audit republication while the seam census, the chunk brief, and the posted round-shape body describe the shed as seam-justified. This round's probes show assignment to a pre-existing binding (api = await import('./changed.js')), multiline destructuring, import x = require(...), declaration-less .then(), and ////* inside string literals all escaping the fail-closed net with no doubt — the net remains enumerative, and every patch adds another corner on an unbounded surface (arbitrary JS/TS source). The result is a fix-audit round that retires an interaction territory after one dry receipt while a fix commit that broke that caller certifies clean — the exact regression this shape exists to catch, falsifying the module's own invariant that under-collection is the one error the seam bound must not make. Close the class structurally rather than patching the next corner: route the clause/declaration read through the TypeScript compiler (already a workspace dependency), or fail closed every read whose bindings cannot be proven collected — at minimum, doubt on any = in before the decl read did not consume, doubt on any dynamic import(/require( call whose before parses to no declaration, split clause entries at = before the rename parse, doubt when a brace entry does not parse to an identifier, treat a keyword-bound clause over the 2000-char cap as doubt, and make stripComments string-aware.
Witness:
Probe at HEAD (08bfeca), unmodified PR code — seamLines shapes:
api = await import('./changed.js'); + api.call(); -> [2] usage line dropped, no doubt
const { moved, } = require('./changed.js'); (multiline) -> [3] usage line dropped, no doubt
import moved = require('./changed.js'); moved(); -> [1] usage dropped
import('./changed.js').then((m) => { m.moved(); }); -> [1] usage dropped
const url = 'http://x'; moved(); -> [1] usage blanked by stripComments
widenScope(seamBound=true): usage-only hunk ABSENT from the republished diff;
seam {"kept":0,"total":1} asserts the shed is seam-justified; no doubt state
Flip: fail-closed doubt republishes every shape in full.
The fix must not violate the seamLines docblock invariant (import-graph.ts:356-357 — "Under-collection of the oracle is the one error the seam bound must not make"), and the doubt shape must remain "mark every line" — incremental-scope.ts:185 reads only the line set. Add one import-graph.test.ts case per entrance class beside the existing describe('seamLines') suite (wrapped declaration beside the awaited-import case, import x = require + usage, multiline/nested destructuring + usage, a .then((mod) => { mod.moved(); }) case, the 300-name barrel, the two string-blanking shapes, and a destructuring default) — removing any one guard must turn its case red.
中文说明
[Critical] R9-1:仍然成立——本轮已通过探针在当前提交上再次验证,并新增了同一类的多个探针实测入口。seamLines 用正则手工解析原始源码文本中的子句,没有任何注释/字符串识别能力,而 widenScope 的 seamBound 分支无条件信任该预言机,对「收集不全」没有任何怀疑态——于是交互文件的用法 hunk 会被悄悄从 fix-audit 重发布中丢弃,而 seam 计数、分块简报与发布的轮次形态说明却把这次丢弃描述为「接缝合理裁剪」。本轮探针显示:对已有绑定的赋值(api = await import('./changed.js'))、多行解构、import x = require(...)、无声明的 .then()、字符串字面量内的 ////* 全部能逃过 fail-closed 网且不触发任何怀疑——这张网仍然是逐形状枚举的,而每次补丁只是在无界表面(任意 JS/TS 源码)上再添一个角。其后果是:某个 fix-audit 轮次在仅一次 dry 回执后就让交互领地退役,而一个破坏了该调用方的修复提交却被认证为干净——这正是该形态本应捕获的回归,也违反了模块自身「收集不全是接缝边界绝不能犯的错」的不变量。请从结构上关闭这一类问题,而不是继续修补下一个角:把子句/声明解析交给 TypeScript 编译器(已是工作区依赖),或让任何无法证明已收集到绑定的读取一律失败关闭——至少包括:before 中出现未被 decl 读取消费的 = 时触发怀疑;任何 before 解析不出声明的动态 import(/require( 调用触发怀疑;重命名解析前先按 = 拆分子句条目;花括号条目解析不出标识符时触发怀疑;超过 2000 字符上限的关键字界定子句按怀疑处理;并让 stripComments 具备字符串感知能力。
证据:见上方英文部分末尾 Witness 代码块(在当前 HEAD 上用未改动的 PR 代码实测:各形状的用法行均被丢弃且不触发怀疑;widenScope(seamBound=true) 下仅含用法的 hunk 未出现在重发布 diff 中;失败关闭后可完整重发布)。
修复不得违反 seamLines 文档注释中的不变量(import-graph.ts:356-357),且怀疑形态必须保持「标记每一行」(incremental-scope.ts:185 只读取行号集合)。请在现有 describe('seamLines') 套件旁为每个入口类各加一个 import-graph.test.ts 用例——移除任一防护都应使对应用例变红。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| const lines = seamLines(path, source, touched, packages); | ||
| const kept = new Set<number>(); | ||
| section.hunks.forEach((h, i) => { | ||
| if (lines.some((ln) => ln >= h.newStart && ln <= h.newEnd)) { |
There was a problem hiding this comment.
[Critical] R11-1: [certifies-falsely] [new-surface] The doubt-state fail-closed guarantee ("Every doubt state republishes in full") is broken for pure-deletion hunks at the top of a file: parseDiff clamps a @@ -1,N +0,0 @@ hunk to new-side range [0,0] (diff-plan.ts:482-491), while seamLines' doubt return marks lines 1..total — no marked line is ever 0 — so this kept predicate matches nothing, hunkKeep sheds the deletion hunk, and the file publishes under-republished with a seam census claiming a reduction, under the very doubt state documented to republish in full. This is distinct from R9-1: even a perfectly doubted oracle cannot keep this hunk shape. A fix-audit round whose interaction file had its first lines deleted by an earlier PR round (full-range section carries @@ -1,2 +0,0 @@) and whose head source trips doubt ships under-published — the round whose scan just announced it could not trust its own read publishes less than the full republication the doubt state promises.
Witness:
Probe through the real widenScope/assembleSections (scratch tree at HEAD):
BASE (unmodified PR code):
seam record: {"kept":1,"total":2}
hunkKeep: [1]
deletion hunk (+0,0) in published diff: false
doubt-state promise kept: false
FIX (detect lines.length >= fileLines before hunk matching):
seam record: null, hunkKeep: undefined
deletion hunk (+0,0) in published diff: true
The vitest-form witness is red on current code and green with the fix;
the 40 existing incremental-scope + import-graph tests stay green.
Detect the doubt shape in widenScope before hunk matching — lines.length >= fileLines is exactly the marks-every-line shape of the doubt return, and a legitimate scan can never exceed fileLines — and continue without recording a seam, leaving the file unbounded exactly like the unreadable-source doubt state. The doubt shape marks lines starting at 1 (import-graph.ts:449), and a skipped file must carry NO seam record, matching the InteractionFile.seam doc "Present exactly when the fix-audit posture seam-bounded this file" (incremental-scope.ts:53-60). Add a case under describe('widenScope seam bound (#10104)') in incremental-scope.test.ts: an interaction-file section carrying one @@ -1,2 +0,0 @@ hunk plus one ordinary hunk, with a worktree source containing the doubt trigger const api = await import('./changed.js');; assert widened.hunkKeep is undefined and the assembled diff still contains the deletion hunk — removing the doubt-shape guard sheds hunk 0 again and turns the test red.
中文说明
[Critical] R11-1:怀疑态的失败关闭保证(「每个怀疑态都完整重发布」)对文件顶部的纯删除 hunk 失效:parseDiff 把 @@ -1,N +0,0 @@ hunk 钳制到新侧区间 [0,0](diff-plan.ts:482-491),而 seamLines 的怀疑返回标记的是 1..total 行——被标记的行永远不可能是 0——于是此处的保留谓词匹配不到任何行,hunkKeep 丢弃该删除 hunk,文件以「欠发布」的状态发布、seam 计数却声称做了裁剪,而这恰恰发生在文档承诺完整重发布的怀疑态之下。这与 R9-1 不同:即使预言机完美地触发了怀疑,也无法保住这种 hunk 形状。失败场景:某个交互文件在本 PR 的较早轮次中删除了开头若干行(全量区间带 @@ -1,2 +0,0 @@),且当前源码触发怀疑的 fix-audit 轮次,会以欠发布的形式发布——扫描刚刚宣布「无法信任自己的读取」,发布的却比承诺的完整重发布更少。
证据:见上方英文部分 Witness 代码块(真实 widenScope/assembleSections 探针:当前代码下删除 hunk 未进入发布 diff、承诺被打破;加入「lines.length >= fileLines 时跳过定界」后恢复完整重发布,既有 40 个测试仍绿)。
请在 widenScope 的 hunk 匹配之前检测怀疑形态(lines.length >= fileLines 正是「标记所有行」的怀疑返回形态,合法扫描不会超过 fileLines),并像「源码不可读」怀疑态一样不记录 seam、直接 continue。修复约束:怀疑形态从 1 开始标行(import-graph.ts:449);被跳过的文件不得携带任何 seam 记录(见 InteractionFile.seam 文档,incremental-scope.ts:53-60)。请在 incremental-scope.test.ts 的 describe('widenScope seam bound (#10104)') 中新增用例并使其在当前代码上变红、修复后变绿。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| const staleAgainstYield = audits.some( | ||
| (a) => | ||
| a.outcome === 'yielded' && | ||
| a.digests.some((d) => latest.digests.includes(d)), | ||
| ); |
There was a problem hiding this comment.
[Critical] R11-2: [certifies-falsely] [new-surface] The convergence-pair staleness guard disqualifies narrowing only on a CERTIFIED yielded predecessor, but findings merge into the cumulative list unconditionally — so an UNCERTIFIED yield (a round classifying unknown) that shares the latest dry round's digest still narrows the chunk out: latest.outcome === 'dry' and no audit has outcome yielded, so a non-delta chunk enters narrowed at round 3 and leaves the wave permanently (narrowed chunks get no cold checks; converged counts them as out), although the territory demonstrably produced findings the dry member never saw. A designed-flow path needs no malformed launch: the yield scan in classifyReturn (retirement.ts:556-572) refuses a filed finding whose **File:** line is a substring of a listed entry — a new finding at src/a.ts:4 beside listed src/a.ts:42, or a re-report of a listed location — classifying the receipt unknown while the orchestrator still merges the finding. The loop can then converge with live findings in territory that never saw them — certifying convergence over live findings, the one failure direction this guard's own comment says is forbidden.
Witness:
Probe over the real scheduler (scratch tree at HEAD) — non-delta chunk 14,
round 1 files a finding at a listed location (classified unknown via echo-skip),
round 2 certified dry, same digest feed01:
before fix: {"due":[],"narrowed":[{"chunkId":14,"dryRound":2}],"converged":true}
after fix: {"due":[14],"narrowed":[],"converged":false,
"diagnostics":["chunk 14 — round 1: receipt not matched"]}
Control row (certified yield, same digest — the shipped #10136 guard):
{"due":[14],"narrowed":[]} both before and after.
With the fix applied, all 150 retirement tests pass.
| const staleAgainstYield = audits.some( | |
| (a) => | |
| a.outcome === 'yielded' && | |
| a.digests.some((d) => latest.digests.includes(d)), | |
| ); | |
| const staleAgainstYield = audits.some( | |
| (a) => | |
| a.outcome !== 'dry' && | |
| a.digests.some((d) => latest.digests.includes(d)), | |
| ); |
The fix must preserve the invariant at retirement.ts:940-944 ("One dry receipt is NOT decisive when it shares its findings digest with a yielded round — the dry member was built before the yield's findings entered it"), and the kept-hot chunk must land in due, not merely be excluded from narrowed — retirement.ts:1030 computes converged from due.length === 0. Add a case in retirement.test.ts beside 'a dry receipt sharing its digest with a yield does not narrow the chunk out (#10136)': same digest on both rounds of a non-delta chunk, round 1 uncertified (one launch transcript matching both records, or none), round 2 a certified substantive dry; assert the chunk is in r3.due and NOT in r3.narrowed — reverting the predicate to a.outcome === 'yielded' makes it red.
中文说明
[Critical] R11-2:收敛对陈旧性防护只在「已认证的 yielded 前序轮」时才取消收窄资格,但发现合并进累积列表是无条件的——于是与最新 dry 轮共享 digest 的「未认证 yield」(分类为 unknown 的轮次)仍会把该分块收窄出局:latest.outcome === 'dry' 且不存在 yielded 回执,非 delta 分块在第 3 轮进入 narrowed 并永久离开波次(收窄分块没有冷检查;converged 把它们算作已离场),尽管该领地确实产出过发现、而那个 dry 成员从未看到它们。存在无需畸形启动的设计内路径:classifyReturn 的 yield 扫描(retirement.ts:556-572)会把 **File:** 行是已列条目子串的已提交发现判为回声而拒绝——例如列表已有 src/a.ts:42 时在 src/a.ts:4 新发现的缺陷——回执被分类为 unknown,但编排器仍会合并该发现。于是循环可以在「活着的发现身处从未被审计的领地」的情况下收敛——在活发现之上认证收敛,正是该防护自身注释声明禁止的唯一失败方向。
证据:见上方英文部分 Witness 代码块(真实调度器探针:修复前该分块被收窄出局且 converged: true;把判定放宽为「任何非 dry 且共享 digest 的轮次」后该分块留在 due 中;对照行证明已发布的 #10136 防护不受影响,150 个退休测试全绿)。
修复必须保留 retirement.ts:940-944 的不变量,且保持热的分块必须落入 due(retirement.ts:1030 用 due.length === 0 计算 converged),而不只是被排除在 narrowed 之外。请在 retirement.test.ts 的 #10136 用例旁新增用例:两轮同 digest、第 1 轮未认证(unknown)、第 2 轮为已认证的实质性 dry;断言该分块在 r3.due 中且不在 r3.narrowed 中——把谓词还原为 a.outcome === 'yielded' 应使该用例变红。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| : 'The posting floor itself resolved OPEN at compose time this round ' + | ||
| fixAuditOpenCauseEn + | ||
| ', so no finding was withheld by a floor — only the narrowed shape ' + |
There was a problem hiding this comment.
[Critical] R11-3: [certifies-falsely] [new-surface] In the fix-audit state this PR newly licences — the compose state omits severityFloor beside the plan record, reachable because the field is model-written and your own test at compose-review.test.ts:2408 pins absence — the reporting read folds absence to auto and the plan arm resolves critical (so the model routes Suggestions into deferredSuggestions and the licence admits them), while the strict enforcement read fails open. The posted body then renders BOTH the deferral list ("Deferred under the convergence posture … recorded, not requested in this round") AND this open-floor sentence claiming "no finding was withheld by a floor — only the narrowed shape above applied". In this module's own terminology deferral IS the floor's withholding — the convergence posture IS the floor resolution — so the open sentence's unqualified universal is falsified by the very same body whenever the deferral list is non-empty: the exact shape the sibling doctrine at compose-review.test.ts:2512-2514 forbids ("the engaged sentence in the same body may not assert the unqualified universal that the very same body falsifies"). The body also says the floor "resolved OPEN" while the marker stamps the reporting resolution (auto-resolved) into the ledger the next round reads — two descriptions of one resolution diverging in a single compose. The zh twin carries the same universal.
Witness:
Probe through the real composeReview (scratch tree at HEAD; the exact state of
test #10136 — severityFloor omitted, POSTURE plan, one model-side deferral):
body carries BOTH:
"The posting floor itself resolved OPEN at compose time this round (the floor
record was absent, and the enforcement reading fails open), so no finding was
withheld by a floor — only the narrowed shape above applied."
"Deferred under the convergence posture (round 1, not a blocker) — recorded,
not requested in this round: - src/a.ts:3 — [review] untested guard"
floorEnforced: []
Fix arm (open arm beside a non-empty deferral list states the backstop moved
nothing and the deferrals below were routed by the round's posture):
open-sentence present: false, deferral-list present: true, 12/12 tests pass.
When the open arm renders beside a non-empty deferredSuggestions list, drop the no-withholding universal: state that the mechanical backstop moved nothing because the floor record was absent/unreadable, and that the deferrals listed below were routed by the round's posture, not moved by a resolved floor (en and zh strings together) — or condition the "no finding was withheld" clause on an empty deferral list. The fix must keep the R1-2 keying — the strict enforcement read, never criticalFloorKind (compose-review.ts:5479-5485) — and the three-cause open-floor split (compose-review.ts:5487-5494) intact. Extend compose-review.test.ts 'an ABSENT floor beside the plan record licences a model-side deferral (#10136)' (~line 2408) to assert that with deferredCount > 0 the body does NOT contain "no finding was withheld by a floor"; the sibling inline-Suggestion variant (~2437) asserting "resolved OPEN at compose time" must still pass.
中文说明
[Critical] R11-3:在本 PR 新许可的 fix-audit 状态下——模型书写的 severityFloor 字段在计划记录旁缺省(可达;你们自己的测试 compose-review.test.ts:2408 钉住了缺省态)——报告侧读取把缺省折叠为 auto、计划分支解析出 critical(模型因此把 Suggestion 路由进 deferredSuggestions,许可也放行),而严格执行侧读取失败开放。于是发布的正文同时渲染了延期清单("在收敛姿态下延期……只记录、本轮不请求")与这句「没有任何发现被下限扣留——只有上述收窄形态生效」的开放下限句。按本模块自身的术语,延期就是下限的扣留——收敛姿态就是下限解析本身——所以只要延期清单非空,这句开放句的无条件全称判断就被同一份正文证伪:正是 compose-review.test.ts:2512-2514 的兄弟准则所禁止的形态(「同一正文中的句子不得断言被该正文自己证伪的无条件全称」)。正文还说下限「解析为开放」,而标记却把报告侧解析(auto-resolved)写进下一轮要读取的台账——同一次 compose 对同一个解析给出了两种相互矛盾的描述。中文孪生句带有同样的全称判断。
证据:见上方英文部分 Witness 代码块(真实 composeReview 探针:在 #10136 测试的确切状态下,正文同时出现开放下限句与延期清单,floorEnforced: [];修复后开放句消失、延期清单保留、12/12 测试通过)。
修复方案:当开放分支在 deferredSuggestions 非空时渲染,去掉「没有发现被扣留」的全称句——改为说明机械兜底因下限记录缺省/不可读而未移动任何内容、下列延期是本轮姿态路由的结果而非已解析下限的移动(中英文字符串一起改),或把该子句条件化为延期清单为空。修复必须保留 R1-2 的键控方式——严格执行侧读取,绝不改用 criticalFloorKind(compose-review.ts:5479-5485)——并保持三因开放分支拆分(compose-review.ts:5487-5494)不变。请扩展 compose-review.test.ts 的 '模型侧延期在缺省下限旁获得许可 (#10136)'(约 2408 行):断言 deferredCount > 0 时正文不包含 "no finding was withheld by a floor";兄弟变体(约 2437 行)必须仍然通过。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下: Round summary — PR #10136 (address-review, round 12)This round addressed all four distinct Critical findings posted by the automated reviewer (five inline comments — R9-1 is anchored twice, at the two reviewed commits). Every claim was reproduced first: each finding got a failing witness test on the pre-round code before any fix was written, and every new guard was mutation-probed before commit. Findings and dispositionsR9-1 —
|
| # | Guard | Mutation | Witness test failed on mutation | Green after restore |
|---|---|---|---|---|
| 1 | over-cap clause doubt | condition negated | ✓ | ✓ |
| 2 | clause entry identifier check | guard disabled | ✓ | ✓ |
| 3 | dynamic import( doubt |
guard disabled | ✓ | ✓ |
| 4 | require no-declaration doubt | doubt replaced by escape | ✓ | ✓ |
| 5 | = split before rename parse |
split removed | ✓ | ✓ |
| 6 | require entry identifier check | condition negated | ✓ | ✓ |
| 7 | string-aware comment strip | string state disabled | ✓ | ✓ |
| 8 | doubt-shape detection in widenScope | guard removed | ✓ | ✓ |
| 9 | staleAgainstYield !== 'dry' |
reverted to === 'yielded' |
✓ | ✓ |
| 10 | open-tail deferral condition | condition negated | ✓ | ✓ |
Conflict
--conflict false — no merge performed.
Verification
npx vitest run src/commands/review/lib/import-graph.test.ts— pre-fix witness RED (7 failed | 33 passed); post-fix 40 passednpx vitest run src/commands/review/lib/incremental-scope.test.ts src/commands/review/lib/retirement.test.ts— pre-fix witnesses RED (2 failed | 157 passed); post-fix greennpx vitest run src/commands/review/compose-review.test.ts -t "ABSENT floor…"— pre-fix witness RED (1 failed | 1 passed); post-fix green- 10 mutation probes — each mutation turned its witness red; each restore went green (table above)
npx vitest run src/commands/review(all 117 review test files, packages/cli) — 5645 tests, 0 failures, 0 errors (17 skipped)npm run build— passednpm run typecheck— passednpm run lint(repo-wide ESLint) — passednpx prettier --checkon the eight touched files — passed
中文说明
轮次总结 — PR #10136(address-review,第 12 轮)
本轮处理了自动评审发布的全部 4 条不同的 Critical 发现(5 条行内评论——R9-1 在两个被审提交上各锚定了一次)。每条声明都先复现后修复:在写任何修复之前,先为每条发现在修复前代码上写了失败的见证测试;每个新防护都在提交前做了变异探针验证。
发现与处置
R9-1 — seamLines 枚举式失败闭合网逃逸(rc:3884361797、rc:3885391510)— 已修复
在修复前提交上复现:该发现列出的 8 类入口全部在无怀疑态的情况下丢弃了用法行(换行声明 [2]、import x = require [1]、嵌套/数组/rest 解构 [1]、无声明 .then() [1]、promise 形态 [1,2]、300 名字桶式导出 [1]、字符串白化 []、解构默认值收集 fallback 而非 moved)。
在 packages/cli/src/commands/review/lib/import-graph.ts 中按该发现给出的失败闭合最小集,从结构上关闭了这一类(任何无法证明已收集到绑定的读取,现在都进入 widenScope 已有的怀疑臂置疑):
- 任何解析到变更文件的动态
import(调用一律失败闭合(await/换行声明、.then回调、promise 形态)。 require(调用所在行若解析不出可收集的声明则失败闭合(无关键词赋值import x = require、this.api = require、换行声明、裸副作用调用)。- require 解构的花括号条目在重命名解析之前先按
=拆分(默认值绑定的是被导入名,而非兜底表达式);解析不出标识符的条目(rest 元素、嵌套形态)失败闭合。 - 关键字定界且超过 2000 字符上限的子句失败闭合(300 名字桶式 re-export),与「无法定界」的
continue分开。 clauseBindings在花括号条目解析不出标识符时返回null(置疑),不再静默跳过。stripComments改为单趟字符串感知状态机(引号与模板内容逐字节保留,注释字节置空格,未闭合引号在行尾结束),关闭了'https://x'中的//与跨字符串/* … */的白化。
见证:import-graph.test.ts 的 describe('seamLines') 中按入口类别新增 8 个用例(换行声明放在 awaited-import 用例旁)。修复前:7 failed | 33 passed;修复后:40/40 全绿。
R11-1 — 怀疑态丢弃被钳制的纯删除 hunk(rc:3885391516)— 已修复
复现:parseDiff 把 @@ -1,N +0,0 @@ 钳制到新侧 [0,0],而怀疑返回标记 1..total 行,于是怀疑态下的 hunk 匹配恰好丢掉怀疑态承诺要保留的 hunk(见证测试修复前为红)。
在 widenScope(incremental-scope.ts)中修复:在 hunk 匹配之前检测怀疑形态——lines.length >= fileLines 正是「标记每一行」的形态,合法扫描绝不会超过 fileLines——此时文件像「源码不可读」怀疑态一样不带任何 seam 记录、不定界。见证:describe('widenScope seam bound (#10104)') 新增用例,section 携带 @@ -1,2 +0,0 @@ 与触发怀疑的源码;断言 hunkKeep 为 undefined、无 seam 记录、组装后的 diff 仍含删除 hunk。
R11-2 — 未认证 yield 仍会把分块收窄出局(rc:3885391520)— 已修复
已在代码中核实该机制:classifyReturn 的 yield 扫描会拒绝 **File:** 行是已列条目子串的已提交发现(把回执分类为 unknown),而发现合并进累积列表是无条件的——于是与「未认证轮」共享 digest 的 dry 回执可能在它从未见过的发现之上被定价出局。
在 retirement.ts 中修复:staleAgainstYield 现在对记录中任何「未被认证为 dry」的轮次(a.outcome !== 'dry'——yielded 或 unknown)只要与最新 dry 回执共享 digest 就取消收窄资格。保持热的分块经由普通规则落入 due(不只是被排除在 narrowed 之外),因此 converged 不会把它算作出场。见证:#10136 用例的孪生用例——第 1 轮未认证(无 transcript)、第 2 轮为已认证的实质性 dry、同 digest;断言该分块在 r3.due 中且不在 r3.narrowed 中。把谓词还原为 a.outcome === 'yielded' 会使其变红(已做变异探针)。
R11-3 — 开放下限句被同一份正文的延期清单证伪(rc:3885391537)— 已修复
通过真实 composeReview 复现:在 #10136 的确切状态(severityFloor 缺省、POSTURE 计划、1 条模型侧延期)下,正文同时出现延期清单与「没有任何发现被下限扣留」的开放下限句(见证测试修复前为红)。
在 compose-review.ts 中修复:当开放分支在延期清单非空时渲染,去掉「无扣留」全称句,改为说明机械兜底未移动任何内容、下方列出的延后由收敛姿态路由而非已解析下限的移动(中英文字符串一起改)。清单为空时保留原全称句;R1-2 键控(严格执行侧读取)与三因开放分支拆分保持不变。见证:#10136 用例扩展为断言 deferredCount > 0 时正文不包含 "no finding was withheld by a floor" / "没有任何发现被下限扣留";断言 "resolved OPEN at compose time" 的兄弟行内 Suggestion 变体仍然通过。
评审主体(rv:5055451462、rv:5056647677)— 无新的可执行项
两者均为 CHANGES_REQUESTED 的「部分审查——缺口已披露」形态,内容为:确认已在 PR 上报告过的建议级发现(不再重复)、未审查缺口(集成套件在 CI 中被跳过)、Test-Plan 文件不存在提示(非阻断)、收敛姿态下延后的条目(「已记录,本轮不要求修改」——按规则未触碰),以及第 11 轮残余风险建议 land-with-residual-risk。该建议是 maintainer 的风险接受决定(合入并承担残余风险),而非再开一轮评审——此处记录供 maintainer 参考,未采取代码行动。
变异探针(每个防护都有见证)
| # | 防护 | 变异方式 | 变异时见证测试变红 | 恢复后变绿 |
|---|---|---|---|---|
| 1 | 超上限子句置疑 | 条件取反 | ✓ | ✓ |
| 2 | 子句条目标识符检查 | 禁用防护 | ✓ | ✓ |
| 3 | 动态 import( 置疑 |
禁用防护 | ✓ | ✓ |
| 4 | require 无声明置疑 | 置疑改回逃逸 | ✓ | ✓ |
| 5 | 重命名解析前按 = 拆分 |
移除拆分 | ✓ | ✓ |
| 6 | require 条目标识符检查 | 条件取反 | ✓ | ✓ |
| 7 | 字符串感知注释剥离 | 禁用字符串态 | ✓ | ✓ |
| 8 | widenScope 怀疑形态检测 | 移除防护 | ✓ | ✓ |
| 9 | staleAgainstYield !== 'dry' |
还原为 === 'yielded' |
✓ | ✓ |
| 10 | 开放句尾延期条件 | 条件取反 | ✓ | ✓ |
冲突
--conflict false — 未执行任何合并。
验证
npx vitest run src/commands/review/lib/import-graph.test.ts— 修复前见证为红(7 failed | 33 passed);修复后 40 passednpx vitest run src/commands/review/lib/incremental-scope.test.ts src/commands/review/lib/retirement.test.ts— 修复前见证为红(2 failed | 157 passed);修复后全绿npx vitest run src/commands/review/compose-review.test.ts -t "ABSENT floor…"— 修复前见证为红(1 failed | 1 passed);修复后全绿- 10 个变异探针 — 每个变异都使其见证变红,每次恢复都变绿(见上表)
npx vitest run src/commands/review(packages/cli 全部 117 个 review 测试文件)— 5645 tests,0 failures,0 errors(17 skipped)npm run build— 通过npm run typecheck— 通过npm run lint(全仓 ESLint)— 通过npx prettier --check(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/模型 qwen3.8-max
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
Not reviewed: reverse audit — stopped before round 5 by the review time budget.
Test Plan (not a blocker): src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory.
Deferred under the convergence posture (round 12, not a blocker) — recorded, not requested in this round:
packages/cli/src/commands/review/agent-prompt.test.ts:5130 — [review] the one-dry narrowing bar itself is pinned by no…packages/cli/src/commands/review/agent-prompt.ts:230 — [review] seam census recorded even when nothing was shed — briefs…packages/cli/src/commands/review/agent-prompt.ts:230 — [review] seam renderings are not gated on isFixAuditRound —…packages/cli/src/commands/review/agent-prompt.ts:3114 — [review] the posture-narrowing note's 'only' re-launch claim is…packages/cli/src/commands/review/agent-prompt.ts:3134 — [review] launch lead-in's truncation model never names the new…packages/cli/src/commands/review/compose-review.test.ts:2466 — [review] the fix-audit block's bilingual (zh) twin has zero…packages/cli/src/commands/review/compose-review.ts:3129 — [review] seam-census admission guard has no compose-side test pinpackages/cli/src/commands/review/compose-review.ts:3129 — [review] seam-census admission admits absurd magnitudes → Infinity…packages/cli/src/commands/review/compose-review.ts:5525 — [review] the 'explicit' cause rendering arm has no testpackages/cli/src/commands/review/compose-review.ts:5590 — [review] engaged floor sentence asserts deferral beside an empty…packages/cli/src/commands/review/compose-review.ts:5596 — [review] seam census silently excludes seam-less interaction files…packages/cli/src/commands/review/fetch-pr.ts:1294 — [review] recordedSeverityFloor wiring at the capture call site has…packages/cli/src/commands/review/lib/import-graph.test.ts:373 — [review] seamLines' packages parameter never exercised non-emptypackages/cli/src/commands/review/lib/import-graph.test.ts:385 — [review] multiline-clause test cannot discriminate correct recovery…packages/cli/src/commands/review/lib/import-graph.test.ts:400 — [review] plain-declaration require arm (decl[2]) untestedpackages/cli/src/commands/review/lib/import-graph.test.ts:568 — [review] destructuring-default test oracle collides with the doubt…packages/cli/src/commands/review/lib/import-graph.test.ts:606 — [review] stripComments' escape branch is pinned by zero testspackages/cli/src/commands/review/lib/import-graph.test.ts:621 — [review] side-effect import arm (callRe second alternative) untestedpackages/cli/src/commands/review/lib/import-graph.ts:308 — [review] clauseBindings' default-import arm has no testpackages/cli/src/commands/review/lib/incremental-scope.ts:168 — [review] heavy exemption in widenScope has no unit-level test…- …and 4 more (see the run report)
Convergence: round 12 posted 3 inline comment(s), 2 of them reported for the first time; the previous round posted 4 (3 new). Findings keep coming back to the same files: packages/cli/src/commands/review/compose-review.ts (findings in round 11; 1 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. (Observation only — nothing was withheld from this review because of this observation.)
中文说明
仅完成部分审查,审查缺口已披露。
未审查:反向审计——评审时间预算不足,未能开始第 5 轮。
Test Plan(非阻断):src/commands/review/lib/posture.test.ts — no such file or directory; src/commands/review/lib/import-graph.test.ts — no such file or directory; src/commands/review/lib/incremental-scope.test.ts — no such file or directory; src/commands/review/lib/retirement.test.ts — no such file or directory; src/skills/bundled/review/SKILL.test.ts — no such file or directory。
收敛姿态下延后(第 12 轮,非阻断)——已记录,本轮不要求修改:共 24 条(原文未翻译,列表见上方英文部分)。
收敛情况:第 12 轮发布了 3 条行内评论,其中 2 条是首次提出;上一轮发布了 4 条(其中 3 条首次提出)。发现反复回到同一批文件:packages/cli/src/commands/review/compose-review.ts(第 11 轮已出过发现,本轮又有 1 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。(仅为观察——本轮评审未因此扣留任何内容。)
— qwen3.8-max via Qwen Code /review (v0.22.3)
| * the file itself always stays in scope with its brief, so the seam question | ||
| * is asked even when no hunk survives. | ||
| * | ||
| * One read fails CLOSED (#10136): any read whose bindings cannot be |
There was a problem hiding this comment.
[Critical] R9-1: [certifies-falsely] [new-surface] Still stands — the seam oracle (seamLines/clauseBindings/stripComments) still under-collects without the doubt state. Four new entrance classes were probe-executed on the unmodified commit this round. The round-11 entrances are closed — the fail-closed net now covers wrapped declarations, keyword-less assignments, nested/array/rest destructuring, declaration-less dynamic imports, the clause cap, in-string markers and destructuring defaults, each test-pinned — but the surface is unbounded and every round finds new entrances: round 9 the original class, round 11 eight more, this round four more. Close the class structurally rather than patching the next corner.
The new entrances, each contradicting this file's own contract ('Under-collection of the oracle is the one error the seam bound must not make', lines 396-398): (1) stripComments has no regex-literal state — const re = /https?:\/\//; import { moved } from './changed.js'; flips the walker into line-comment mode and blanks the real import off the same line; const re = /\/*/; opens a fake block comment blanking every following line; a quote-carrying regex (const QUOTE_RE = /'/; before an 'https://x' string) false-opens a phantom string — all return seamLines = [] with no doubt for provable dependents. (2) stripComments models template literals flat, ignoring ${} nesting — a quoted backtick inside an interpolation (${''}) false-closes the template, and the later //blanks a real require; the raw specifier scan still finds the specifier whileseamLinesreturns []. (3)CLAUSE_NOISEcapture drop —import type from './changed.js'(a legal default import whose binding is literally namedtype), Flow's import typeof moved from …, import * as type from, and import { moved as type } all return [1] with the usage line unmarked instead of the doubt shape, while the brace-{ type }andconst type = require(…)siblings correctly fail closed. (4) ASCII-only captures —import éd from './changed.js';+éd();returns [1] (neither [1,2] nor doubt) while brace and require siblings fail CLOSED on the same input. Two of these mechanisms (the regex-literal and interpolation corruption) were opened by the round-11 fix's own string-aware rewrite ofstripComments`.
In widenScope every such return reads as 'no seam lines' rather than the doubt shape: kept stays empty, the interaction file republishes header-only with seam: {kept: 0}, and the hunks displaying the caller's uses of what changed are silently shed from the critical-posture round while the census and briefs describe the round as covered.
Witness:
regex-slash-slash [] / regex-block [] / regex-quote [] (control without prefix: [1,2])
interpolation: SPECS ['./changed.js'] SEAM [] (interpolation-aware strip flips to [1,2])
import-type [1] / import-typeof [1] / * as type [1] / {moved as type} [1]
vs named-{type} doubt [1,2]; controls [1,2]; fail-closed fix flips all to doubt
DEF-UNICODE [1] / STAR-UNICODE [1] / MIXED [1,3]
vs BRACE-UNICODE [1,2] REQUIRE-UNICODE [1,2] (doubt); unicode captures flip to [1,2]/[1,2]/[1,2,3]
(probes against the committed seamLines/stripComments/widenScope at 06b944c4, scratch tree;
every probe flips under the implied fix; existing suites stay green)
Close the class structurally: route the clause/declaration/comment read through an authoritative parser (the TypeScript compiler is already a workspace dependency), or make every read whose bindings cannot be proven collected — including a stripComments that cannot prove it stayed faithful — fail closed into widenScope's existing doubt arm (republish the file in full). Minimum concrete guards for this round's entrances: regex-literal awareness (or doubt) in stripComments; interpolation-aware template walking (on ${ recurse into a code state until the matching }); fail closed at every capture site where the capture is a CLAUSE_NOISE word (def, star and brace-alias arms); Unicode-aware identifier captures (\p{ID_Start}[\p{ID_Continue}$]* with the u flag) or fail closed when the clause head holds unconsumed non-space content.
The fix must preserve stripComments' length/newline guarantee ('every comment byte becomes a space, nothing else moves', import-graph.ts:317-319 — lineOf and m.index arithmetic depend on position identity), keep the doubt return as the all-lines shape consumed by if (lines.length >= fileLines) continue; in incremental-scope.ts, and keep import type T from … shedding the modifier legally. Fix witness: import-graph.test.ts cases per entrance class (the regex-literal and interpolation sources above, import type from + usage, import * as type + usage, import { moved as type } + usage, import éd from + usage) — removing any one guard must turn its case red; the probes above already flip for each.
中文说明
[Critical] R9-1:[certifies-falsely] [new-surface] 仍未解决——接缝预言机(seamLines/clauseBindings/stripComments)仍在无怀疑态下收集不足。本轮在未修改的提交上以 probe 证实了四个新入口类别。第 11 轮的入口已关闭——失败闭合网现已覆盖换行声明、无关键词赋值、嵌套/数组/rest 解构、无声明动态 import、子句上限、字符串内标记与解构默认值,均有测试钉住——但该表面无界,每轮都出现新入口:第 9 轮原始类别、第 11 轮 8 个、本轮 4 个。请结构性关闭该类,而不是再补下一个角。
新入口均违反本文件自身契约(「对接缝限宽而言,预言机收集不足是唯一不可犯的错误」,396-398 行):(1) stripComments 没有正则字面量状态——const re = /https?:\/\//; import { moved } from './changed.js'; 会把词法器翻入行注释模式、白化同一行上真实的 import;const re = /\/*/; 打开假块注释、白化其后所有行;含引号的正则(const QUOTE_RE = /'/; 后跟 'https://x' 字符串)会错误打开幻影字符串——对可证明的依赖文件全部返回 seamLines = [] 且不置疑。(2) stripComments 把模板字面量按扁平处理、忽略 ${} 嵌套——插值中带引号的反引号(${''})使模板提前闭合,其后的 //白化真实 require;原始说明符扫描仍能找到说明符,而seamLines返回 []。(3)CLAUSE_NOISE 捕获丢弃——import type from './changed.js'(合法默认导入,绑定名恰为 type)、Flow 的 import typeof moved from …、import * as type from、import { moved as type }都返回 [1](使用行未标记)而非疑态,而同形的花括号{ type }与const type = require(…) 却正确失败闭合。(4) 仅 ASCII 的捕获——import éd from './changed.js';+éd();返回 [1](既非 [1,2] 也非疑态),而花括号/require 同形输入失败闭合。其中正则字面量与模板插值两类破坏正是第 11 轮修复重写stripComments`(改为感知字符串)时引入的。
在 widenScope 中,这些返回都被读作「没有接缝行」而非疑态:kept 为空、交互文件只重发头部并记 seam: {kept: 0},展示调用方对变更内容使用场景的 hunk 被悄悄剔除,而计数与 brief 却把该轮描述为已覆盖。
证据:见英文部分代码块(对 06b944c 上真实 seamLines/stripComments/widenScope 的 probe,scratch tree 中进行;每个 probe 在相应修复下翻转;既有测试保持全绿)。
结构性修复:把子句/声明/注释读取交给权威解析器(TypeScript 编译器已是工作区依赖),或让任何无法证明已收集绑定的读取——包括无法证明保持忠实的 stripComments——失败闭合进 widenScope 已有的疑态臂(全量重发)。针对本轮入口的最小具体守卫:stripComments 增加正则字面量识别(或置疑);模板按插值感知行走(遇 ${ 递归进入代码态直至配对 });在每一处捕获为 CLAUSE_NOISE 词的捕获点(def、star、花括号别名分支)失败闭合;标识符捕获改为 Unicode 感知(u 标志的 \p{ID_Start}[\p{ID_Continue}$]*),或在子句头部仍有未消费非空内容时失败闭合。
修复必须保持 stripComments 的长度/换行保持保证(「每个注释字节变成空格,其他内容不移动」,import-graph.ts:317-319——lineOf 与 m.index 依赖位置同一性);疑态返回保持全行形态(由 incremental-scope.ts 的 if (lines.length >= fileLines) continue; 消费);import type T from … 继续合法剥离修饰符。修复验收:按入口类别在 import-graph.test.ts 各增一例;移除任一处守卫必须使对应用例变红。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| ids.add(c.id as number); | ||
| } | ||
| } | ||
| if (ids.size === 0) return null; |
There was a problem hiding this comment.
[Critical] R12-1: [certifies-falsely] [new-surface] postureNarrowing prices chunks out of the reverse-audit wave when the scope record never classified them. The guard here only handles the EMPTY delta-coverage case (ids.size === 0 → null → ordinary schedule). A plan whose scope record covers at least one chunk but leaves other chunks holding files in NEITHER deltaFiles nor interaction paths engages the narrowing anyway — those unclassified chunks leave the wave after ONE dry audit, take no cold checks, and never block converged. An honest capture provably cannot produce this state (widenScope publishes exactly touched ∪ interaction.keys() and assembleSections emits no section outside that set) — the input class is the hand-edited/corrupted plan the sibling disjoint test exists for, whose own comment states the module standard: 'Every sibling reader fails malformed input toward MORE coverage; the schedule must too.' This sibling state of the same input class fails toward LESS coverage.
Witness:
handler probe at HEAD (plan: posture critical, deltaFiles covering chunk 13 only,
interaction: [], chunks 14/15 holding a.ts/bundle.min.js;
round 1: 13 YIELD, 14/15 unknown; round 2: all DRY):
round 3 → '1 auditors required this round — one per chunk still under audit
(0 retired and 2 posture-narrowed chunk(s) skipped…'
scheduleReverseAuditRound → due: [13], narrowed: [{14, dryRound: 2}, {15, dryRound: 2}]
WITH the containment fix → '3 auditors required this round — one per chunk.'
(both committed narrowing tests stay green under the fix)
Once the delta chunk also retires on a later round, due empties and refuseConverged exits: most of the diff was audited only in rounds 1–2 while the round output presents a healthy narrowing. Fix: after building the delta set, also collect the interaction paths from scope.interaction and return null unless EVERY chunk file path is in delta ∪ interaction — degrading a scope record that does not classify the whole diff to the byte-for-byte ordinary schedule.
The containment check must never null an honest fix-audit round: honest published paths are exactly delta ∪ interaction (const paths = new Set([...touched, ...interaction.keys()]);, incremental-scope.ts:207, consumed by assembleSections' if (!paths.has(file.path)) continue;). Fix witness: add an agent-prompt.test.ts case mirroring the disjoint test — a fix-audit plan with deltaFiles covering chunk 13 only and interaction [] (chunk 14's file unclassified), rounds 1–2 answered, runRound(3) asserting the output CONTAINS — chunk 14 ─ and does NOT contain posture narrowing (#10104); removing the containment check reds it.
中文说明
[Critical] R12-1:[certifies-falsely] [new-surface] postureNarrowing 会把作用域记录从未分类的分块从反向审计波次中计价出局。此处守卫只处理空的 delta 覆盖情形(ids.size === 0 → null → 普通调度)。若计划的范围记录覆盖了至少一个分块、却让其他分块持有既不在 deltaFiles 也不在 interaction 路径中的文件,收窄仍会生效——这些未分类分块在一次 dry 审计后即离开波次、没有冷检查、也从不阻止 converged。诚实的捕获不可能产生该状态(widenScope 恰好发布 touched ∪ interaction.keys(),assembleSections 不会发出该集合之外的段落)——输入类别是兄弟不相交测试所针对的手改/损坏计划,其注释声明了模块准则:「每个兄弟读取器都把畸形输入失败朝向更多覆盖;调度也必须如此。」同一输入类别的这个兄弟状态却失败朝向更少覆盖。
证据:见英文部分代码块(HEAD 上真实处理器探针:损坏计划下第 3 轮只启动 1 个审计器、两个分块被 posture 收窄出局;包含性修复后翻转为 3 个审计器,两个既有收窄测试保持绿色)。
一旦 delta 分块在后续轮次也退休,due 变空、refuseConverged 退出:大部分 diff 只在第 1-2 轮被审计过,而轮次输出呈现为健康收窄。修复:在构建 delta 集合后,同时收集 scope.interaction 的路径,除非每个分块文件路径都在 delta ∪ interaction 中,否则返回 null——把未能分类整个 diff 的范围记录降级为逐字节的普通调度。
包含性检查绝不能把诚实的 fix-audit 轮次判为 null:诚实发布路径恰好是 delta ∪ interaction(const paths = new Set([...touched, ...interaction.keys()]);,incremental-scope.ts:207,由 assembleSections 的 if (!paths.has(file.path)) continue; 消费)。修复验收:在 agent-prompt.test.ts 增加镜像不相交测试的用例——fix-audit 计划、deltaFiles 仅覆盖分块 13、interaction 为空(分块 14 的文件未分类),第 1-2 轮应答后 runRound(3),断言输出包含 — chunk 14 ─ 且不包含 posture narrowing (#10104);移除包含性检查应使该用例变红。
— qwen3.8-max via Qwen Code /review (v0.22.3)
| `posting posture (engaged by ${fixAuditCauseEn}) — the territory fan-out ` + | ||
| `covered the commits since the previous round plus their import-seam ` + | ||
| `interaction files${fixAuditSeamEn}, and the reverse-audit waves ` + | ||
| `re-launched only delta territories and chunks whose previous wave ` + |
There was a problem hiding this comment.
[Critical] R12-2: [certifies-falsely] [new-surface] The posted Round-shape block asserts wave narrowing that cannot have happened. The wave sentence here is keyed only on the plan's posture record (fixAudit non-null) and states narrowing as an unconditional past-tense fact — 'the reverse-audit waves re-launched only delta territories and chunks whose previous wave yielded'. But narrowing is structurally impossible before round 3: scheduleReverseAuditRound returns ALL chunks due with narrowed: [] under if (round < 3) (retirement.ts:732), and the caller reads the schedule only from retirementReadsFrom = 3 (agent-prompt.ts:2970). The round-2 trigger is reachable: resolveCriticalPosture's explicit arm has no round guard and fetch-pr passes the configured floor as defaultSeverityFloor, so a round-2 re-review with --severity-floor critical (or configured review.severityFloor: critical) writes the posture, runs the fix-audit shape, re-launches every chunk — and compose then posts a wave reduction that did not happen, in the block whose own comment mandates owning every reduction.
Witness:
composeReview probe at HEAD (valid fix-audit plan record, postureCause 'explicit'):
side file round: 1 (this compose is round 2) → ROUND2-WAVE-CLAIM: true
no side file (prevRound 0, side-file-lost state) → ROUND1-WAVE-CLAIM: true
with the sentence gated on prevRound + 1 >= 3 → false / false
Fix: condition the wave sentence on the round being composed (prevRound + 1 >= 3 — prevRound is already a parameter of composeReviewBody), rendering an honest full-waves variant below it; or never assert the narrowing as a fact this compose cannot verify — state the posture's contract unless the compose can read that narrowing applied. The zh twin must carry the same gate.
The compose-side bar must mirror the scheduler's own guards (retirement.ts:732 if (round < 3) and agent-prompt.ts:2970 retirementReadsFrom = 3) — any other boundary asserts narrowing on a round the scheduler ran wide, or withholds the claim where narrowing did run. Fix witness: a compose-review.test.ts case beside the existing POSTURE pins — valid fix-audit plan record + prevRound: 1 + severityFloor: 'critical', asserting the body does NOT contain 're-launched only delta territories'; removing the round guard reds it.
中文说明
[Critical] R12-2:[certifies-falsely] [new-surface] 发布的「轮次形态」块断言了不可能发生的波次收窄。此处的波次语句只以计划中的姿态记录为键(fixAudit 非空),并把收窄陈述为无条件的过去时事实——「反向审计波次只重落 delta 领地与上一波产出发现的分块」。但第 3 轮之前收窄在结构上不可能发生:scheduleReverseAuditRound 在 if (round < 3) 下让所有分块到期并返回 narrowed: [](retirement.ts:732),调用方也只从 retirementReadsFrom = 3 起读取调度(agent-prompt.ts:2970)。第 2 轮触发可达:resolveCriticalPosture 的显式分支没有轮次守卫,fetch-pr 把配置下限作为 defaultSeverityFloor 传入,因此第 2 轮以 --severity-floor critical(或配置 review.severityFloor: critical)重审会写入姿态、运行 fix-audit 形态、重落所有分块——随后 compose 却发布了一条并未发生的波次收窄,恰好在这个其注释要求「认领每一项削减」的块里。
证据:见英文部分代码块(HEAD 上 composeReview 探针:第 2 轮与无 side file 两种状态下 ROUND2/ROUND1-WAVE-CLAIM 均为 true;加上 prevRound + 1 >= 3 门后均翻转为 false)。
修复:把波次语句以正在 compose 的轮次为条件(prevRound + 1 >= 3——prevRound 已是 composeReviewBody 的参数),其下渲染诚实的全波次变体;或永远不要断言本 compose 无法核实的收窄事实——除非 compose 能读到收窄确实发生,否则只陈述姿态的契约。中文孪生句必须携带同样的门。
compose 侧的门槛必须镜像调度器自身的守卫(retirement.ts:732 if (round < 3) 与 agent-prompt.ts:2970 retirementReadsFrom = 3)——任何其他边界都会在调度器全宽运行的轮次上断言收窄,或在收窄确实发生的轮次上扣住该声明。修复验收:在既有 POSTURE 钉住用例旁新增一例——有效 fix-audit 计划记录 + prevRound: 1 + severityFloor: 'critical',断言正文不包含 're-launched only delta territories';移除轮次守卫应使其变红。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind Autofix stopped — PR #10136 verification-repair round: the gate's
|
|
🤖 AutoFix ran out of time before finishing (timeout (7200000ms)) (attempt 7/100) — it will retry on the next scan. What I found before stopping: See the Qwen Autofix agent step logs for model/tool output. 中文说明🤖 AutoFix 在完成前耗尽了时间(timeout (7200000ms))(第 7/100 次尝试)—— 将在下次扫描时重试。 Run log: https://github.com/QwenLM/qwen-code/actions/runs/33248624092 🧠 Handled by Qwen Code · model/模型 |
|
Qwen Code review timed out. Qwen review timed out after 21600 seconds (of the 360-minute budget). This run already used the maximum 360 minute timeout. See workflow logs. |
|
🔀 Base updated: red check(s) [review-pr] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [review-pr] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |





What this PR does
When a multi-round
/reviewre-review is knowably headed for the critical-only posting posture and a usable incremental anchor exists, the round now runs a narrowed fix-audit shape instead of round 1's full shape:fetch-prpredicts the compose-time floor resolution from the side filepr-contextpersisted (the round scheduleround+1 >= 6, or the latchedflatRoundsstreak — monotone arms only) or from the CLI-recorded explicit floor (recovered with the sameresolveGhHosthost formula the compose/submit boundary uses), and recordsincremental.posture: "critical"with itspostureCausein the plan. Every doubt state reads as "no posture" — the ordinary full round.isTerritoryFanOut) reads the posture, so a fix-audit round is a territory fan-out whatever its narrowed sizes say — the roster (chunk agents, no Agent 0; 1b/1c/7/test-matrix and heavy-file invariant agents stay), the round-cap tier (the 3B tier of 5), the review: --all-chunks fans out per chunk without checking the plan's topology #9242 note andcheck-coverageall follow from the one shared predicate. Chunk briefs carry a fix-audit frame ("what did each fix change, what could that change break"); severities are unchanged — the floor governs posting, never finding.seamLinesin import-graph.ts,$-safe boundaries), with aseam: {kept, total}census per entry. A file with no seam hunk publishes header-only and still lands in a chunk, so its brief asks the seam question from the worktree. Every doubt state (unreadable source, hunk-less section, scan that keeps everything) republishes in full — the seam-bounded round sits strictly between the unwidened floor and the full widening.unknownoutcomes stay hot. Recall stays where the measured fix-induced Criticals surfaced — waves up to the same cap — over a shrinking front.floorResolvesCritical), so a round that ran the narrow shape defers sub-Critical findings even where the auto arms cannot re-derive it at compose time (a context-unavailable compose, a side file rewritten between capture and compose). An explicit--severity-floor suggestionstill wins over a stale plan record, and the body then states the floor resolved open.posture narrowing:note beside the retirement note, and a "Round shape" paragraphcompose-reviewrenders into the posted body.Why it's needed
Once a multi-round review settles into the critical-only posting posture (
floor: c), the re-review round still ran round 1's full shape: the whole territory fan-out plus up to five full-width reverse-audit waves, while everything found below Critical was deferred anyway. Measured on PR #9729 round 15 (3h13m, ~131M input tokens): the entire 18-agent finder fan-out contributed nothing postable, all three posted Criticals first surfaced in the reverse-audit waves, and the one-hop import widening re-entered 89% of the diff because every fix commit touches hub files the rest of the PR imports. Sixteen such rounds cost ~50 runner-hours without converging. The signal on these rounds lives in the fix commits and their import seams; the shape should match it.Reviewer Test Plan
How to verify
Non-UI change; everything is covered by deterministic unit and real-handler tests. From
packages/cli:npx vitest run src/commands/review # 104 files, 5123 passed npx vitest run src/commands/review/lib/posture.test.ts src/commands/review/lib/import-graph.test.ts src/commands/review/lib/incremental-scope.test.ts src/commands/review/lib/retirement.test.tsand from
packages/core:npx vitest run src/skills/bundled/review/SKILL.test.ts(41 passed).tsc --noEmitis clean for the review tree andeslint --max-warnings 0is clean on every touched file.What the new tests pin, end to end: the posture prediction's arms and clamps against compose's own resolution (
posture.test.ts); seam-line scanning including$-carrying identifiers (import-graph.test.ts); seam-bounded widening with parse/tile round-trips and header-only sections (incremental-scope.test.ts); the fix-audit roster and tier stamping (roster.test.ts,budget.test.ts); wave narrowing vs plain retirement (retirement.test.ts); the realfetch-prhandler wiring side file → posture → header-only publication → recorded budget tier (fetch-pr.test.ts); briefs and the round's narrowing note through the real builder (agent-prompt.test.ts); and the body disclosure with both floor branches, including the context-unavailable alignment arm and the explicit-suggestionoverride (compose-review.test.ts).Three independent adversarial audit rounds were run over the full diff (coverage/certification chain, marker forgery, wave-recall traps, hostile-input regexes, state-machine paths) plus a verification round over the audit fixes; all findings are addressed in this PR (notably the
$-identifier seam regex, the shape/posting alignment arm, theresolveGhHosthost axis, and validation parity between the two posture readers).Evidence (Before & After)
N/A (no UI change). Behavioral delta in one line: a critical-posture re-review that previously ran 13 territory chunks + Agent 0/1b/1c/7 + 5 full-width audit waves over 89% of the diff now runs chunk agents over the delta + seam hunks only, no Agent 0, and audit waves that shed provably-dry non-delta territories — with the reduction disclosed in the plan, the briefs, the round notes, and the posted body.
Tested on
Environment (optional)
Unit tests only (vitest aliases to src; no build needed).
Risk & Scope
incremental.posture,postureCause,interaction[].seam); plans without them behave exactly as before, and every reader fails toward the full round on malformed input.Linked Issues
Closes #10104. Related: #9790 (continuous agent-budget scaling), #9783 / #9919 (model-side scaffolding reduction), #9578 (fix-induced defect measurement).
中文说明
本 PR 做了什么
当多轮
/reviewre-review 可预知进入 critical-only 发布姿态且存在可用增量锚点时,该轮不再跑第 1 轮的全量形态,改跑收窄的 fix-audit 形态:fetch-pr从pr-context持久化的 side file(轮次日程round+1 >= 6,或已锁存的flatRounds信号——只取单调臂)或 CLI 记录的显式下限(用与 compose/submit 边界相同的resolveGhHosthost 公式恢复)预测 compose 期的下限决议,并在 plan 里记录incremental.posture: "critical"与postureCause。一切疑态都读作"无姿态"——普通全量轮。isTerritoryFanOut)读取姿态,fix-audit 轮无论收窄后的尺寸如何都走领地扇出——roster(chunk agents、去掉 Agent 0;1b/1c/7/test-matrix 与 heavy 文件 invariant agents 保留)、round-cap tier(3B 档的 5)、review: --all-chunks fans out per chunk without checking the plan's topology #9242 提示与check-coverage全部从这一个共享谓词得出。chunk brief 带 fix-audit 框架("每个修复改了什么、改动可能破坏什么");严重度语义不变——下限只管发布,不管发现。seamLines,$安全边界),每条记录seam: {kept, total}。没有接缝 hunk 的文件以 header-only 段发布、仍落入 chunk,brief 依然要求从 worktree 回答接缝问题。一切疑态(源不可读、无 hunk 段、扫描全保留)按全量重发——接缝限宽轮严格处于未加宽下限与全量加宽之间。unknown一律保持热态。召回保持在测得 fix-induced Critical 出现的位置——同一上限内的后期波次——只是覆盖面收缩。floorResolvesCritical)的一个证据臂,因此跑了收窄形态的轮次即使 compose 期无法重推(context-unavailable、side file 在 capture 与 compose 之间被改写)也照样延后 sub-Critical 发现。本轮显式--severity-floor suggestion仍胜过陈旧的 plan 记录,此时正文如实声明下限实际为开放。posture narrowing:note、以及compose-review渲染进发布正文的"轮次形态"段落。为什么需要
多轮评审进入 critical-only 发布姿态(
floor: c)后,re-review 轮仍然跑第 1 轮的全量形态:全量领地扇出加最多五波全宽反向审计,而所有低于 Critical 的发现最终都进 deferral。在 PR #9729 第 15 轮(3h13m、约 1.31 亿 input tokens)上的测量:整个 18-agent finder 扇出没有产出任何可发布内容,该轮发布的全部三条 Critical 均首现于反审波,import 一跳加宽把 89% 的 diff 拉回范围(每个修复 commit 都会碰被全 PR import 的枢纽文件)。这样的轮次跑了 16 轮、约 50 runner 小时仍未收敛。这类轮次的信号在修复 commit 及其 import 接缝上;形态应当与之匹配。Reviewer Test Plan
如何验证
非 UI 改动;全部行为由确定性单元测试与真实 handler 测试覆盖。在
packages/cli下:npx vitest run src/commands/review # 104 个文件,5123 例通过 npx vitest run src/commands/review/lib/posture.test.ts src/commands/review/lib/import-graph.test.ts src/commands/review/lib/incremental-scope.test.ts src/commands/review/lib/retirement.test.ts在
packages/core下:npx vitest run src/skills/bundled/review/SKILL.test.ts(41 例通过)。review 目录tsc --noEmit干净;触及文件eslint --max-warnings 0干净。新增测试端到端钉住:姿态预测各臂与钳制对 compose 决议的对齐(
posture.test.ts);含$标识符的接缝行扫描(import-graph.test.ts);接缝限宽的解析/铺片往返与 header-only 段(incremental-scope.test.ts);fix-audit roster 与 tier 落章(roster.test.ts、budget.test.ts);波次收窄对比普通退役(retirement.test.ts);真实fetch-prhandler 的 side file → posture → header-only 发布 → 预算档位接线(fetch-pr.test.ts);真实 builder 的 brief 与轮次收窄 note(agent-prompt.test.ts);正文披露的两个下限分支,含 context-unavailable 对齐臂与显式suggestion优先(compose-review.test.ts)。对全量 diff 做了三轮独立对抗审计(覆盖/认证链、marker 伪造、波次召回陷阱、恶意输入正则、状态机路径),并对审计修复增量做了核验轮;全部发现均已在本 PR 内解决(尤其是
$标识符接缝正则、形态/发布对齐臂、resolveGhHosthost 轴、两个姿态读取器的校验一致性)。证据(Before & After)
N/A(无 UI 改动)。行为差一句话:critical 姿态的 re-review 从"13 个领地 chunk + Agent 0/1b/1c/7 + 5 波全宽反审覆盖 89% diff"变为"chunk agents 只覆盖 delta + 接缝 hunks、无 Agent 0、反审波次剔除已证干燥的非 delta 领地"——且全部收窄在 plan、brief、轮次 note 与发布正文中披露。
测试环境
环境(可选)
仅单元测试(vitest 直连 src,无需构建)。
风险与范围
incremental.posture、postureCause、interaction[].seam);不带这些字段的 plan 行为与之前完全一致,所有读取端对畸形输入一律回退到全量轮。关联 Issue
Closes #10104。相关:#9790(agent 预算随 diff 连续伸缩)、#9783 / #9919(模型侧脚手架精简)、#9578(fix-induced 缺陷测量)。