Skip to content

fix(review): gate the recovered incremental anchor on the model that certified it - #9184

Merged
wenshao merged 21 commits into
mainfrom
fix/review-anchor-model-gate
Aug 18, 2026
Merged

fix(review): gate the recovered incremental anchor on the model that certified it#9184
wenshao merged 21 commits into
mainfrom
fix/review-anchor-model-gate

Conversation

@wenshao

@wenshao wenshao commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Incremental review's "skip what the previous round already cleared" shortcut is a same-model contract: "clean up to this commit" is one model's verdict. The local cache has always enforced that — a same-SHA re-run under a different model gets a full second opinion instead of a skip — but the anchor recovered from the posted review's machine ledger shipped bare, with no record of who certified it. This PR makes the ledger marker carry the certifying model beside the anchor and teaches the incremental checks to refuse a cross-model anchor:

  • The posted marker now records the model whose clean verdict certified the anchored commit. The field rides and falls with the anchor: fail-closed and truncated rounds withhold both, and a marker whose anchor does not survive parsing loses the model with it, so a hand-edited marker cannot present a model that qualifies no range.
  • The recovered-ledger section of the PR context file names the certifying model and instructs the orchestrator to scope incrementally only when it matches the model running the review; an absent model — markers written before this field existed — counts as a mismatch.
  • The bundled skill's incremental check now requires a model match before scoping to the interdiff, on both the cache path and the marker-recovery path. On a mismatch the round reviews the full diff and says so. The previous round's findings work list still carries over — every entry is re-asserted against the code, so it crosses models safely; only the anchor does not.

Why it's needed

Without the gate, a round run under model B that recovered model A's anchor scoped its review to changes since A's round — leaving everything before that anchor reviewed by no run of B, permanently, because B's own clean round would re-anchor past it. The cache path already refused the same-SHA shortcut across models, so the cross-model hole existed only on the recovery path that every fresh environment (CI, another clone, a colleague's checkout) takes — precisely where nothing else could catch it.

Reviewer Test Plan

How to verify

Unit suites cover the three seams: the marker round-trip keeps the model beside the anchor and drops it whenever the anchor is withheld, truncated, or fails validation; a clean composed round's posted body carries the model while a capped round withholds both; and the rendered context section names the certifying model and the gate, absent-counts-as-mismatch included. Run the review command suites in packages/cli and the bundled-skill guard tests in packages/core (npx vitest run src/commands/review and the skills test respectively). For end-to-end behavior: post a high-effort review round on a test PR, then re-run under a different model id from a clean checkout — the run should announce a full review instead of scoping to the recovered anchor, while still ruling on the previous round's findings.

Evidence (Before & After)

N/A (no UI change).

Tested on

OS Status
🍏 macOS ⚠️
🪟 Windows ⚠️
🐧 Linux

Environment (optional)

Unit tests only (vitest); no daemon or TUI involved.

Risk & Scope

  • Main risk or tradeoff: the first high-effort round after this change treats existing anchors (which predate the field) as mismatches and runs one full review; incremental scoping resumes from the next posted round. That is the fail-safe direction on purpose.
  • Not validated / out of scope: dependency-aware widening of the incremental scope and content-addressed (rebase-surviving) per-file verdict caching are follow-ups, not part of this change.
  • Breaking changes / migration notes: none — the marker field is optional, and the parser stays fail-quiet on markers that lack it.

Linked Issues

None.

中文说明

本 PR 做了什么

增量审查的"跳过上一轮已确认干净的部分"这一捷径,本质上是一个同模型契约:"截至该 commit 是干净的"只是某一个模型的裁定。本地缓存一直在强制执行这一点——同一 SHA 换模型重跑会得到一次完整的第二意见审查,而不是跳过——但从已发布 review 的机器 ledger 中恢复的 anchor 之前是"裸"的,不记录是谁认证的。本 PR 让 ledger marker 在 anchor 旁携带认证模型,并让增量检查拒绝跨模型的 anchor:

  • 发布的 marker 现在记录"其干净裁定认证了该 anchor commit"的模型。该字段与 anchor 共存亡:fail-closed 和被截断的轮次两者一并被扣下;anchor 未能通过解析的 marker 也会连带丢弃模型字段,因此手工编辑的 marker 无法伪造出"没有范围却有模型"的状态。
  • PR context 文件中恢复的 ledger 小节会写明认证模型,并指示 orchestrator 仅在其与本轮运行的模型一致时才做增量范围;模型字段缺失——早于该字段的旧 marker——按不匹配处理。
  • bundled skill 的增量检查在缓存路径和 marker 恢复路径上都要求模型匹配后才缩小到 interdiff。不匹配时本轮审查完整 diff 并明确告知。上一轮的 findings 工作清单仍然会继承——每一条都会对照代码重新断言,因此可以安全跨模型;只有 anchor 不行。

为什么需要

没有这道闸门时,模型 B 的轮次若恢复了模型 A 的 anchor,就会把审查范围缩小到 A 那一轮之后的变更——anchor 之前的所有代码将永远没有被 B 的任何一轮审查过,因为 B 自己的干净轮次还会把 anchor 继续向前推。缓存路径本来就拒绝跨模型的同 SHA 捷径,所以这个跨模型漏洞只存在于恢复路径上——而 CI、另一台机器、他人的 checkout 等所有全新环境走的恰恰是这条路径,也正是没有其他机制能兜底的地方。

审阅者测试计划

如何验证

单元测试覆盖三个接缝:marker 往返序列化在 anchor 旁保留模型,并在 anchor 被扣下、截断或校验失败时一并丢弃;干净轮次组装出的发布正文携带模型,被 cap 的轮次两者都不携带;渲染出的 context 小节写明认证模型与闸门规则,包括"缺失按不匹配处理"。分别运行 packages/cli 的 review 命令测试套件与 packages/core 的 bundled skill 守护测试(npx vitest run src/commands/review 及相应 skills 测试)。端到端行为:在测试 PR 上发布一轮高 effort 审查,然后从干净 checkout 换一个模型 id 重跑——运行应宣布进行完整审查而不是缩小到恢复的 anchor,同时仍对上一轮的 findings 逐条裁定。

证据(前后对比)

N/A(无 UI 变更)。

测试平台

Linux ✅;macOS/Windows ⚠️(单元测试与平台无关)。

环境(可选)

仅单元测试(vitest);不涉及 daemon 或 TUI。

风险与范围

  • 主要风险或取舍:合入后的第一轮高 effort 审查会把现存的(早于该字段的)anchor 视为不匹配并做一次完整审查;从下一次发布的轮次起恢复增量。这是有意选择的 fail-safe 方向。
  • 未验证 / 超出范围:增量范围的依赖感知扩展,以及内容寻址(可在 rebase 后存活)的按文件裁定缓存,均为后续工作,不在本次变更内。
  • 破坏性变更 / 迁移说明:无——marker 字段是可选的,解析器对缺少该字段的旧 marker 保持 fail-quiet。

关联 Issue

无。

…certified it

Incremental scoping is a same-model contract: "clean up to this commit"
is one model's verdict. The cache path has always enforced it through
lastModelId, but the anchor recovered from the posted review's ledger
marker shipped bare, so a round run under a different model would scope
sha..HEAD past code the current model never reviewed — permanently,
since each clean round re-anchors past the last.

The marker now carries the certifying model beside the anchor, riding
and falling with it: withheld on fail-closed and truncated rounds, and
dropped by the parser when the sha beside it did not survive. The
recovered-ledger context section names the model and instructs the gate
(absent counts as a mismatch — markers predating the field), and the
skill's incremental check requires a model match on both the cache path
and the marker-recovery path before scoping to the interdiff. The
findings work list still carries across models — every entry is
re-asserted against the code — only the anchor does not.
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Re-run on @wenshao's /triage — this pass reviews head 4112877, the commit pushed after the round-12 review.

Template looks good ✓

Problem: real, and demonstrated two ways. First, in the base-branch code: on main the ledger marker carries sha without model, and Step 1's recovered-anchor instructions read only the sha — while the cache path has always paired its anchor with lastModelId. The two recovery routes disagree about the same same-model contract. Second, and stronger: this PR's own review history is a live reproduction — twelve review rounds each closed one channel of the identity-comparison class, and the next round found another, until the head commit closed the class structurally.

Direction: aligned. This hardens /review's incremental scoping — qwen-code's own infrastructure — with no user-visible surface and no sensitive area. The fail-safe bias (unknown → mismatch → full review, never skip) is the right direction for a gate whose failure mode is code going unreviewed.

Size: 604 production logic lines, 1587 test lines, 31 lines of docs and bundled-skill text. Production: pr-context.ts 163, fetch-pr.ts 92, compose-review.ts 89, ledger.ts 69, round-model.ts 66 (new), shellContextEnv.ts 41, config.ts 40, sessionIdContext.ts 27, submit.ts 17. It now touches core paths (packages/core config/session/shell-env — 108 production lines) as well as the CLI review commands. The author is a maintainer, so no hard block applies; the 500+ production-line core-touch advisory does, and Stage 3 handles it.

Approach: scope grew from the original ~111 production lines because each review round demonstrated a new channel of the same class — the bare-id comparison in prompt text, the blanked runtime channel, round-start drift, the side-file divergence — and each addition closes one demonstrated hole, none speculative. The final commit is the right endpoint: it moves the last identity comparison out of prompt text into the CLI, and the skill test now asserts the absence of comparison wording, closing the class by construction rather than by another point fix. No drive-by changes.

Risk: no elevated risk signals — none of the changed files match the revert-correlated paths.

Moving on to code review. 🔍

中文说明

@wenshao/triage re-run——本轮审查 head 4112877,即第 12 轮 review 之后推送的提交。

模板完整 ✓

问题:真实存在,且有两重证明。其一,base 分支代码可直接观察到:main 上的 ledger marker 只携带 sha 而没有 model,Step 1 的恢复 anchor 指令也只读 sha——而缓存路径一直将 anchor 与 lastModelId 配对。两条恢复路径对同一个"同模型契约"执行不一致。其二更有力:本 PR 自己的 review 历史就是活的复现——12 轮 review 每轮关掉身份比较这一类问题的一个通道,下一轮又发现另一个,直到 head 提交从结构上关闭整类问题。

方向:对齐。这是对 /review 增量审查机制的加固——qwen-code 自身基础设施——无用户可见界面,不涉及敏感区域。fail-safe 取向(未知 → 不匹配 → 完整审查,绝不跳过)对于"失败模式是代码漏审"的闸门来说是正确方向。

规模:604 行生产逻辑、1587 行测试、31 行文档与 bundled skill 文本。生产代码:pr-context.ts 163、fetch-pr.ts 92、compose-review.ts 89、ledger.ts 69、round-model.ts 66(新增)、shellContextEnv.ts 41、config.ts 40、sessionIdContext.ts 27、submit.ts 17。现已触及核心路径(packages/core 的 config/session/shell-env——108 行生产代码)以及 CLI review 命令。作者是维护者,不适用硬性阻断;500+ 生产行的核心触及提示适用,由 Stage 3 处理。

方案:范围从最初约 111 行生产代码增长,是因为每轮 review 都实证出同一类问题的一个新通道——prompt 文本中的裸 id 比较、被置空的运行时通道、轮次开始后的身份漂移、side file 分歧——每次增量都堵住一个被实证的洞,没有投机性改动。最后一个提交是正确的终点:把最后一处身份比较从 prompt 文本移入 CLI,且 skill 测试现在断言比较措辞的缺席,从构造上关闭整类问题,而不是再打一个点补丁。无顺手改动。

风险:无升级风险信号——改动文件均未命中与 revert 相关的路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at 411287758df06cac8aee2a4ee581244fb6bfd313 · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Code review

My independent proposal before going line-by-line: (1) qualify the marker's anchor with the model that certified it, (2) make the pair share one lifecycle — anywhere the anchor is withheld or fails validation, the model goes with it, (3) take the certifying identity from something a model cannot forge — the runtime-injected env, not the model-written state field, (4) gate both recovery routes on it in-process, absent counting as mismatch, (5) propagate it through the side file automatically. The PR matches that on every point and goes three legitimate steps further: a provider-qualified identity (<model>@<digest>, closing the two-providers-one-name hole a bare-id comparison would have missed), a round-start stamp with a drift gate (closing the review-under-A-then-post-under-B flow), and moving the cache-path comparison into fetch-pr as well — so zero identity comparisons remain in prompt text, with the skill test asserting their absence.

What I verified against head 4112877:

  • Both round-12 Criticals are closed by the head commit. R12-1 (cache-path gate compared bare ids on both sides): the gate no longer lives in prompt text — --since-model carries the certifier verbatim and runFetchPr rules it with certifierMatchesRound before any history is consulted; the new fetch-pr test pins that order (a cross-model anchor is refused with no cat-file probe at all), and the SKILL guard asserts no lastModelId equals / model matches|differs wording survives. R12-2 (drift gate disengaged on a blank runtime channel): identityDrifted = roundStart !== '' && (runtime === '' || roundStart !== runtime) — a stamped round whose poster cannot be identified now withholds the whole anchor pair instead of falling back to the model-written field; an unstamped round keeps prior behaviour. Both have dedicated tests, including the exact deferred-post scenario.
  • The identity pipeline is coherent end to end. Config publishes QWEN_CODE_MODEL_IDENTITY (<model>@<sha256(authType+baseUrl)> truncated to 8 hex; the bare id when nothing qualifies), keyed per session — in daemon mode the global slot belongs to the first session to boot, and a later session gets its own entry, not a confidently wrong qualification. getShellContextEnvVars blanks the key rather than omitting it (an omitted key leaks the parent's stale value through the spawn-site spread) and drops a global identity that does not describe the session's own model. roundModelIdFrom prefers the qualified slot, reads blank as "fall back to the bare id", and certifierMatchesRound is whole-string equality where every unknown is a mismatch — including two unknowns.
  • The lifecycle pairing holds at every seam. The serializer writes model only beside a validated sha; an over-cap id withholds the pair whole; over the byte cap the pair sheds before any finding; the parser drops a model whose sha did not survive; stripAnchor strips the pair for foreign ledgers; attribution off withholds the model with the footer — the runtime channel included, pinned by test; identity drift withholds the pair.
  • The earlier Criticals are resolved too. R9-3 (wiring-test env hygiene): both wiring tests now clear and restore QWEN_CODE_MODEL_IDENTITY — necessary since this PR's own Config publishes an ambient one on the dogfooding path. R2-9 (cross-provider identity): substantively closed — the decision parked with the maintainer in the earlier triage run was answered by implementing the richer identity, and DESIGN.md records the residual boundary honestly (the cache's lastModelId stays model-typed; a forged cache id can defeat the gate, but not beyond the pre-change baseline).
  • The side-file divergence gate rules on the sha Step 1 will actually pass. persistedAnchorSha reads the file after the persist decision (order verified), anchorRuling is only rendered when the recovered ledger carries a sha, and divergence is a no-verdict state that routes to the full range.

Remaining open items — all Suggestion-level, none blocking: three prose locations still name QWEN_CODE_MODEL where the boundaries prefer QWEN_CODE_MODEL_IDENTITY (the R9-11 class — the DESIGN.md bullet, the fetch-pr.ts field doc, the compose-review.ts JSDoc); the provider-separation assertion in compose-review.test.ts keeps its tautological .not.toBe half (R9-8); the user-facing note quoted in code-review.md is illustrative — no code path emits that exact string (R9-12); and the provider-separation tests vary baseUrl under one authType, leaving authType-only discrimination unpinned (J3). Round 12's eight deferred probes (the divergence gate's sha-less and certifier-only edges, two wiring-coverage gaps) remain recorded; every one degrades toward more review, so they belong in a follow-up, not in a block.

Testing evidence — this is an unattended CI run, so nothing here was executed by triage; the evidence is the PR's own CI, read through the API:

Final CI results for 4112877 (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Classify PR ✅ success
Dependency CVE audit ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success
Secret scan (TruffleHog) ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

No red checks at the time of writing. The one to watch is Test (ubuntu-latest, Node 22.x), still running; the three skipped test jobs are the repo's standing pattern for this PR class — the previous head ef2e5f39 shows the identical shape with ubuntu green, so they are not a PR signal. The finalize workflow updates the table once CI settles. Not verified: the suite's result on this exact head, pending that run.

Sandboxed verification would settle what the unit suite cannot: @qwen-code /verify — the multi-run recovery contract (a clean round posted under model A, then a model-B run in a fresh environment refusing A's anchor and reviewing the full range) is this PR's central behavioural claim, and no test exercises it end-to-end — the suites pin the seams (marker round-trip, boundary injection, gate rulings) but not their composition across runs.

中文说明

代码审查

逐行阅读前的独立方案:(1) 让 marker 的 anchor 携带认证它的模型;(2) 二者共存亡——anchor 被扣下或校验失败的任何地方,model 一并扣下;(3) 认证身份取自模型无法伪造的来源——运行时注入的环境变量,而非模型填写的 state 字段;(4) 两条恢复路径都在进程内对其做闸门判定,缺失按不匹配处理;(5) 自动传递到 side file。本 PR 每一点都与该方案吻合,并合理地多走了三步:provider 限定的身份(<model>@<digest>,堵上裸 id 比较会漏掉的"两个 provider 同名模型"漏洞)、轮次开始时的身份戳记加漂移闸门(堵上"A 模型审查、B 模型发布"的流程)、并把缓存路径的比较也移入 fetch-pr——prompt 文本中从此零身份比较,且 skill 测试断言其缺席。

在 head 4112877 上核实的内容:

  • 第 12 轮的两个 Critical 均由 head 提交关闭。 R12-1(缓存路径闸门两侧比较裸 id):闸门不再位于 prompt 文本——--since-model 原样携带认证者,runFetchPr 在查阅任何历史之前用 certifierMatchesRound 裁定;新的 fetch-pr 测试钉死了该顺序(跨模型 anchor 被拒时完全没有 cat-file 探测),SKILL 守卫断言 lastModelId equals / model matches|differs 措辞不再存留。R12-2(运行时通道为空时漂移闸门失效):identityDrifted = roundStart !== '' && (runtime === '' || roundStart !== runtime)——带戳记但无法确定发布者的轮次现在整体扣下 anchor 对,而不是回退到模型填写的字段;无戳记轮次保持原行为。两者都有专门测试,覆盖确切的延迟发布场景。
  • 身份管道端到端自洽。 Config 发布 QWEN_CODE_MODEL_IDENTITY<model>@<sha256(authType+baseUrl)> 截 8 位十六进制;无可限定信息时为裸 id),按会话键控——daemon 模式下全局槽位属于首个启动的会话,后续会话取自己的条目,而不是拿到一个"自信的错误"限定。getShellContextEnvVars 置空而非省略该键(省略会让父进程的旧值经由 spawn 处的 spread 泄漏),并丢弃不能描述本会话模型的全局身份。roundModelIdFrom 优先限定槽位,把空白读作"回退裸 id";certifierMatchesRound 是全字符串相等,任何未知都是不匹配——两个未知亦然。
  • 生命周期配对在每个接缝成立。 序列化器只在通过校验的 sha 旁写 model;超上限的 id 整体扣下配对;超出字节上限时先丢配对再丢 findings;解析器丢弃 sha 未存活的 model;stripAnchor 对外部账户 ledger 剥除配对;关闭署名时 model 与页脚一并扣下——含运行时通道,有测试钉死;身份漂移扣下配对。
  • 更早的 Critical 也已解决。 R9-3(接线测试环境清理):两处接线测试现在都会清除并恢复 QWEN_CODE_MODEL_IDENTITY——本 PR 的 Config 在 dogfooding 路径下会发布环境值,这一步是必要的。R2-9(跨 provider 身份):实质关闭——上次 triage 转交维护者的决策已由实现更丰富身份作答,DESIGN.md 也如实记录了残余边界(缓存的 lastModelId 仍由模型填写;伪造的缓存 id 可以骗过闸门,但不超过改动前的基线)。
  • side file 分歧闸门裁定的正是 Step 1 实际会传的 sha。 persistedAnchorSha 在 persist 决定之后读取(顺序已验证),anchorRuling 仅在恢复的 ledger 携带 sha 时渲染,分歧态不给出裁定、直接走完整审查。

其余未决项——全部为 Suggestion 级,均不阻断:三处行文仍以 QWEN_CODE_MODEL 指代身份,而边界实际优先 QWEN_CODE_MODEL_IDENTITY(R9-11 类——DESIGN.md 条目、fetch-pr.ts 字段文档、compose-review.ts JSDoc);compose-review.test.ts 的 provider 分离断言保留了同义反复的 .not.toBe 半边(R9-8);code-review.md 引用的用户可见提示是示意性的——没有任何代码路径会输出这串原文(R9-12);provider 分离测试只在一处 authType 下变换 baseUrl,authType 单独区分未被钉死(J3)。第 12 轮记录的八条延后探针(分歧闸门无 sha/仅认证者不同的边界、两处接线覆盖缺口)仍然在案;它们一律朝"多审"方向退化,应进跟进任务,不构成阻断。

测试证据——这是无人值守的 CI 运行,triage 未执行任何 PR 代码;证据为 PR 自身的 CI,经 API 读取。写入时没有任何红色检查;需关注的是仍在运行的 Test (ubuntu-latest, Node 22.x)。三个被跳过的测试作业是本仓库对此类 PR 的既有模式——上一个 head ef2e5f39 呈完全相同的形态且 ubuntu 为绿,故不属于本 PR 的信号。未验证:该 head 上的套件结果,等待该次运行。

沙盒验证可以补足单测无法覆盖的部分:@qwen-code /verify——多轮恢复契约(模型 A 发布干净轮次后,模型 B 在全新环境拒绝 A 的 anchor 并完整审查)是本 PR 的核心行为主张,而没有任何测试端到端演练它——各套件钉死的是接缝(marker 往返、边界注入、闸门裁定),而非跨轮次的组合行为。

Qwen Code · qwen3.8-max

Reviewed at 411287758df06cac8aee2a4ee581244fb6bfd313 · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Confidence: 3/5 — clean review, capped by policy: the Stage 0 core-size awareness flag applies (604 production lines touching core paths), and that cap drives the action, not doubt about the diff.

Stepping back: against my independent proposal this PR matches on every point and goes three legitimate steps further — provider-qualified identity, the round-start drift gate, and every identity comparison moved out of prompt text. The two round-12 Criticals that the standing CHANGES_REQUESTED review rests on are closed at this head; I verified both fixes in the code, and each has a dedicated test pinning the exact scenario. Every Critical raised across the twelve rounds is resolved or substantively closed at this commit — R12-1 and R12-2 by the final commit, R9-3 by the wiring-test hygiene fix, R2-9/R1-3 by the maintainer's own decision to implement the richer identity. What remains is Suggestion-level doc wording and a recorded probe list — follow-up material. Six months from now this reads as careful, fail-safe engineering: every unknown degrades to reviewing more, never to skipping.

Why defer instead of approve: this run's Stage 0 raises the 500+ production-line core-touch advisory, and an escalated PR caps at 3/5 with the decision handed to a maintainer. The flag is a formality here — the author is the maintainer this gate would escalate to, and nobody has engaged this PR more deeply — but the cap exists so the bot does not auto-approve a 600-line core change on its own authority, and this run will not be the one to decide the rule doesn't apply. CI on the reviewed head is also still running (the ubuntu unit suite), so there is no approve-on-green marker either — an approval should land on green, not in flight.

@wenshao — your call, and it should be an easy one: sign off here (or a maintainer approval on the PR) and this is ready to merge once CI lands green. The open nits (R9-11 doc wording in three places, the R9-8 tautology, the R9-12 quoted notice, the J3 pin) and the eight round-12 probes are fine as follow-ups; none of them gate the merge in my reading.

中文说明

置信度:3/5——审查是干净的,压分来自政策:Stage 0 的核心规模提示适用(604 行生产逻辑触及核心路径),该上限驱动行动,而非对 diff 有疑问。

退一步整体看:对照我的独立方案,本 PR 每一点都吻合,并合理地多走了三步——provider 限定的身份、轮次开始的漂移闸门、以及把所有身份比较移出 prompt 文本。支撑当前 CHANGES_REQUESTED 状态的第 12 轮两个 Critical 已在本 head 上关闭;我在代码中核实了两处修复,且各有一个专门测试钉死对应场景。十二轮中提出的每一个 Critical 都已在此 commit 上解决或实质关闭——R12-1 与 R12-2 由最后一个提交关闭,R9-3 由接线测试的环境清理修复,R2-9/R1-3 由维护者亲自选择实现更丰富的身份而关闭。剩下的只有 Suggestion 级的行文措辞与一份记录在案的探针清单——属于跟进事项。六个月后回头看,这是一份谨慎、fail-safe 的工程:任何未知都退化为"多审",绝不"跳过"。

为什么转交而非批准:本轮 Stage 0 触发了 500+ 生产行核心触及提示,被升级的 PR 封顶 3/5、决定权交给维护者。这个提示在此只是形式——作者就是这道闸门要转交的那位维护者,没有人比 ta 更深入地参与了本 PR——但该上限的意义正在于:机器人不凭自身权威自动批准一个 600 行规模的核心改动,本轮也不会擅自判定规则不适用。受审 head 上的 CI 也还在运行(ubuntu 单测套件),因此也不发 approve-on-green 标记——批准应落在绿色之后,而不是飞行途中。

@wenshao——由你拍板,而且应该很轻松:在此确认(或在 PR 上给出维护者批准),CI 转绿后即可合入。未决的小项(三处 R9-11 行文、R9-8 同义反复、R9-12 引用的提示、J3 钉死)以及第 12 轮的八条探针都可以作为跟进;按我的判断,它们都不构成合入闸门。

Qwen Code · qwen3.8-max

Reviewed at 411287758df06cac8aee2a4ee581244fb6bfd313 · re-run with @qwen-code /triage

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 84.79% 84.79% 90.12% 83.84%
Core 88.09% 88.09% 89.58% 86.68%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   84.79 |    83.84 |   90.12 |   84.79 |                   
 src               |   85.77 |    81.78 |   88.03 |   85.77 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |    73.4 |    78.04 |   80.76 |    73.4 | ...1338-1342,1469 
  ...ractiveCli.ts |   88.17 |    82.44 |   88.88 |   88.17 | ...3117,3123,3189 
  ...liCommands.ts |   88.93 |    83.21 |      80 |   88.93 | ...97-599,615,721 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   72.36 |    74.79 |   91.58 |   72.36 |                   
  acpAgent.ts      |   71.77 |    74.62 |   91.13 |   71.77 | ...83,12888-12890 
  ...k-reporter.ts |     100 |       80 |     100 |     100 | 81,84,119,141     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...figuration.ts |     100 |      100 |     100 |     100 |                   
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |    97.1 |    95.83 |   93.33 |    97.1 |                   
  filesystem.ts    |    97.1 |    95.83 |   93.33 |    97.1 | ...22-123,246-247 
 ...ration/session |   91.18 |    86.26 |   95.84 |   91.18 |                   
  Session.ts       |   90.53 |    84.85 |   95.23 |   90.53 | ...16,11943-11947 
  ...entTracker.ts |   96.81 |    89.36 |      90 |   96.81 | 137-143,222       
  ...projection.ts |   98.85 |    91.59 |     100 |   98.85 | 234,250,262       
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   94.18 |     86.2 |     100 |   94.18 | ...15,319,399,403 
  ...y-replayer.ts |   83.17 |    92.98 |   94.11 |   83.17 | ...24-142,260-262 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...oal-update.ts |   98.61 |    97.29 |     100 |   98.61 | 64                
  ...lure-guard.ts |   98.32 |    97.72 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.62 |    92.69 |   96.96 |   95.62 |                   
  ...ageEmitter.ts |   95.25 |    93.54 |     100 |   95.25 | ...08-115,128-129 
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   98.57 |    94.84 |     100 |   98.57 | 75-76,394-395     
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/agent-view    |   89.03 |    81.37 |   89.09 |   89.03 |                   
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  ...sor-client.ts |   80.38 |    72.54 |   76.66 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    89.47 |   84.61 |   96.61 | 129-130,150-151   
  ...sor-runner.ts |    84.9 |     75.6 |      85 |    84.9 | ...44,468,471-481 
  ...sor-server.ts |   85.71 |    83.06 |   95.45 |   85.71 | ...67-468,471-488 
  ...isor-store.ts |   97.73 |    81.16 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |     91.3 |   83.33 |   93.98 | 228-238           
 src/commands      |   90.34 |    77.48 |   65.62 |   90.34 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.79 |      100 |      50 |   98.79 | 94                
  serve.ts         |   88.95 |    74.52 |     100 |   88.95 | ...74,877-880,892 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   89.08 |    88.56 |   90.64 |   89.08 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   94.88 |    95.49 |      90 |   94.88 | ...20-323,368-371 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.88 |    96.35 |     100 |   95.88 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.91 |    85.55 |   94.33 |   93.91 | ...1264,1271-1272 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.53 |    96.66 |     100 |   98.53 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    85.8 |    82.17 |      88 |    85.8 | ...85,591-594,606 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.85 |    87.73 |   87.09 |   88.85 |                   
  consent.ts       |   72.53 |    90.32 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |   75.63 |    55.55 |     100 |   75.63 | ...30-134,136-140 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.31 |    84.61 |   83.33 |   90.31 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   93.15 |    84.84 |      80 |   93.15 | ...78-180,198-199 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   90.02 |    89.58 |   90.34 |   90.02 |                   
  agent-prompt.ts  |      94 |    92.55 |   97.43 |      94 | ...2785,2940-3020 
  base-tree.ts     |   76.16 |    80.76 |   77.77 |   76.16 | ...50-371,373-386 
  capture-local.ts |      70 |     90.9 |      75 |      70 | 112-116,163-194   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   92.79 |     88.7 |   84.61 |   92.79 | ...43-648,650-651 
  comment-body.ts  |   69.92 |    92.85 |   66.66 |   69.92 | ...18,145,147-152 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |    97.1 |    92.66 |   97.43 |    97.1 | ...3102,3130-3152 
  cost-ledger.ts   |   94.58 |     94.4 |   81.25 |   94.58 | ...53-654,694-704 
  drive.ts         |   76.07 |    85.71 |   81.81 |   76.07 | ...90-492,497-499 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-diff.ts    |   73.41 |      100 |   66.66 |   73.41 | 75-95             
  fetch-pr.ts      |   98.22 |    95.25 |   90.47 |   98.22 | ...1236,1371-1376 
  findings.ts      |   96.01 |    92.08 |     100 |   96.01 | ...1227,1236-1237 
  issue-context.ts |    88.1 |     93.1 |   85.71 |    88.1 | 247-274           
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.54 |     92.3 |   66.66 |   85.54 | 67-72,131-136     
  meta.ts          |   76.84 |     91.3 |   66.66 |   76.84 | 91-96,115-130     
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |    99.4 |    95.16 |     100 |    99.4 | 472,645,701       
  plan-diff.ts     |    68.1 |      100 |   66.66 |    68.1 | 162-205           
  pr-context.ts    |   94.43 |    83.81 |     100 |   94.43 | ...1600,1677-1693 
  presubmit.ts     |   90.36 |    89.15 |      90 |   90.36 | ...50-751,837-867 
  ...ish-assets.ts |    81.3 |    82.22 |   85.71 |    81.3 | ...75-479,506-552 
  repo-context.ts  |   94.62 |    90.75 |     100 |   94.62 | ...66-467,482-487 
  ...ve-anchors.ts |   78.34 |    89.28 |      75 |   78.34 | ...83-188,200-217 
  run.ts           |   83.92 |    88.37 |   94.11 |   83.92 | ...16,632-680,693 
  save-artifact.ts |   90.06 |    81.81 |   93.75 |   90.06 | ...18-321,414-417 
  script-lint.ts   |   81.27 |    79.38 |   88.88 |   81.27 | ...69-783,785-807 
  submit.ts        |   85.33 |    87.64 |      90 |   85.33 | ...14,603,630-666 
  test-delta.ts    |   86.34 |       92 |      60 |   86.34 | 171-202,465-473   
  test-efficacy.ts |   88.04 |    84.12 |   95.45 |   88.04 | ...2602,2610-2630 
  test-plan.ts     |   91.44 |    91.39 |   89.47 |   91.44 | ...38-839,903-920 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |    97.8 |    95.14 |   98.67 |    97.8 |                   
  agent-briefs.ts  |      99 |      100 |      50 |      99 | 748-749           
  ...t-identity.ts |     100 |      100 |     100 |     100 |                   
  anchors.ts       |     100 |    96.42 |     100 |     100 | ...39,175,184,231 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  audit-layers.ts  |   98.67 |    96.15 |     100 |   98.67 | 288-290           
  authorization.ts |   93.02 |    94.11 |     100 |   93.02 | 152-158           
  budget.ts        |     100 |    97.91 |     100 |     100 | 876,916           
  build-budget.ts  |     100 |      100 |     100 |     100 |                   
  coverage.ts      |    96.6 |    92.85 |     100 |    96.6 | ...1115,1669-1670 
  deadline.ts      |   98.67 |    94.05 |     100 |   98.67 | 207,625,657,725   
  diff-flags.ts    |     100 |        0 |     100 |     100 | 75                
  diff-plan.ts     |   98.73 |    93.08 |     100 |   98.73 | ...41,264,290-291 
  disk.ts          |     100 |      100 |     100 |     100 |                   
  effort.ts        |     100 |      100 |     100 |     100 |                   
  failing-files.ts |     100 |    93.33 |     100 |     100 | 41                
  gh.ts            |   89.09 |    95.31 |   77.77 |   89.09 | ...29,366-367,394 
  git.ts           |   97.84 |    96.15 |     100 |   97.84 | 207-208           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ...audit-gate.ts |     100 |    97.56 |     100 |     100 | 138               
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |   84.86 |    90.38 |     100 |   84.86 | ...63-473,475-483 
  ...ry-context.ts |   96.61 |    95.48 |     100 |   96.61 | ...47-450,496-499 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  npm-toolchain.ts |   98.17 |    95.39 |     100 |   98.17 | ...,755,1126,1143 
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   91.48 |       75 |     100 |   91.48 | 31-32,35-36       
  prompt-record.ts |   98.03 |    94.23 |     100 |   98.03 | 293-294,300       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   97.26 |    91.42 |     100 |   97.26 | 49-50             
  report.ts        |   94.89 |    93.75 |     100 |   94.89 | 207-211           
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 187               
  retirement.ts    |     100 |    93.52 |     100 |     100 | ...38-539,729,883 
  review-footer.ts |     100 |      100 |     100 |     100 |                   
  ...w-settings.ts |     100 |    94.73 |     100 |     100 | 79                
  roster.ts        |     100 |    95.52 |     100 |     100 | 136,154,199       
  round-model.ts   |     100 |      100 |     100 |     100 |                   
  run-ledger.ts    |   98.15 |     93.7 |     100 |   98.15 | ...23,521,627,650 
  same-file.ts     |     100 |    94.11 |     100 |     100 | 35                
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.11 |    94.11 |     100 |   98.11 | 416,457,497-498   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  toolchain.ts     |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   98.05 |    95.03 |     100 |   98.05 | ...67,415,684-685 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 186               
  workspaces.ts    |     100 |    96.77 |     100 |     100 | 222,452,499,512   
  worktree.ts      |     100 |      100 |     100 |     100 |                   
 ...w/lib/platform |   95.48 |       75 |     100 |   95.48 |                   
  github.ts        |   95.23 |    74.28 |     100 |   95.23 | 25-28,210-211     
  registry.ts      |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...mands/sessions |   94.11 |    89.06 |   89.47 |   94.11 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
  ps.ts            |     100 |    94.44 |     100 |     100 | 58                
 src/config        |   94.95 |    89.87 |   96.28 |   94.95 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   89.12 |    88.69 |   83.78 |   89.12 | ...2497,2499-2507 
  ...cy-monitor.ts |      90 |    77.27 |     100 |      90 | ...72-73,90-92,98 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |    96.5 |    93.51 |      95 |    96.5 | ...85-586,640-641 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |    97.4 |       50 |     100 |    97.4 | 240-243           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.96 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.27 |    92.64 |      90 |   91.27 | ...1030,1032-1033 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.47 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    78.94 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |    88.88 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |   75.08 |    67.64 |   71.42 |   75.08 |                   
  ...tputBridge.ts |   75.33 |    68.18 |   73.68 |   75.33 | ...09-410,418-421 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   86.22 |    81.92 |   89.65 |   86.22 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   80.98 |    77.27 |   84.12 |   80.98 |                   
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...31-632,635-636 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |   45.95 |    69.03 |   55.26 |   45.95 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   55.01 |    67.14 |   58.33 |   55.01 | ...15-624,639-644 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   40.64 |    68.11 |   46.66 |   40.64 | ...72-684,693-722 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.16 |    94.22 |   95.29 |   98.16 |                   
  ...putAdapter.ts |   98.02 |     93.3 |   98.07 |   98.02 | ...1433,1449-1450 
  ...putAdapter.ts |   96.22 |    91.66 |   85.71 |   96.22 | 52-53             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.51 |      100 |   90.47 |   98.51 | 90-91,131-132     
  ...projection.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/runtime       |   99.61 |    95.04 |     100 |   99.61 |                   
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   88.17 |    84.75 |   90.81 |   88.17 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.99 |     91.5 |     100 |   93.99 | ...29-430,433-435 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 700               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.54 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.89 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   89.64 |    94.11 |   96.29 |   89.64 | ...57-269,521-524 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.27 |     85.2 |     100 |   87.27 | ...10,816-820,838 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...horization.ts |     100 |      100 |     100 |     100 |                   
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.54 |    84.53 |   97.14 |   92.54 | ...1489,1543-1547 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.9 |     78.6 |   94.73 |    90.9 | ...1001,1022-1027 
  ...tree-guard.ts |   92.89 |    87.55 |     100 |   92.89 | ...2766,2836-2840 
  daemon-logger.ts |   82.82 |    78.68 |   92.04 |   82.82 | ...1775,1802-1808 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.64 |    91.77 |     100 |   98.64 | ...1503,1505-1506 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    87.09 |     100 |   92.06 | ...72,287-293,316 
  ...h-settings.ts |   94.94 |    90.41 |     100 |   94.94 | ...30,708,724,734 
  fast-path.ts     |   90.99 |    81.38 |   95.45 |   90.99 | ...33-542,608-609 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-149             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...30-131,142-143 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.68 |    88.29 |     100 |   92.68 | ...89-291,303-305 
  ...qwen-serve.ts |   84.01 |    80.96 |    75.9 |   84.01 | ...7923,7941-7945 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.27 |    89.18 |     100 |   94.27 | ...34,538-539,578 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  ...-lifecycle.ts |   89.16 |    90.29 |   86.95 |   89.16 | ...24-325,330-334 
  server.ts        |   91.14 |     90.6 |   72.03 |   91.14 | ...2960,2990-2991 
  ...-admission.ts |   98.24 |     94.8 |     100 |   98.24 | 79-80,303-304     
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...-redaction.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.72 |    77.93 |     100 |   93.72 | ...51,854,867-869 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   92.18 |    88.37 |     100 |   92.18 | ...21-224,267-270 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   94.98 |     90.5 |     100 |   94.98 | ...67-568,575-576 
  ...e-remember.ts |   98.23 |    92.56 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |    89.4 |    90.47 |     100 |    89.4 | ...89-190,258-279 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...visibility.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.09 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   79.65 |    79.91 |   94.09 |   79.65 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |   93.03 |    84.13 |   98.52 |   93.03 | ...1624,1671-1682 
  dispatch.ts      |   74.18 |    76.45 |   91.52 |   74.18 | ...5383,5440-5446 
  index.ts         |   82.68 |    79.74 |   91.22 |   82.68 | ...2424,2510-2511 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  ...ach-budget.ts |     100 |      100 |     100 |     100 |                   
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   98.26 |    88.75 |     100 |   98.26 | 87-88,117         
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   94.06 |    89.09 |     100 |   94.06 | 50,55,134,138-141 
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 .../conversations |   90.53 |     87.2 |   95.23 |   90.53 |                   
  ...e-activity.ts |     100 |      100 |     100 |     100 |                   
  ...ime-errors.ts |     100 |      100 |     100 |     100 |                   
  ...me-manager.ts |     100 |      100 |     100 |     100 |                   
  ...-ownership.ts |   87.33 |    83.33 |   88.46 |   87.33 | ...57-558,601-602 
  ...-workspace.ts |   88.26 |    82.53 |     100 |   88.26 | ...33-234,246-247 
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
 src/serve/fs      |   87.27 |    82.01 |     100 |   87.27 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |    74.01 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.52 |    89.18 |     100 |   90.52 | 172-180           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   87.37 |    81.39 |     100 |   87.37 | ...2811,2821-2822 
 src/serve/live    |   78.07 |    70.17 |   90.13 |   78.07 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  discovery.ts     |   85.89 |    81.91 |    90.9 |   85.89 | ...73-579,592-593 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.63 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |   76.69 |    67.47 |   85.71 |   76.69 | ...1884,1975-1976 
  ...controller.ts |   67.82 |    79.31 |   72.72 |   67.82 | ...66-278,287-295 
  ...ak-to-user.ts |   96.66 |      100 |   83.33 |   96.66 | 37-38             
  ...sk-service.ts |   86.32 |    61.35 |   93.33 |   86.32 | ...1170,1194-1201 
  ...task-tools.ts |      99 |      100 |   85.71 |      99 | 205-206           
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.85 |    77.39 |     100 |   94.85 | ...18,327-330,350 
  types.ts         |     100 |      100 |     100 |     100 |                   
 .../local-control |   82.89 |    86.13 |      90 |   82.89 |                   
  credentials.ts   |   96.42 |    95.45 |     100 |   96.42 | 109-110           
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...interfaces.ts |   43.58 |       75 |   42.85 |   43.58 | ...09-117,130-142 
  ...r-identity.ts |     100 |    85.71 |     100 |     100 | 61                
  service.ts       |    93.4 |       90 |     100 |    93.4 | ...20-222,313-315 
 src/serve/routes  |   85.63 |    80.48 |   94.78 |   85.63 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |   98.73 |    96.15 |     100 |   98.73 | 82                
  ...nel-notify.ts |   79.16 |    85.18 |     100 |   79.16 | ...03-104,120-126 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 143               
  health.ts        |   99.09 |    91.17 |     100 |   99.09 | 147               
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |   84.61 |    76.47 |     100 |   84.61 | ...04,106-111,131 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.53 |    84.26 |   93.33 |   87.53 | ...1389,1432-1433 
  ...on-runtime.ts |   91.42 |       90 |     100 |   91.42 | 56-64             
  session.ts       |   85.86 |    81.76 |   91.34 |   85.86 | ...6283,6285-6286 
  sse-events.ts    |   86.85 |    85.64 |   94.11 |   86.85 | ...18-929,932,939 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.35 |    78.94 |     100 |   90.35 | ...52-553,576-577 
  ...d-contacts.ts |   83.62 |    94.59 |     100 |   83.62 | 123,125-142       
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.46 |    75.19 |    93.1 |   88.46 | ...2037,2082-2083 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   89.58 |    79.16 |     100 |   89.58 | ...84,698-705,786 
  ...t-branches.ts |   75.43 |    66.66 |     100 |   75.43 | ...13-618,627-634 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    93.18 |     100 |     100 | 52,77,188         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...al-control.ts |   74.17 |    69.23 |     100 |   74.17 | ...18,220-226,231 
  ...management.ts |   87.47 |       85 |     100 |   87.47 | ...1733,1743-1748 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.04 |    72.99 |     100 |   75.04 | ...79-690,696-697 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.9 |    87.15 |     100 |    76.9 | ...29-354,360-394 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   76.92 |     67.1 |      80 |   76.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    81.02 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   91.85 |    89.31 |      97 |   91.85 |                   
  access-log.ts    |    98.7 |    97.18 |     100 |    98.7 | 118,189           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |   86.92 |     73.6 |     100 |   86.92 | ...68,785,848-857 
  fs-factory.ts    |     100 |    94.54 |     100 |     100 | 42,103,159        
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...list-cache.ts |   99.01 |    95.52 |     100 |   99.01 | 184-185           
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |       80 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.13 |    95.09 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |      95 |     87.5 |     100 |      95 | 182-188           
  ...on-archive.ts |   89.74 |    86.28 |   97.36 |   89.74 | ...82,909,937-938 
  ...ion-export.ts |     100 |    94.73 |     100 |     100 | 64                
  session-list.ts  |   95.86 |    93.39 |     100 |   95.86 | ...-848,1026-1030 
  telemetry.ts     |   99.07 |    97.46 |     100 |   99.07 | ...61,676,821-823 
 src/serve/voice   |    92.7 |    91.48 |   97.67 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |    90.9 |    87.96 |    91.3 |    90.9 |                   
  index.ts         |   90.41 |    87.29 |      90 |   90.41 | ...1505-1509,1512 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.69 |    89.52 |   98.06 |   92.69 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 106-120           
  ...killLoader.ts |   97.19 |    85.29 |     100 |   97.19 | 142,153-154       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   87.09 |    83.07 |     100 |   87.09 | ...35-340,345-350 
  ...omptLoader.ts |   79.55 |    88.29 |   83.33 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.77 |    92.15 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   92.14 |    92.42 |     100 |   92.14 | ...91-296,329-330 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |     86.8 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.77 |   94.73 |   88.28 | ...1362,1366-1373 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.09 |    79.16 |   77.77 |   94.09 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   73.33 |    75.65 |   68.47 |   73.33 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   74.45 |    72.14 |   69.44 |   74.45 | ...4188,4304-4310 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |   63.63 |      100 |   41.17 |   63.63 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   71.42 |     74.5 |    62.5 |   71.42 | ...10,337,404-409 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   58.76 |    66.66 |   51.06 |   58.76 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.21 |    70.73 |   57.69 |   60.21 | ...90,794,803,806 
  useAuth.ts       |   94.83 |       75 |     100 |   94.83 | ...33-234,253-259 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   83.72 |    83.71 |   90.02 |   83.72 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...or-command.ts |     100 |    95.65 |     100 |     100 | 104,182           
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...28-129,137-146 
  ...essCommand.ts |   68.06 |    54.05 |      75 |   68.06 | ...96-197,211-214 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   71.83 |    71.05 |   84.61 |   71.83 | ...83-616,627-628 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   70.16 |    84.61 |      95 |   70.16 | ...29-679,682-816 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   80.48 |       75 |     100 |   80.48 | 49-54,69-72,93-98 
  effort-utils.ts  |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |     100 |    96.49 |     100 |     100 | 139,192           
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   94.44 |    90.14 |     100 |   94.44 | ...13-214,241-251 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   85.02 |    82.53 |     100 |   85.02 | ...1089,1123-1128 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |    89.6 |       90 |     100 |    89.6 | ...72-176,212-219 
  ...oreCommand.ts |   90.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   92.92 |       85 |   66.66 |   92.92 | ...72-177,276-281 
 src/ui/components |   72.79 |    79.77 |   77.58 |   72.79 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   88.65 |    90.41 |     100 |   88.65 | ...84-286,300-302 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-76,88,143,157 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |   11.28 |      100 |       0 |   11.28 | 71-598            
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   81.27 |    69.23 |      50 |   81.27 | ...06,245,267-272 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.69 |    67.61 |     100 |   79.69 | ...17,520,523-529 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   84.26 |    82.94 |      80 |   84.26 | ...2215,2236,2332 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.58 |    95.06 |   46.15 |   95.58 | ...79,482-486,489 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   85.22 |    74.08 |     100 |   85.22 | ...1041,1097,1099 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |   16.66 |      100 |       0 |   16.66 | 14-56             
  ...onsDialog.tsx |    2.13 |      100 |       0 |    2.13 | 62-133,148-1004   
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |    8.57 |      100 |       0 |    8.57 | 24-55,58-134      
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |   21.42 |      100 |       0 |   21.42 | 13-39             
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.9 |    86.88 |     100 |    93.9 | ...20,282,302-304 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   95.62 |    87.09 |     100 |   95.62 | ...24-125,273-275 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   58.69 |    70.24 |    62.5 |   58.69 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |     100 |    81.81 |     100 |     100 | 82                
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |   45.51 |    70.53 |   60.86 |   45.51 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |    9.77 |      100 |       0 |    9.77 | 27-166            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...ackground-view |   85.34 |    84.91 |   92.98 |   85.34 |                   
  ...sksDialog.tsx |   81.87 |    82.77 |   85.71 |   81.87 | ...1853,1965-1971 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |    50.7 |    52.38 |   20.83 |    50.7 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.24 |      100 |       0 |    9.24 | 40-67,70-163      
 ...mponents/hooks |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.35 |    86.92 |   85.71 |   90.35 |                   
  ...orMessage.tsx |     100 |      100 |     100 |     100 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.11 |    95.91 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.63 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.06 |    86.32 |   93.75 |   93.06 | ...1037,1082-1084 
 ...ponents/shared |   86.29 |    82.41 |   94.17 |   86.29 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    87.05 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |    3.96 |      100 |       0 |    3.96 |                   
  ...gerDialog.tsx |    3.96 |      100 |       0 |    3.96 | 79-137,140-681    
 ...ents/subagents |   30.87 |        0 |       0 |   30.87 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   10.95 |      100 |       0 |   10.95 | ...1,56-57,60-102 
 ...bagents/create |    9.13 |      100 |       0 |    9.13 |                   
  ...ionWizard.tsx |    7.28 |      100 |       0 |    7.28 | 34-299            
  ...rSelector.tsx |   14.75 |      100 |       0 |   14.75 | 26-85             
  ...onSummary.tsx |    4.26 |      100 |       0 |    4.26 | 27-331            
  ...tionInput.tsx |    8.63 |      100 |       0 |    8.63 | 23-177            
  ...dSelector.tsx |   33.33 |      100 |       0 |   33.33 | 20-21,26-27,36-63 
  ...nSelector.tsx |    37.5 |      100 |       0 |    37.5 | 20-21,26-27,36-58 
  ...EntryStep.tsx |   12.76 |      100 |       0 |   12.76 | 34-78             
  ToolSelector.tsx |    4.16 |      100 |       0 |    4.16 | 31-253            
 ...bagents/manage |    21.6 |    59.52 |   27.27 |    21.6 |                   
  ...ctionStep.tsx |   10.25 |      100 |       0 |   10.25 | 21-103            
  ...eleteStep.tsx |   20.93 |      100 |       0 |   20.93 | 23-62             
  ...tEditStep.tsx |   25.53 |      100 |       0 |   25.53 | ...2,37-38,51-124 
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |   13.72 |      100 |       0 |   13.72 | 18-73             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   86.01 |    81.62 |   86.48 |   86.01 |                   
  ...ewContext.tsx |   87.56 |       80 |      75 |   87.56 | ...37-240,246-256 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 235-236           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |   93.33 |    85.71 |   66.66 |   93.33 |                   
  ...ngsManager.ts |   93.33 |    85.71 |   66.66 |   93.33 | 49,63-64          
 src/ui/hooks      |   85.97 |    83.88 |   87.78 |   85.97 |                   
  ...dProcessor.ts |   85.53 |     85.2 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...87-288,293-294 
  ...dProcessor.ts |   86.79 |    71.86 |   83.33 |   86.79 | ...1529,1558-1562 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...ng-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      52 |    63.63 |     100 |      52 | ...59,67-70,76-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.53 |    83.01 |     100 |   95.53 | ...64-165,289-292 
  ...ompletion.tsx |   97.09 |    87.09 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |   11.62 |      100 |       0 |   11.62 | 44-87             
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   87.32 |    84.15 |   77.77 |   87.32 | ...5718-5720,5722 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.38 |    98.85 |     100 |   98.38 | 141-144           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.4 |     100 |     100 | 175,262           
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |   85.29 |    80.28 |    92.3 |   85.29 | ...36,351-361,441 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.13 |     86.9 |     100 |   89.13 | ...61-463,496-506 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.34 |    77.14 |     100 |   95.34 | 124-125,227-232   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.19 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.32 |    93.93 |     100 |   97.32 | ...18-422,518-525 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |    79.2 |    35.29 |     100 |    79.2 | ...15-116,120-121 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |   91.25 |    89.47 |     100 |   91.25 |                   
  ...AppLayout.tsx |   90.99 |     87.5 |     100 |   90.99 | 61-63,111-116,152 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   93.56 |    86.13 |     100 |   93.56 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   93.81 |     92.1 |     100 |   93.81 | ...1,45-46,99-100 
  ...tion-state.ts |     100 |      100 |     100 |     100 |                   
  ...ction-text.ts |   93.85 |    93.44 |     100 |   93.85 | 30-34,130-131     
  ...selection.tsx |   91.88 |    78.57 |     100 |   91.88 | ...16-417,446-447 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   87.68 |    85.72 |   96.05 |   87.68 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   80.07 |     75.6 |     100 |   80.07 | ...70,274,332-333 
  ...wnDisplay.tsx |   92.87 |     93.5 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   93.63 |    81.77 |   95.23 |   93.63 | ...47-750,803-808 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |    52.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.46 |    92.38 |     100 |   98.46 | 121,149-150,356   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.21 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.42 |       95 |     100 |   91.42 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |   96.07 |    97.14 |     100 |   96.07 | 104-107           
  ...mage-parts.ts |   97.75 |    94.59 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   91.33 |    79.03 |     100 |   91.33 | ...73,273,277-278 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   83.24 |       80 |     100 |   83.24 | ...02-624,755-756 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   95.19 |      100 |   88.88 |   95.19 | 121-126           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...ize-reflow.ts |     100 |     92.3 |     100 |     100 | 57,62,209,217,347 
  ...wOptimizer.ts |     100 |    94.11 |     100 |     100 | 33,76             
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   98.71 |    95.72 |     100 |   98.71 | 292-293,478-479   
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   90.42 |    92.85 |     100 |   90.42 | ...06-207,240-241 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  windowTitle.ts   |   96.55 |    94.73 |     100 |   96.55 | 56-57             
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |     60.1 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    51.35 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.27 |    79.64 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |        0 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.97 |    87.32 |   92.73 |   81.97 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |      100 |     100 |     100 |                   
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |    89.65 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...64,381-382,427 
  ...projection.ts |   95.27 |    95.58 |     100 |   95.27 | 140-145           
  jsonc-editor.ts  |   93.18 |    92.66 |     100 |   93.18 | ...80-381,384-385 
  languageUtils.ts |   98.88 |    97.01 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   86.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.14 |    91.79 |     100 |   95.14 | ...54-455,553,566 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.52 |    57.35 |   76.92 |   45.52 | ...1040,1052-1075 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       90 |     100 |     100 | 23                
  systemInfo.ts    |   95.09 |    90.27 |     100 |   95.09 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iagnostics.ts |    95.8 |     87.5 |   93.75 |    95.8 | ...03,277-278,289 
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   93.51 |    90.95 |   96.96 |   93.51 |                   
  cleanup.ts       |   92.59 |    93.75 |     100 |   92.59 | ...02-205,209-211 
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |      93 |    88.34 |      95 |      93 | ...57-359,411-415 
  throttledOnce.ts |   95.95 |    93.93 |     100 |   95.95 | 77-78,153-154     
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   88.09 |    86.68 |   89.58 |   88.09 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.55 |     84.7 |    94.9 |   90.55 |                   
  ...transcript.ts |   88.49 |    84.09 |     100 |   88.49 | ...32,640,646-650 
  ...ent-resume.ts |   85.59 |    77.75 |   83.33 |   85.59 | ...1794-1798,1801 
  ...ound-tasks.ts |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
  worktree-pin.ts  |     100 |    88.23 |     100 |     100 | 78,99             
 src/agents/arena  |   76.94 |    68.22 |   78.94 |   76.94 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.89 |     65.2 |   78.57 |   75.89 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   91.13 |    86.87 |   89.86 |   91.13 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   84.45 |    76.43 |   77.19 |   84.45 | ...2344,2390-2392 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.38 |      100 |    92.3 |   98.38 | 85-86             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |    92.3 |    75.86 |     100 |    92.3 | ...49-150,190-192 
  ...chestrator.ts |   93.43 |    91.19 |   90.47 |   93.43 | ...2145,2194-2197 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1750,1756-1757 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   82.71 |    84.51 |   88.97 |   82.71 |                   
  TeamManager.ts   |    73.6 |    80.82 |   79.62 |    73.6 | ...1706,1729-1730 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   91.71 |    94.54 |      95 |   91.71 | ...18-319,355-365 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.35 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |       85 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.16 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.29 |    86.87 |   75.56 |   84.29 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |    83.6 |     86.6 |   74.07 |    83.6 | ...8880,8884-8885 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.35 |    88.16 |   93.05 |   92.35 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   92.46 |    87.73 |   91.76 |   92.46 | ...4146,4244-4245 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   89.77 |     84.7 |   94.73 |   89.77 | ...6422,6450-6466 
  geminiChat.ts    |    94.7 |    90.13 |   95.53 |    94.7 | ...5059,5107-5108 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    91.89 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 83-87             
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   99.19 |    94.48 |     100 |   99.19 | 682-683,752       
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.33 |    88.12 |   96.15 |   96.33 |                   
  ...tGenerator.ts |   97.24 |    86.72 |   94.87 |   97.24 | ...1436,1465,1476 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1329,1550-1552 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   96.12 |     91.3 |    90.9 |   96.12 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   96.06 |    90.75 |   90.47 |   96.06 | ...1309-1310,1338 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |    91.9 |    90.54 |   95.76 |    91.9 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |    91.3 |    89.49 |   96.87 |    91.3 | ...1942,2111-2126 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   68.25 |    82.35 |      50 |   68.25 | 44-53,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.27 |     90.9 |     100 |   95.27 | ...1434,1442,1541 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.39 |    92.28 |    98.5 |   97.39 |                   
  dashscope.ts     |   98.36 |    95.08 |   96.42 |   98.36 | ...08-709,851-852 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.18 |    97.05 |     100 |   99.18 | 208               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   87.71 |    84.66 |   92.57 |   87.71 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.94 |     86.5 |   97.91 |   90.94 | ...1230-1236,1280 
  ...ionManager.ts |   83.89 |    82.86 |   81.72 |   83.89 | ...2832,2861-2862 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.71 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.48 |    82.71 |     100 |   90.48 | ...4,994-995,1005 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 ...ent-plugins-v1 |   84.94 |    79.51 |     100 |   84.94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  manifest.ts      |   81.87 |    84.48 |     100 |   81.87 | ...55-156,161-174 
  mcp.ts           |   84.98 |    79.56 |     100 |   84.98 | ...88-389,419-420 
  paths.ts         |     100 |    94.44 |     100 |     100 | 59                
  skills.ts        |   82.31 |    63.88 |     100 |   82.31 | ...38-141,150-151 
 src/followup      |   81.45 |    79.25 |   84.21 |   81.45 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   75.98 |    67.22 |   58.33 |   75.98 | ...42-743,750-751 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   92.96 |    89.06 |   94.34 |   92.96 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.34 |    87.06 |    97.5 |   88.34 | ...1162,1185-1188 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...87,190,194-196 
  ...ersistence.ts |   87.29 |    85.71 |    87.5 |   87.29 | ...53-154,185-190 
  goal-protocol.ts |   96.87 |    95.65 |     100 |   96.87 | 200-201           
  goal-reducer.ts  |      95 |    92.34 |   97.05 |      95 | ...43,520,538-539 
  goal-runtime.ts  |   96.89 |    89.95 |   95.74 |   96.89 | ...1315-1316,1437 
  goal-tools.ts    |   98.38 |    94.05 |   95.45 |   98.38 | ...98-199,300-301 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.35 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.09 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.83 |    83.93 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    86.79 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.62 |   91.13 |   92.55 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.16 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.63 |    88.88 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |    92.72 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.09 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.6 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    74.04 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 81-83,86-88,90-93 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   90.38 |    86.01 |   96.77 |   90.38 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   98.48 |    87.28 |     100 |   98.48 | 81-82,105,474-475 
  branch-points.ts |     100 |    95.23 |     100 |     100 | ...20,211,224,327 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   90.96 |    86.66 |    92.5 |   90.96 | ...2439,2466-2467 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.17 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |   74.75 |    70.76 |   96.07 |   74.75 | ...2296,2325-2326 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.88 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |   97.22 |    90.99 |     100 |   97.22 | ...55-456,609-610 
  ...ttachments.ts |   97.74 |     90.9 |     100 |   97.74 | 298-308,646       
  ...pi-history.ts |   98.94 |    88.88 |     100 |   98.94 | 43                
  ...ersistence.ts |   91.66 |    80.75 |     100 |   91.66 | ...1060-1061,1089 
  ...tory-state.ts |     100 |    95.23 |     100 |     100 | 31                
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...n-registry.ts |   98.73 |    96.29 |     100 |   98.73 | 584,638-639,692   
  ...ken-counts.ts |     100 |       96 |     100 |     100 | 58                
  ...ipt-reader.ts |   93.71 |    91.05 |   97.77 |   93.71 | ...2755-2756,2833 
  ...turn-state.ts |   94.11 |     90.9 |   91.66 |   94.11 | 108-112,129-130   
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   89.31 |    85.86 |   96.05 |   89.31 | ...2642,2656-2676 
  sessionTitle.ts  |   95.75 |    77.41 |     100 |   95.75 | ...53-256,287-288 
  ...ionService.ts |   84.43 |    78.45 |   97.18 |   84.43 | ...2496,2502-2507 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    94.11 |     100 |     100 | 118               
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...ite-origin.ts |     100 |    93.33 |     100 |     100 | 32                
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   88.36 |     87.7 |     100 |   88.36 | ...48-449,465-466 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.92 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |    87.69 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   82.41 |    84.65 |   85.74 |   82.41 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   76.92 |    75.71 |   73.68 |   76.92 | ...88,395-397,413 
  ...attributes.ts |   96.98 |    91.37 |     100 |   96.98 | ...47-348,366-367 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.12 |    96.03 |      95 |   99.12 | 150,379-380       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.73 |    78.01 |   66.66 |   60.73 | ...1507,1524-1544 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   93.89 |    86.32 |      75 |   93.89 | ...39,489-490,506 
  sdk.ts           |    82.7 |     90.9 |   66.66 |    82.7 | ...00-204,242-264 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ion-events.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   91.17 |    88.72 |    97.5 |   91.17 | ...1920,1949-1952 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   83.09 |     95.1 |   86.36 |   83.09 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.38 |    98.61 |   83.33 |   96.38 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.29 |    85.08 |   88.82 |   86.29 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.77 |   81.25 |   82.76 | ...45-746,865-915 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   80.03 |    86.58 |   89.47 |   80.03 | ...2272,2276-2279 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.71 |    77.08 |   81.25 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.96 |    84.29 |      93 |   78.96 | ...5036,5111-5112 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   78.22 |    84.21 |   83.33 |   78.22 | ...66,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   93.11 |    92.53 |   91.66 |   93.11 | ...76-577,593-599 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   86.72 |    84.92 |   88.88 |   86.72 | ...25-828,865-900 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   86.91 |    87.59 |   88.49 |   86.91 |                   
  agent.ts         |   85.49 |    86.49 |   86.02 |   85.49 | ...4244,4278-4288 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   86.64 |    84.81 |      75 |   86.64 |                   
  workflow.ts      |   86.64 |    84.81 |      75 |   86.64 | ...95,540,542-543 
 src/utils         |   93.09 |     89.8 |    96.8 |   93.09 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |      95 |     92.7 |     100 |      95 | ...49-550,657-661 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   88.92 |    93.58 |   66.66 |   88.92 | ...92,394,410-411 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.97 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.64 |    82.85 |   93.75 |   92.64 | ...47,655,660-667 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.83 |    82.35 |    87.5 |   78.83 | ...22-123,164-215 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.08 |    93.33 |     100 |   95.08 | ...62-166,234-238 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.41 |    93.61 |     100 |   95.41 | ...27-328,370-373 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   90.88 |    90.54 |     100 |   90.88 | ...25-626,628-630 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  ...s-liveness.ts |     100 |    93.47 |     100 |     100 | 62,72,108         
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |   97.77 |    91.48 |     100 |   97.77 | 172-173           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |       90 |     100 |     100 | 95                
  ...orageUtils.ts |   96.21 |    85.21 |     100 |   96.21 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.26 |    88.58 |     100 |   86.26 | ...2295,2302-2306 
  ...lAstParser.ts |    98.3 |    91.59 |     100 |    98.3 | ...1340-1342,1352 
  ...ContextEnv.ts |     100 |    94.73 |     100 |     100 | 76,111            
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |    98.1 |     92.3 |   93.33 |    98.1 | ...34-235,237-241 
  ...iagnostics.ts |   99.06 |     97.7 |   91.66 |   99.06 | 132-133,204       
  ...-retention.ts |     100 |    95.83 |     100 |     100 | 116               
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       25 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.39 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |   87.55 |    86.13 |     100 |   87.55 | ...78-482,512-527 
  truncation.ts    |   90.61 |    90.51 |     100 |   90.61 | ...53-461,498-504 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.39 |    89.47 |     100 |   95.39 | ...16-317,321-322 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

For detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run.

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship — CI landed green after the review. ✅

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not explored to full depth (tool budget reached): "agent 4": none — no checks were cut short..

中文说明

未探索到全部深度(达到工具调用预算):"agent 4"none — no checks were cut short.

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +551 to +554
const model =
typeof input.modelId === 'string' && input.modelId.trim() !== ''
? input.modelId.trim()
: undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R1-9: With review.attribution: false the visible footer is withheld, but this new marker field still publishes the exact model id in the posted review body — violating the setting's documented contract ("whether the posted review names its model", review-settings.ts; user docs: "Disable to post reviews without AI attribution"). composeReview calls ledgerMarkerFor(input, result.cappedBy) without attribution (line 484), and this extraction reads input.modelId unconditionally. Pre-PR markers carried findings/round/sha and no model identity, so this diff newly leaks exactly the information the setting removes, into a write this module calls public and irreversible. The module's own standard indicts it: forged footers are stripped from inline comments even with attribution off (submit.ts:154-156). — Failure scenario: an operator sets review.attribution: false (reviews post under a shared bot identity) → the footer is suppressed everywhere visible, but anyone with API access (gh api repos/…/pulls/…/reviews) or the raw-body edit view reads the exact model id out of the posted <!-- qwen-review-ledger {…,"model":"<exact model id>"} -->.

Witness (probe, both arms):

attribution=false →
  markerLine: <!-- qwen-review-ledger {"v":1,"round":1,…,"sha":"deadbeef00112233","model":"test-model"} -->
  footerPresent: false, rawModelIdPresent: true
attribution threaded into ledgerMarkerFor →
  no "model" key, rawModelIdPresent: false, sha intact

Suggested fix (verified by the probe flip): thread attribution into ledgerMarkerFor and withhold model when it is off — the anchor then degrades to the skill's already-specified "absent model → mismatch → full-range" fail-safe; alternatively, document a marker exemption in the setting contract and the DESIGN bullet (today neither says so):

// compose-review.ts:484
ledgerMarkerFor(input, result.cappedBy, attribution)

// ledgerMarkerFor
const model =
  attribution &&
  typeof input.modelId === 'string' && input.modelId.trim() !== ''
    ? input.modelId.trim()
    : undefined;
中文说明

review.attribution: false 时,可见的 footer 被正确扣下,但新增的 marker model 字段仍会把确切的模型 id 发布到已提交的 review 正文中——违反了该设置的文档契约("发布的 review 是否注明其模型",review-settings.ts;用户文档:"禁用以发布不带 AI 署名的审查")。composeReview 调用 ledgerMarkerFor(input, result.cappedBy) 时未传 attribution(第 484 行),此处无条件读取 input.modelId。本 PR 之前的 marker 只携带 findings/round/sha、不含模型身份,因此本 diff 新泄露了该设置恰恰要移除的信息,且写入是本模块所称的"公开、不可逆"的。模块自身的标准也印证这一点:即使 attribution 关闭,伪造的 footer 也会从行内评论中被剥掉(submit.ts:154-156)。 — 失败场景:运维者设置 review.attribution: false(以共享机器人身份发布审查)→ 所有可见处的 footer 都被抑制,但任何有 API 访问权限的人(gh api repos/…/pulls/…/reviews)或原始正文编辑视图都能从已发布的 <!-- qwen-review-ledger {…,"model":"<确切模型 id>"} --> 中读出确切的模型 id。

见证(probe,双向验证):attribution=false → marker 行包含 "model":"test-model",footerPresent: false,rawModelIdPresent: true;将 attribution 传入 ledgerMarkerFor 后 → 无 "model" 键,rawModelIdPresent: false,sha 不受影响。

建议修复(已由 probe 翻转验证):将 attribution 传入 ledgerMarkerFor,关闭时扣下 model——anchor 随即退化为 skill 已规定的"模型缺失 → 不匹配 → 全量审查"的 fail-safe;或者在设置契约与 DESIGN 条目中明确声明 marker 豁免(目前两处都未说明)。

— qwen3.8-max via Qwen Code /review (v0.21.12)

- **Incremental review check** (high effort only — neither low nor medium consults or updates the cache): if `.qwen/review-cache/pr-<n>.json` exists, read it **in the same response as the fetch report** — both are `read_file`, genuinely parallel — for `lastCommitSha` and `lastModelId`. Compare to `fetchedSha` from the fetch report and the current model ID (`{{model}}`):
- If SHAs differ → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.
- If SHAs differ **and** model matches → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.
- If SHAs differ **but** model differs → continue with the worktree, but the scope is the **full diff**, never `<lastCommitSha>..HEAD`: "clean up to `lastCommitSha`" is {cached_model}'s verdict, and an incremental range scoped to another model's anchor leaves everything before it reviewed by no run of `{{model}}` — permanently, because this round's own cache write would re-anchor past it. Inform: "Previous round was reviewed by {cached_model}. Running full review with {{model}}." Still read the cache's `findings` ledger and owe each entry its Step 6 ruling — the work list carries across models (every entry is re-asserted against the code); only the anchor does not.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-1: The two-anchor fallback is asymmetric: when the side file's preferred anchor fails the model gate, the cache's same-model anchor is an explicit fallback (the recovery paragraph's parenthetical), but when the CACHE's anchor fails the model gate, the side file's same-model anchor is never consulted — the recovery paragraph only opens "when the cache is absent or its lastCommitSha was rebased away". — Failure scenario: a machine that ran the last review (cache present) switches models between rounds; lastCommitSha differs from fetchedSha and lastModelId differs from the running model, while the PR's last posted review (e.g. posted by CI running the CURRENT model) carries a same-model anchor in the side file → this branch mandates the full diff and the recovery paragraph's entry condition excludes this case, so the valid same-model anchor is never read: one wasted full review per model switch on cache-owning machines — exactly the cost the recovered-anchor feature exists to avoid (fail-safe direction; self-heals after Step 8 rewrites the cache).

Suggested fix: in this branch, before falling back to the full diff, consult the side file's anchor under the same gate as the reverse-direction fallback (valid sha, ancestry checks, model == {{model}}) and scope to it when it passes.

中文说明

双 anchor 回退不对称:当旁路文件中被优先的 anchor 未通过模型闸门时,缓存中同模型的 anchor 是显式回退(恢复段落的括注);但当缓存的 anchor 未通过模型闸门时,旁路文件中同模型的 anchor 却永远不会被参考——恢复段落的进入条件是"缓存不存在或其 lastCommitSha 已被 rebase 掉"。 — 失败场景:运行过上一轮审查的机器(缓存存在)在两轮之间切换了模型;lastCommitShafetchedSha 不同且 lastModelId 与当前模型不同,而 PR 最近一次发布的审查(例如由运行当前模型的 CI 发布)在旁路文件中携带同模型的 anchor → 本分支强制全量 diff,且恢复段落的进入条件排除了这种情况,于是有效的同模型 anchor 永远不会被读取:缓存存在的机器上每次切换模型都浪费一次全量审查——恰恰是恢复 anchor 特性本要避免的成本(方向 fail-safe;Step 8 重写缓存后自愈)。

建议修复:在该分支中,退回全量 diff 之前,先以与反向回退相同的闸门(有效 sha、祖先检查、model == {{model}})参考旁路文件的 anchor,通过则按其划分范围。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +1162 to +1163
sha: 'abc1234def56789',
model: 'qwen3.7-max',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-2: The recovery seam this PR's payoff depends on — posted marker → latestOwnLedger → the prev-ledger side file Step 1's gate reads — is pinned for sha only by the existing test 'carries the anchor sha through the recovery seam intact' (line 1039, whose comment exists precisely for this hazard); the new model field rides the same seam untested. — Failure scenario (mutation probe, executed): projecting latestOwnLedger's return onto known fields without model left all 380 existing tests green → in production the side file always lacks model, Step 1's gate reads every recovered anchor as absent-model mismatch, and incremental scoping from recovered markers silently never fires — every fresh-environment review degrades to full-range with no visible error (fail-safe direction, but the feature ships inert).

Suggested fix: add model: 'qwen3.7-max' to the anchored ledger in 'carries the anchor sha through the recovery seam intact' (line 1039) so the toEqual pin covers the new field beside the sha.

中文说明

本 PR 收益所依赖的恢复接缝——已发布 marker → latestOwnLedger → Step 1 闸门读取的 prev-ledger 旁路文件——目前只由现有测试 'carries the anchor sha through the recovery seam intact'(第 1039 行,其注释正是为这一风险而写)为 sha 钉住;新增的 model 字段经过同一接缝却未被测试。 — 失败场景(已执行的突变 probe):将 latestOwnLedger 的返回值投影为不含 model 的已知字段后,现有 380 个测试全部保持绿色 → 生产中旁路文件将永远缺少 model,Step 1 的闸门会把每个恢复的 anchor 判为"模型缺失 = 不匹配",从已发布 marker 恢复的增量范围划分将静默地永不生效——所有全新环境的审查都退化为全量,且没有任何可见错误(方向上是 fail-safe,但功能等于带着失效上线)。

建议修复:在 'carries the anchor sha through the recovery seam intact'(第 1039 行)的 anchored ledger 中加入 model: 'qwen3.7-max',使 toEqual 钉住新字段与 sha 并列。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +551 to +554
const model =
typeof input.modelId === 'string' && input.modelId.trim() !== ''
? input.modelId.trim()
: undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-3: The attribution-off branch of this new guard — the branch its own comment says exists ("the boundary validation of modelId runs only when attribution is on, and the marker rides either way") — is exercised by no test; a mutation deleting the typeof check survives the whole suite. — Failure scenario (mutation probe, executed): deleting the typeof check left 380/380 tests green; in production, an operator runs with review.attribution: false and the state JSON omits modelId (legal — attribution off skips the modelId is required validation) on a clean round with fetchedSha set → input.modelId.trim() throws inside ledgerMarkerFor's try → returns null → the ENTIRE marker is silently dropped, not just the model: the round counter resets (the next round re-issues ids the PR already carries) and the findings work list is lost. Every marker-path test passes a string modelId, and the attribution-off tests use a plan with no prNumber, so this guard is never reached.

Suggested fix: add a marker-path test with attribution off and missing modelId — a covered plan with prNumber + fetchedSha, compose with attribution false, then assert parseLedger(r.body)!.sha is the fetched sha and ledger.model is toBeUndefined(), pinning both that the marker survives and that the model is withheld. (Pairs naturally with the R1-9 fix.)

中文说明

新增守卫的 attribution 关闭分支——其自身注释声称存在的分支("modelId 的边界校验只在 attribution 开启时运行,而 marker 无论如何都会挂载")——没有任何测试覆盖;删除 typeof 检查的突变体能在整个测试套件中存活。 — 失败场景(已执行的突变 probe):删除 typeof 检查后 380/380 测试仍全绿;生产环境中,运维者以 review.attribution: false 运行,且 state JSON 省略了 modelId(合法——attribution 关闭时跳过 modelId is required 校验),此时是带有 fetchedSha 的干净轮次 → input.modelId.trim()ledgerMarkerFor 的 try 内抛错 → 返回 null → 整个 marker 被静默丢弃,而不仅仅是 model:轮次计数器重置(下一轮会重新签发本 PR 已携带的 id),findings 工作清单丢失。所有 marker 路径的测试都传入了字符串 modelId,而 attribution 关闭的测试使用的 plan 没有 prNumber,因此永远不会到达这个守卫。

建议修复:增加一个 attribution 关闭且缺失 modelId 的 marker 路径测试——使用带 prNumber + fetchedSha 的 covered plan,以 attribution false 组装,然后断言 parseLedger(r.body)!.sha 为 fetched sha 且 ledger.modeltoBeUndefined(),同时钉住"marker 存活"与"model 被扣下"两点。(与 R1-9 的修复天然配套。)

— qwen3.8-max via Qwen Code /review (v0.21.12)

- **Own-account, latest round only.** The ledger claims "these are the findings the previous /review stood behind", and only this account's reviews can make that claim — another user's marker is data about _their_ tooling. Each posted round embeds a fresh full copy, so the newest marker is the whole state.
- **Data, not authority.** Every recovered entry is owed a Step 6 ruling against the code — the ledger routes work, it never rules. A tampered or stale marker therefore costs a few wasted rulings, not a wrong verdict, which is why parsing is fail-quiet and the round number feeds `compose-review` from a CLI-written side file rather than a model's memory.
- **Medium reads, high writes.** Recovering the ledger is free (the reviews were already fetched), so the default-effort re-review finally opens like a round-2 comment; the cache write and the posting that carries the marker keep their existing effort gates untouched.
- **The anchor names its model.** Incremental scoping is a same-model contract — "clean up to `sha`" is one model's verdict, and the cache path has always enforced that through `lastModelId` (a same-SHA re-run under a different model gets a full second opinion, not a skip). The marker's anchor shipped bare, so the recovery path had no way to honour the contract: a round run under model B that recovered model A's anchor would scope `sha..HEAD` past code B never reviewed — permanently, since each clean round re-anchors past the last. The marker now carries `model` beside `sha`, riding and falling with the anchor (withheld on fail-closed and truncated rounds alike, dropped by the parser when the sha beside it did not survive), and Step 1's recovered-anchor gate requires it to match the running model — absent, on markers from before the field, counts as a mismatch: the work list still carries (rulings re-assert against the code, so they cross models safely), only the anchor does not.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-4: This added design bullet overstates pre-change behavior: "the cache path has always enforced that through lastModelId" — but the pre-change cache path enforced the same-model contract only in the same-SHA (skip) case; its SHAs-differ branch had no model condition until this very PR adds one (verified via git show at the merge base; the diff's own deleted SKILL.md line proves it). — Failure scenario: a maintainer relying on this bullet would believe (a) the only pre-change hole was the marker path and (b) legacy cache anchors already satisfy the same-model contract → the exact inference that would let a tainted legacy cache anchor keep scoping incremental rounds past code the current model never reviewed, since unlike bare-model markers (which the new absent=mismatch rule heals via full review) nothing heals a tainted cache entry.

Suggested fix: reword to say the cache path paired its anchor with lastModelId but enforced the contract only in the same-SHA skip case, and that this change extends the enforcement to the differ-SHA incremental branch and to the recovered-anchor path.

中文说明

新增的设计条目夸大了改动前的行为:"缓存路径一直通过 lastModelId 强制执行该契约"——但改动前的缓存路径只在同 SHA(跳过)情形下强制执行同模型契约;其 SHA 不同的分支在本 PR 之前没有任何模型条件(已用 git show 在 merge base 上验证;diff 自己删除的 SKILL.md 行即为证据)。 — 失败场景:依赖此条目的维护者会认为 (a) 改动前唯一的漏洞是 marker 路径,且 (b) 遗留缓存 anchor 已满足同模型契约 → 恰恰是让被污染的遗留缓存 anchor 继续把增量轮次的范围划到当前模型从未审查过的代码的推理;因为不像缺少模型的 marker(新的"缺失=不匹配"规则会通过全量审查自愈),被污染的缓存条目没有任何自愈机制。

建议修复:改为"缓存路径将其 anchor 与 lastModelId 配对,但此前仅在同 SHA 跳过情形下强制执行契约;本改动将强制执行扩展到 SHA 不同的增量分支与恢复 anchor 路径"。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +78 to +80
* beside it did not survive — a model naming no range qualifies nothing.
*/
model?: string;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-5: Test-efficacy probe (harness validated): reverting this model?: string declaration hunk on its own left every affected test green — vitest transpiles without type-checking, so if the declaration were deleted or renamed, the entire unit suite still passes; the dangling ledger.model/payload.model references are caught only by the separate tsc typecheck step. — Concrete cost: a refactor that drops or renames the field turns no test red — only npm run typecheck notices. (Mitigating: the field's runtime read/write hunks — cap constant, serializer, parser — were all killed by probes, and ledger.test.ts gates the full-file revert.)

Suggested fix: confirm typecheck is relied upon as the gate for the declaration hunk (it runs in CI), or add a type-level pin so its removal reddens a test.

中文说明

测试有效性 probe(harness 已验证):单独回退这个 model?: string 声明 hunk 后,所有受影响的测试仍为绿色——vitest 转译时不做类型检查,因此即使删除或重命名该声明,整个单元测试套件依然通过;悬空的 ledger.model/payload.model 引用只能由独立的 tsc typecheck 步骤捕获。 — 具体代价:删除或重命名该字段的重构不会让任何测试变红——只有 npm run typecheck 能发现。(缓解因素:该字段的运行时读写 hunk——上限常量、序列化器、解析器——均被 probe 杀死,且 ledger.test.ts 对整文件回退是有效的。)

建议修复:确认 typecheck 被作为该声明 hunk 的闸门(CI 中有运行),或增加类型层面的钉住,使其被移除时测试变红。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined — with the confirmation this finding asked for recorded here.

The disposition: npm run typecheck (tsc, run in CI and re-run in this round) IS the relied-upon gate for the model?: string declaration hunk. Vitest transpiles without type-checking by design, so a type declaration's removal or rename reddens no unit test and is caught by the separate typecheck step — that is the intended division of labor, not a gap to close with a type-level pin. The finding's own mitigation confirms the behavioral surface is already pinned: the runtime read/write hunks (cap constant, serializer, parser) were all killed by its probes, and ledger.test.ts gates the full-file revert. Adding a compile-time assertion so a field deletion reddens a test too would duplicate what tsc already catches in the same CI run — defense a senior engineer would call unnecessary, and this PR's diff budget is better spent on findings with live failure modes. No code change this round.

中文说明

拒绝处理——并按本条发现的要求,在此记录确认结论。

结论:npm run typecheck(tsc,CI 中运行,本轮也已重新运行)就是 model?: string 声明 hunk 所依赖的闸门。Vitest 按设计转译时不做类型检查,因此删除或重命名一个类型声明不会让任何单元测试变红,而是由独立的 typecheck 步骤捕获——这是预期的职责分工,而不是需要用类型层面钉住来弥补的缺口。本条发现自身的缓解说明也确认行为面已被钉住:运行时读写 hunk(上限常量、序列化器、解析器)均被其 probe 杀死,且 ledger.test.ts 对整文件回退是有效的。再增加一个编译期断言、让删除字段也能让测试变红,只是重复 tsc 在同一次 CI 运行中已经捕获的东西——属于资深工程师会认为不必要的防御,本 PR 的 diff 预算更适合花在存在真实失败模式的发现上。本轮不做代码改动。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Request changes to Comment: self-PR; CI still running. Partially reviewed — gaps disclosed. 2 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here.

Not reviewed: build-and-test — packages/core test suite timed out locally.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI.

中文说明

⚠️ 已从请求修改降级为评论:self-PR; CI still running。 仅完成部分审查,审查缺口已披露。 2 条建议级发现无法锚定到改动行,已丢弃;此处无需进一步处理。

未审查:build-and-test — packages/core test suite timed out locally。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI。

— gpt-5.6-sol via Qwen Code /review (v0.21.11)

Comment on lines +159 to +160
const model = ledger.model?.trim();
if (model) payload.model = model.slice(0, LEDGER_MAX_MODEL);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R1-1: Truncating the certifying model ID creates identity collisions in the recovered-anchor gate — Failure scenario: a model ID longer than 64 characters is serialized as its prefix; a distinct model whose full ID equals that prefix then compares equal and scopes to sha..HEAD, skipping code it never reviewed.

Witness:

PR code: {"longLength":75,"recoveredLength":64,"gateWouldMatch":true}
With truncation removed from both serializer and parser: {"recoveredLength":75,"gateWouldMatchPrefix":false}

Preserve the complete model identity. If it cannot fit, withhold the sha/model pair, or store and compare a collision-resistant digest of the complete identity.

中文说明

**问题:**认证模型 ID 被截断后会产生身份碰撞。

**失败场景:**长度超过 64 字符的模型 ID 会被序列化为前缀;另一个完整 ID 恰好等于该前缀的模型随后会被错误判断为同一模型,并使用 sha..HEAD,跳过它从未审查过的代码。

**建议修复:**保留完整模型身份;若无法完整存储,则同时扣下 shamodel,或保存完整身份的抗碰撞摘要。

— gpt-5.6-sol via Qwen Code /review (v0.21.11)

Comment on lines +551 to +553
const model =
typeof input.modelId === 'string' && input.modelId.trim() !== ''
? input.modelId.trim()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R1-2: The certifying model is accepted from model-authored compose state instead of trusted runtime provenance — Failure scenario: a review running under model B can write model A's ID into compose state; the posted ledger then certifies the anchor as A, so a later real A run accepts sha..HEAD and skips earlier code A never reviewed.

Witness: not run — the defect is the absence of trusted runtime provenance at the JSON boundary; the caller-controlled field flows directly into the certificate without an independent value to compare against.

Inject the current model identity at a trusted CLI/session boundary, or compare the supplied value against that trusted identity and fail closed on disagreement.

中文说明

**问题:**认证模型来自模型自身编写的 compose state,而非可信运行时来源。

**失败场景:**实际由模型 B 执行的审查可以把 modelId 写成模型 A;ledger 会把 anchor 认证为 A,之后真正的 A 会接受 sha..HEAD,跳过 A 从未审查过的早期代码。

**建议修复:**在可信 CLI/session 边界注入当前模型身份,或将输入值与可信身份比较并在不一致时 fail closed。

— gpt-5.6-sol via Qwen Code /review (v0.21.11)

Comment on lines +551 to +553
const model =
typeof input.modelId === 'string' && input.modelId.trim() !== ''
? input.modelId.trim()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R1-3: A bare model ID is not a unique resolved-model identity across providers and endpoints — Failure scenario: two provider or endpoint configurations can expose the same model ID while resolving to different underlying models; the second configuration accepts the first configuration's anchor and skips code it never reviewed.

Witness: not run — a live two-provider setup was unavailable, but the repository's provider-aware identity code explicitly compares authType and baseUrl in addition to the model ID.

Persist and compare a stable resolved-model identity including the relevant auth type and provider or endpoint discriminator, and use the same identity for cache and posted-ledger gates.

中文说明

**问题:**裸模型 ID 无法在不同 provider 或 endpoint 间唯一标识解析后的模型。

**失败场景:**两个 provider/endpoint 可以暴露相同模型 ID、但实际解析为不同模型;第二个配置会接受第一个配置的 anchor,并跳过它从未审查过的代码。

**建议修复:**持久化并比较包含 authType 以及 provider/endpoint 区分信息的稳定解析模型身份,并让本地缓存与已发布 ledger 使用同一身份。

— gpt-5.6-sol via Qwen Code /review (v0.21.11)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not resolved in this round — escalated for a maintainer's decision rather than silently picking a direction.

What landed instead: the marker's model is now the identity the runtime publishes (QWEN_CODE_MODEL, injected at both CLI boundaries from the environment Config keeps on the active model), never the model-written state field alone — so the posted certificate names exactly the identity the session itself reports as active, which closes the typed-identity hole (R1-2). But it is still the bare model id, so the cross-provider collision this finding names remains open in principle.

Why it is escalated rather than implemented: making the identity provider-aware spans subsystems this PR does not touch, with a real tradeoff on a public surface. (1) The identity is decided at the publisher (publishModelEnv in core config) — enriching it there changes what every consumer of QWEN_CODE_MODEL sees. (2) The same-model gate is enforced by the skill comparing against {{model}}, and the cache path's lastModelId (model-written at Step 8) has the same bare-id limitation — pre-existing, and per this finding's own "same identity for both gates" requirement both would have to move together. (3) The marker rides a PUBLIC, irreversible comment: the obvious discriminators (baseUrl, endpoint URL) can be private infrastructure, so a provider-aware posted identity needs a sanitized format — a design choice, and the local cache and the posted marker may not be able to share one.

Options as I see them: (a) accept the bare runtime-published id as this PR's identity contract and record the multi-provider limitation in DESIGN.md; (b) track a follow-up that enriches the identity at the publisher (authType-qualified selectors already exist in the runtime, e.g. getFastModel) and defines a public-safe provider discriminator for the marker; (c) redesign identity inside this PR — I would advise against it, since the cache format, the skill's gate instructions, and the marker format would all change together, far beyond this diff's footprint.

Question for the maintainer: is the bare runtime model id acceptable as the same-model identity for this PR, with provider-aware identity tracked as a follow-up — or should this PR wait for the richer identity?

中文说明

本轮未解决——此处需要维护者拍板,因此选择升级上报,而不是悄悄选定某个方向。

本轮实际落地的内容:marker 的 model 现在取运行时发布的身份(QWEN_CODE_MODEL,由两个 CLI 边界从 Config 始终指向当前活跃模型的环境变量中注入),不再仅取模型自己编写的 state 字段——因此已发布的证书所载身份与会话自身上报的活跃身份完全一致,堵住了"自报身份"的漏洞(R1-2)。但它仍是裸模型 id,所以本条指出的跨 provider 碰撞在原则上依然存在。

升级上报而非直接实施的原因:让身份感知 provider 会波及本 PR 未触及的子系统,且在公开表面上存在真实取舍。(1) 身份由发布端决定(core config 中的 publishModelEnv)——在那里扩充身份会改变所有 QWEN_CODE_MODEL 消费方看到的内容。(2) 同模型闸门由 skill 比较 {{model}} 来执行,而缓存路径的 lastModelId(Step 8 由模型写入)同样存在裸 id 的局限——这是既有行为,且按本条发现自身"两个闸门使用同一身份"的要求,两者必须同步改动。(3) marker 搭载在公开、不可逆的评论中:最直接的区分信息(baseUrl、endpoint URL)可能是私有基础设施信息,因此感知 provider 的已发布身份需要一种脱敏格式——这是一个设计决策,而且本地缓存与已发布 marker 可能根本无法共用同一种格式。

我所看到的选项:(a) 接受裸的运行时发布 id 作为本 PR 的身份契约,并在 DESIGN.md 中记录多 provider 的局限;(b) 以跟进任务的方式追踪:在发布端扩充身份(运行时已存在带 authType 限定的 selector,如 getFastModel),并为 marker 定义一种可安全公开的 provider 区分信息;(c) 在本 PR 内重做身份设计——我不建议这样做,因为缓存格式、skill 的闸门指令、marker 格式需要一起改动,远超本 diff 的足迹。

向维护者提问:本 PR 的同模型身份是否可以接受裸的运行时模型 id、将感知 provider 的身份作为跟进任务追踪——还是本 PR 应等待更丰富的身份方案?

@wenshao

wenshao commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

@qwen-code-dev-bot qwen-code-dev-bot added the autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+) label Aug 15, 2026
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤝 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/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。移除 autofix/takeover 标签(或评论 @qwen-code /takeover stop)即可释放。

@qwen-code-dev-bot

qwen-code-dev-bot commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

⚠️ AutoFix round 15 ended without publishing a reportview run.

中文说明

⚠️ AutoFix 第 15 轮结束但未发布报告 —— 查看运行

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下:

Autofix review-round summary — PR #9184 (round 2)

Addressed the review feedback on the ledger-marker model gate. The round
landed one commit, cb366f5578 ("fix(review): certify the ledger anchor with
the runtime model identity"), on top of the branch head 5f3f779da8. Seven of
nine inline findings are resolved in code, one is declined with its reason
recorded, and one Critical is escalated for a maintainer decision because it is
an identity-scheme design call, not a defect this PR can fix alone.

Dispositions

rc id Sev / author Disposition
3786241088 Critical (qwen-code-ci-bot, R1-9) Resolved — attribution-off leak
3786251561 Critical (wenshao, R1-1) Resolved — truncation collision
3786251565 Critical (wenshao, R1-2) Resolved — model-authored provenance
3786251570 Critical (wenshao, R1-3) Escalated — provider-aware identity is a design decision
3786241097 Suggestion (qwen-code-ci-bot, R1-1) Resolved — asymmetric fallback
3786241102 Suggestion (qwen-code-ci-bot, R1-2) Resolved — recovery-seam pin
3786241108 Suggestion (qwen-code-ci-bot, R1-3) Resolved — attribution-off branch test
3786241113 Suggestion (qwen-code-ci-bot, R1-4) Resolved — DESIGN.md wording
3786241120 Suggestion (qwen-code-ci-bot, R1-5) Declined — typecheck is the gate (recorded)

What changed

Attribution-off leak (rc:3786241088). With review.attribution: false
the footer is suppressed but the new model field still published the exact
model id in the posted body, violating the setting's contract. ledgerMarkerFor
now receives attribution and withholds model entirely when it is off; the
anchor degrades to the skill's absent-model fail-safe (full-range). The sha
still rides.

Model-authored provenance (rc:3786251565). The certifying model was read
from input.modelId — a field of the model-written state JSON. Both CLI
boundaries (compose-review handler and submit) now inject
process.env['QWEN_CODE_MODEL'] (the identity Config publishes as the active
model and the shell tool hands to the subprocess) through a new runtimeModelId
parameter; the marker certifies with that, falling back to the declared field
only when no runtime identity was published. A review can no longer certify an
anchor to a model it names but is not.

Truncation collision (rc:3786251561). The model id was truncated to 64
chars, so a long id serialized as its prefix and a distinct model whose full id
equals that prefix compared equal in the gate (probe-reproduced: a 75-char id
recovered as its 64-char prefix matched the prefix's owner). The marker now
carries the identity whole or not at all: an over-cap model withholds the
whole sha/model pair on write, and the parser drops an over-cap model it
reads (the serializer would never have written one) while keeping the sha. The
gate reads the absence as a mismatch — the fail-safe direction.

Asymmetric fallback (rc:3786241097). The "SHAs differ but model differs"
cache branch now carries a reprieve mirroring the recovery paragraph's own
fallback: when the side file lands with the setup batch, if its anchor passes
the recovered-anchor gate, scope to it instead of mandating the full diff.

Recovery-seam pin (rc:3786241102). Added model: 'qwen3.7-max' to the
anchored ledger in 'carries the anchor sha and model through the recovery seam intact', so the toEqual pin covers the new field beside the sha and a
future projection that drops it reddens the test.

Attribution-off branch test (rc:3786241108). Added marker-path tests:
attribution off withholds the model (and the body names no model), and with a
missing modelId the marker survives with only the model withheld. Also added
a runtime-identity test and a handler wiring test pinning
QWEN_CODE_MODEL → marker.

DESIGN.md wording (rc:3786241113). The bullet no longer claims the cache
path "always enforced" the same-model contract through lastModelId; it now
says the cache paired the anchor with lastModelId but enforced the contract
only in the same-SHA skip case, and that this change extends enforcement to the
differ-SHA branch and the recovery path.

Declined (rc:3786241120). The test-efficacy probe asked to confirm
typecheck gates the model?: string declaration hunk or add a type-level pin.
Confirmed: npm run typecheck (run in CI and re-run this round) is the gate —
vitest transpiles without type-checking by design, and the finding's own
mitigation records that the runtime hunks are probe-killed and ledger.test.ts
gates the full-file revert. Adding a compile-time pin would duplicate what tsc
already catches; declined as unnecessary diff growth. Reason recorded in the
thread reply.

Escalated (rc:3786251570). Provider-aware model identity (authType +
endpoint discriminator) is not implemented here. It spans the runtime publisher
(publishModelEnv), the skill's {{model}} gate, the cache's lastModelId,
and the marker — and the marker rides a public, irreversible comment, so a
provider discriminator (e.g. baseUrl) raises a leak concern. This is an
identity-scheme design decision for a maintainer, not a defect this PR can fix
in isolation. Options and a recommendation are posted on the thread; the thread
is left unresolved.

Conflict notes

None. --conflict was false; no merge of origin/main was needed and none
was performed.

Verification

Commands actually run this round, and their results:

  • npm run build — passed (exit 0).
  • npm run typecheck — passed (exit 0).
  • npm run lint — passed (exit 0); also ran focused npx eslint over the six
    changed .ts files (clean).
  • npx prettier --check on the changed files — passed after one --write fix
    to lib/ledger.ts.
  • Focused Vitest, packages/cli: compose-review.test.ts (233), lib/ledger.test.ts
    (18), pr-context.test.ts (68), submit.test.ts (65) — 384 passed (384).
  • Focused Vitest, packages/core: skills/bundled/review/SKILL.test.ts11 passed (11).
  • Probe (tsx): reproduced the truncation collision pre-fix
    (gateWouldMatchWrongModel: true), and confirmed it flips post-fix
    (gateWouldMatchWrongModel: false).
  • Red-first: the new model-gate tests were added and confirmed failing against
    the unchanged source (attribution-off leak, runtime-vs-declared identity, and
    over-cap truncation), then passing after the fix.
  • Not run (not triggered): integration tests after npm run bundle — the
    changed behavior is fully exercised by the focused unit tests above, not only
    through the bundled CLI. npm run generate:settings-schema — no settings
    source changed.
中文说明

Autofix 审查轮次总结 — PR #9184(第 2 轮)

本轮处理了关于 ledger-marker 模型闸门的审查反馈,在分支头 5f3f779da8
之上提交了一个 commit:cb366f5578("fix(review): certify the ledger anchor
with the runtime model identity")。9 条行内发现中 7 条已在代码中解决,1 条
记录理由后拒绝处理,1 条 Critical 升级给维护者决策——因为它是身份方案的
设计决策,而非本 PR 能单独修复的缺陷。

处理结果

rc id 严重度 / 作者 处理
3786241088 Critical(qwen-code-ci-bot,R1-9) 已解决 — attribution 关闭时的泄露
3786251561 Critical(wenshao,R1-1) 已解决 — 截断碰撞
3786251565 Critical(wenshao,R1-2) 已解决 — 模型自报来源
3786251570 Critical(wenshao,R1-3) 已升级 — 感知 provider 的身份属于设计决策
3786241097 Suggestion(qwen-code-ci-bot,R1-1) 已解决 — 不对称回退
3786241102 Suggestion(qwen-code-ci-bot,R1-2) 已解决 — 恢复接缝钉住
3786241108 Suggestion(qwen-code-ci-bot,R1-3) 已解决 — attribution 关闭分支测试
3786241113 Suggestion(qwen-code-ci-bot,R1-4) 已解决 — DESIGN.md 措辞
3786241120 Suggestion(qwen-code-ci-bot,R1-5) 已拒绝 — typecheck 即闸门(已记录)

改动内容

attribution 关闭时的泄露(rc:3786241088)。review.attribution: false 时,footer 被抑制,但新增的 model 字段仍会把确切的模型 id 发布到
已提交的正文中,违反该设置的契约。ledgerMarkerFor 现在接收 attribution
关闭时完全扣下 model;anchor 退化为 skill 已规定的"模型缺失"fail-safe
(全量审查)。sha 仍然保留。

模型自报来源(rc:3786251565)。 认证模型此前读自 input.modelId——一个
由模型编写的 state JSON 字段。两个 CLI 边界(compose-review handler 与
submit)现在通过新增的 runtimeModelId 参数注入
process.env['QWEN_CODE_MODEL'](Config 发布为当前活跃模型、并由 shell 工具
传给子进程的身份);marker 以该身份认证,仅当没有任何运行时身份时才回退到
声明字段。审查再也无法把 anchor 认证到一个它自称但其实不是的模型。

截断碰撞(rc:3786251561)。 模型 id 此前被截断为 64 字符,因此过长的 id
会被序列化为它的前缀,而完整 id 恰好等于该前缀的另一个模型在闸门中会被判为
相等(已用 probe 复现:75 字符 id 恢复为 64 字符前缀后与前缀的所有者匹配)。
marker 现在要么完整携带、要么完全不携带该身份:超过上限的模型在写入时把
整个 sha/model 对一起扣下,解析器读到超过上限的模型时将其丢弃(序列化器
本不会写出这样的值)但保留 sha。闸门把缺失读作不匹配——即 fail-safe 方向。

不对称回退(rc:3786241097)。 "SHAs 不同但模型不同"的缓存分支现在带有一个
与恢复段落自身回退相对应的宽限:当旁路文件随 setup batch 落地时,若其 anchor
通过恢复 anchor 闸门,则按其划分范围,而不是强制全量 diff。

恢复接缝钉住(rc:3786241102)。'carries the anchor sha and model through the recovery seam intact'anchored ledger 中加入
model: 'qwen3.7-max',使 toEqual 钉住新字段与 sha 并列;未来若有任何投影
丢弃该字段,测试会变红。

attribution 关闭分支测试(rc:3786241108)。 新增 marker 路径测试:
attribution 关闭时扣下模型(且正文不出现任何模型名);缺失 modelId
marker 存活、仅扣下模型。另新增运行时身份测试与 handler 接线测试,钉住
QWEN_CODE_MODEL → marker

DESIGN.md 措辞(rc:3786241113)。 该条目不再声称缓存路径"一直通过
lastModelId 强制执行"同模型契约;现改为:缓存路径将 anchor 与
lastModelId 配对,但仅在同 SHA 跳过情形下强制执行契约,本改动将强制执行
扩展到 SHA 不同的增量分支与恢复路径。

已拒绝(rc:3786241120)。 测试有效性 probe 要求确认 typecheck 是
model?: string 声明 hunk 的闸门,或增加类型层面的钉住。已确认:
npm run typecheck(CI 中运行,本轮也已重新运行)就是闸门——vitest 按设计
转译时不做类型检查,且该发现自身的缓解说明已记录:运行时各 hunk 均被 probe
杀死,ledger.test.ts 对整文件回退是有效的。再加一个编译期钉住只是重复 tsc
已捕获的东西;作为不必要的 diff 增长予以拒绝。理由已记录在线程回复中。

已升级(rc:3786251570)。 感知 provider 的模型身份(authType + endpoint
区分信息)未在本轮实现。它横跨运行时发布端(publishModelEnv)、skill 的
{{model}} 闸门、缓存的 lastModelId 与 marker——而且 marker 搭载在公开、
不可逆的评论中,因此 provider 区分信息(如 baseUrl)存在泄露顾虑。这是一
个需要维护者拍板的身份方案设计决策,而非本 PR 能单独修复的缺陷。线程中已给
出选项与建议,线程保持未解决。

冲突说明

无。--conflictfalse;无需合并 origin/main,也未执行任何合并。

验证

本轮实际运行的命令及结果:

  • npm run build — 通过(exit 0)。
  • npm run typecheck — 通过(exit 0)。
  • npm run lint — 通过(exit 0);另对改动的 6 个 .ts 文件运行了聚焦的
    npx eslint(无问题)。
  • 对改动文件运行 npx prettier --check — 在对 lib/ledger.ts 执行一次
    --write 修复后通过。
  • 聚焦 Vitest,packages/clicompose-review.test.ts(233)、
    lib/ledger.test.ts(18)、pr-context.test.ts(68)、submit.test.ts
    (65)— 384 通过(384)
  • 聚焦 Vitest,packages/coreskills/bundled/review/SKILL.test.ts
    11 通过(11)
  • Probe(tsx):修复前复现了截断碰撞(gateWouldMatchWrongModel: true),
    修复后确认翻转为 gateWouldMatchWrongModel: false
  • 先红后绿:先添加新的模型闸门测试并确认其在未改动源码上失败
    (attribution 关闭泄露、运行时 vs 声明身份、超限截断),修复后通过。
  • 未运行(未触发):npm run bundle 之后的集成测试——本次改动的行为已由上述
    聚焦单元测试完全覆盖,并非只通过打包后的 CLI 才能验证。
    npm run generate:settings-schema — 未改动任何 settings 来源。

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

中文说明

仅完成部分审查,审查缺口已披露。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +583 to +584
const certifying = runtime !== '' ? runtime : declared;
const model = attribution && certifying !== '' ? certifying : undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R2-9: Re-check of the round-1 cross-provider identity blocker (filed by @wenshao's reviewer): still stands at this commit. The marker's certifying identity is still the bare runtime model string with no authType/provider/endpoint discriminator; the autofix round escalated exactly this point for a maintainer decision (accept the bare runtime id and record the limitation, or track a provider-aware identity as a follow-up), and that decision is still open — so the blocker is re-asserted for this round's verdict. — Failure scenario: two provider or endpoint configurations expose the same model ID while resolving to different underlying models → the second configuration accepts the first configuration's anchor and skips code it never reviewed.

Witness: not run — the blocker is the absence of a provider discriminator in the identity; read at cb366f55: both arms above are bare model ids (runtime = QWEN_CODE_MODEL, declared = state.modelId), and the escalation reply confirms the round-1 remedy was not implemented.

Suggested fix: persist and compare a stable resolved-model identity including the relevant auth type and provider or endpoint discriminator, using the same identity for the cache and posted-ledger gates — or record a maintainer decision accepting the bare runtime id as this PR's identity contract and track the richer identity as a follow-up.

中文说明

【Critical】 对第 1 轮跨 provider 身份阻断项(由 @wenshao 的审查者提出)的复核:在本提交上仍然存在。marker 的认证身份仍是裸的运行时模型字符串,没有 authType/provider/endpoint 区分信息;autofix 轮次已就这一点升级上报、等待维护者决策(接受裸运行时 id 并记录其局限,或将 provider 感知的身份作为跟进任务追踪),该决策仍未落地——因此本条阻断项在本轮裁定中重新成立。 — 失败场景:两个 provider 或 endpoint 配置暴露相同的模型 ID、但解析为不同的底层模型 → 第二个配置会接受第一个配置的 anchor,并跳过它从未审查过的代码。

见证:未运行——阻断点是身份中缺少 provider 区分信息;已在 cb366f55 上直接阅读代码:上述两个分支都是裸模型 id,升级回复也确认第 1 轮的补救方案未实施。

建议修复:持久化并比较包含相关 auth type 与 provider/endpoint 区分信息的稳定解析模型身份,缓存与已发布 ledger 两个闸门使用同一身份——或由维护者明确决策接受裸运行时 id 作为本 PR 的身份契约,并将更丰富的身份作为跟进任务追踪。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This round deliberately leaves the blocker unresolved. At this commit the marker's certifying identity is still the bare runtime model string (QWEN_CODE_MODEL, with the model-written state field as the fallback) — no authType/provider/endpoint discriminator — so the round-1 claim still stands, and this round did not attempt to implement either remedy unilaterally.

The previous round escalated exactly this point for a maintainer decision, and that decision is still open. The two options, restated:

  • Option A — accept the bare runtime model id as this PR's identity contract, record the limitation (two provider/endpoint configurations exposing the same model id while resolving to different underlying models would share anchors), and track a provider-aware identity as a follow-up issue.
  • Option B — require the richer identity in this PR: persist and compare a stable resolved-model identity including the relevant auth type and provider/endpoint discriminator, used identically for the cache and posted-ledger gates.

Recommendation on record: Option A. This PR's threat model is forgery through model-typed channels, which the runtime injection closes; cross-provider id collision is a narrower scenario, and fixing it requires a design decision across the core auth/provider/config surface, which is maintainer-only per AGENTS.md. This thread stays UNRESOLVED until a maintainer chooses; the answer arrives as ordinary feedback next round.

中文说明

本轮有意保持该阻断项未解决。在本提交上,marker 的认证身份仍是裸的运行时模型字符串(QWEN_CODE_MODEL,以模型自己填写的 state 字段作为回退)——没有 authType/provider/endpoint 区分信息——因此第 1 轮的主张依然成立,本轮也没有单方面实施任何一种补救方案。

上一轮已就这一点升级上报、等待维护者决策,该决策仍未落地。两个选项重述如下:

  • 选项 A — 接受裸运行时模型 id 作为本 PR 的身份契约,记录其局限(两个暴露相同模型 id、却解析为不同底层模型的 provider/endpoint 配置会共享 anchor),并将 provider 感知的身份作为跟进 issue 追踪。
  • 选项 B — 在本 PR 中就要求更丰富的身份:持久化并比较包含相关 auth type 与 provider/endpoint 区分信息的稳定解析模型身份,缓存与已发布 ledger 两个闸门使用同一身份。

记录在案的建议:选项 A。本 PR 的威胁模型是经由模型可填写通道的伪造,运行时注入已经关闭了该通道;跨 provider 的 id 冲突是更窄的场景,其修复需要在 core 的 auth/provider/config 表面做设计决策——按 AGENTS.md 属维护者专属。该线程保持未解决,直到维护者作出选择;答复会在下一轮作为普通反馈到达。

Comment on lines +501 to +502
// into this subprocess — not the id the state JSON typed.
process.env['QWEN_CODE_MODEL'],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R2-1: The runtime-model injection at this posting boundary has no wiring test — deleting the fourth argument survives the entire suite. submit.test.ts never sets QWEN_CODE_MODEL, and its marker suite ('the ledger marker on the body that reaches GitHub') asserts only round and findings on parseLedger(posted().body); the PR's new wiring test covers only the compose-review handler, which writes nothing and posts nothing — submit is the only boundary whose body reaches GitHub. — Failure scenario: a future edit drops process.env['QWEN_CODE_MODEL'] from runSubmit's compose(...) call → runtimeModelId becomes undefined, the posted marker's model silently falls back to the model-written state.modelId, and every posted anchor is again certified by whatever id the state JSON typed — the exact cross-model forgery this PR exists to prevent — while submit.test.ts (65/65) and the compose-review/ledger/pr-context suites (319/319) all stay green.

Witness (probe, both arms): unmutated — probe passes, posted marker "model":"the-session-model"; with the argument dropped — posted marker {"model":"typed-by-the-model","sha":"deadbeef00112233"} with the whole suite still green.

Suggested fix: mirror the compose-review wiring test in submit.test.ts — save/set process.env['QWEN_CODE_MODEL'] = 'the-session-model' (restore in finally), run runSubmit with a state whose modelId is a different literal ('typed-by-the-model') and a plan carrying fetchedSha, then assert parseLedger(posted().body)?.model === 'the-session-model'.

中文说明

【Suggestion】 R2-1:此发布边界的运行时模型注入没有任何接线测试——删掉第四个参数后整个测试套件仍然全绿。submit.test.ts 从未设置 QWEN_CODE_MODEL,其 marker 测试块('the ledger marker on the body that reaches GitHub')只对 parseLedger(posted().body) 断言了 roundfindings;本 PR 新增的接线测试只覆盖了 compose-review handler,而该 handler 什么都不写、什么都不发布——submit 才是唯一让正文到达 GitHub 的边界。 — 失败场景:未来某次修改把 process.env['QWEN_CODE_MODEL']runSubmitcompose(...) 调用中删掉 → runtimeModelId 变为 undefined,已发布 marker 的 model 静默回退到模型自己写的 state.modelId,所有已发布的 anchor 又变成由 state JSON 所填写的任意 id 来认证——正是本 PR 要防止的跨模型伪造——而 submit.test.ts(65/65)与 compose-review/ledger/pr-context 套件(319/319)全部保持绿色。

见证(probe,双向验证):未突变——probe 通过,发布的 marker 为 "model":"the-session-model";删掉该参数后——发布的 marker 为 {"model":"typed-by-the-model","sha":"deadbeef00112233"},整套测试仍全绿。

建议修复:在 submit.test.ts 中镜像 compose-review 的接线测试——保存并设置 process.env['QWEN_CODE_MODEL'] = 'the-session-model'(在 finally 中恢复),以 modelId 为不同字面量('typed-by-the-model')的 state 和带 fetchedSha 的 plan 运行 runSubmit,然后断言 parseLedger(posted().body)?.model === 'the-session-model'

— qwen3.8-max via Qwen Code /review (v0.21.12)

- **Own-account, latest round only.** The ledger claims "these are the findings the previous /review stood behind", and only this account's reviews can make that claim — another user's marker is data about _their_ tooling. Each posted round embeds a fresh full copy, so the newest marker is the whole state.
- **Data, not authority.** Every recovered entry is owed a Step 6 ruling against the code — the ledger routes work, it never rules. A tampered or stale marker therefore costs a few wasted rulings, not a wrong verdict, which is why parsing is fail-quiet and the round number feeds `compose-review` from a CLI-written side file rather than a model's memory.
- **Medium reads, high writes.** Recovering the ledger is free (the reviews were already fetched), so the default-effort re-review finally opens like a round-2 comment; the cache write and the posting that carries the marker keep their existing effort gates untouched.
- **The anchor names its model.** Incremental scoping is a same-model contract — "clean up to `sha`" is one model's verdict. The cache path has paired its anchor with `lastModelId` from the start, but enforced the contract only in the same-SHA skip case (a re-run under a different model gets a full second opinion, not a skip); its differing-SHA incremental branch carried no model condition until this change. The marker's anchor shipped bare, so the recovery path had no way to honour the contract at all: a round run under model B that recovered model A's anchor would scope `sha..HEAD` past code B never reviewed — permanently, since each clean round re-anchors past the last. The marker now carries `model` beside `sha`, riding and falling with the anchor (withheld on fail-closed and truncated rounds alike; an id over the marker's cap withholds the PAIR — a truncated id is a prefix, and a prefix can equal another model's full id; dropped by the parser when the sha beside it did not survive), and Step 1's recovered-anchor gate requires it to match the running model — absent, on markers from before the field, counts as a mismatch: the work list still carries (rulings re-assert against the code, so they cross models safely), only the anchor does not. Two boundaries of that carriage: the identity the marker carries is the one the session publishes (`QWEN_CODE_MODEL`, injected at the CLI boundaries), with the model-written state field only the fallback for runs no session published — a review must not be able to certify an anchor to a model it names but is not; and `review.attribution: false` withholds it with the footer, because the setting's contract is whether the posted review names its model, and the marker rides the posted body.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R2-2: The setting's enlarged behavioural surface is documented only here (DESIGN/SKILL); the user-facing settings entry — whose own convention already lists consequences of disabling it — does not mention the new one. With attribution off the marker omits model, and the new same-model gate reads absence as a mismatch, so for an attribution-off user every round in a fresh environment (CI, another clone — the normal state per SKILL.md, where the cache is absent) silently degrades from incremental to full-range review. Pre-PR, the recovered anchor had no model condition and passed; post-PR it never passes. — Concrete cost: a user wondering why incremental scoping never engages in CI has docs/users/configuration/settings.md (the review.attribution row, which already documents a sibling side effect) as the lookup surface and finds nothing there.

Suggested fix: add a sentence to the review.attribution row in docs/users/configuration/settings.md (and docs/users/features/code-review.md): with attribution off, the ledger marker also withholds the model, so recovered anchors in fresh environments fall back to a full review.

中文说明

【Suggestion】 R2-2:该设置被扩大的行为面只记录在这里(DESIGN/SKILL);面向用户的设置条目——其自身惯例本就会列出禁用后的后果——没有提到新增的这一条。attribution 关闭时 marker 会省略 model,而新的同模型闸门把缺失视为不匹配,因此对关闭 attribution 的用户来说,在全新环境(CI、另一份 clone——按 SKILL.md 这是常态,缓存不存在)中的每一轮都会从增量审查静默退化为全量审查。本 PR 之前,恢复的 anchor 没有模型条件、可以通过;之后永远无法通过。 — 具体代价:用户想知道为什么增量范围划分在 CI 里从不生效时,docs/users/configuration/settings.md(review.attribution 一行,已经记录了同类的副作用)是其查阅入口,但那里找不到任何相关信息。

建议修复:在 docs/users/configuration/settings.mdreview.attribution 一行(以及 docs/users/features/code-review.md)补充一句:attribution 关闭时,ledger marker 也会扣下模型,因此全新环境中恢复的 anchor 会退化为全量审查。

— qwen3.8-max via Qwen Code /review (v0.21.12)


- **Incremental review check** (high effort only — neither low nor medium consults or updates the cache): if `.qwen/review-cache/pr-<n>.json` exists, read it **in the same response as the fetch report** — both are `read_file`, genuinely parallel — for `lastCommitSha` and `lastModelId`. Compare to `fetchedSha` from the fetch report and the current model ID (`{{model}}`):
- If SHAs differ → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.
- If SHAs differ **and** model matches → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R2-5: This new differing-SHA model gate reads lastModelId — a value the model itself types into .qwen/review-cache/pr-<n>.json at Step 8 ("lastModelId": "{{model}}"; a repo-wide grep confirms no CLI writer of the cache exists — only the unused REVIEW_CACHE_DIR constant). The boundary this PR's own added DESIGN.md paragraph claims — "a review must not be able to certify an anchor to a model it names but is not", enforced for the marker by runtime injection — is therefore not enforced on the very cache gate this same diff adds. — Failure scenario: a round under model A (including one steered by prompt injection in the PR content) writes "lastModelId": "B" beside the honest lastCommitSha at Step 8; the operator later runs model B for the cross-model re-review the skill explicitly supports — round N+1 under B reads "SHAs differ and model matches" (forged), scopes lastCommitSha..HEAD, and permanently skips code only A ever reviewed. Mitigating: pre-PR this branch had no model condition at all, so the forged outcome does not exceed the pre-PR baseline — a defeated improvement plus an overstated design claim, not a new worst case.

Suggested fix: mirror the marker's fix pattern on the cache boundary — route the Step 8 cache write through a CLI subcommand that stamps QWEN_CODE_MODEL so lastModelId is injected, not typed; or, at minimum, name in the new DESIGN.md paragraph that the cache path's lastModelId remains a model-typed channel and the "must not be able to certify" sentence bounds only the marker.

中文说明

【Suggestion】 R2-5:这个新增的"SHA 不同"模型闸门读取的 lastModelId,是模型自己在 Step 8 写入 .qwen/review-cache/pr-<n>.json 的值("lastModelId": "{{model}}";全仓 grep 确认不存在任何 CLI 写入方——只有未使用的 REVIEW_CACHE_DIR 常量)。因此,本 PR 自己在 DESIGN.md 新增段落中声明的边界——"审查不能把 anchor 认证到自己口头声称但并非实际运行的模型"(marker 侧已通过运行时注入强制)——在同一个 diff 新增的这个缓存闸门上并未被强制。 — 失败场景:模型 A 的一轮审查(包括被 PR 内容中的 prompt injection 操纵的一轮)在 Step 8 把 "lastModelId": "B" 与诚实的 lastCommitSha 写在一起;之后运维者按 skill 明确支持的跨模型复审运行模型 B——B 的第 N+1 轮读到"SHA 不同且模型匹配"(伪造),范围划为 lastCommitSha..HEAD,永久跳过只有 A 审查过的代码。缓解因素:本 PR 之前该分支根本没有模型条件,因此伪造结果并未超过改动前基线——这是被击败的改进加上被夸大的设计声明,而非新的最坏情形。

建议修复:在缓存边界镜像 marker 的修复模式——把 Step 8 的缓存写入改由 CLI 子命令完成并盖上 QWEN_CODE_MODEL,使 lastModelId 是被注入的而非模型填写的;或至少在 DESIGN.md 新段落中说明:缓存路径的 lastModelId 仍是模型可填写的通道,"不能认证"那句话只约束 marker。

— qwen3.8-max via Qwen Code /review (v0.21.12)

- If SHAs match **but** model differs → continue. Inform: "Previous review used {cached_model}. Running full review with {{model}} for a second opinion."

- **When the cache has no anchor, the PR itself carries one** (high effort only, same as the cache). The file being absent is the NORMAL state everywhere except the machine that ran the last review — CI, another clone, a colleague's checkout — and it used to mean the incremental range silently degraded to the full diff every time, which is precisely the cost incremental review exists to avoid. The anchor now rides the posted review: the machine ledger's marker carries `sha`, the head the last clean round reviewed, and `pr-context` writes it into the side file `qwen-review-pr-<n>-prev-ledger.json` with the rest of the ledger. So when the cache is absent or its `lastCommitSha` was rebased away: proceed with the setup batch as usual, and when the side file lands, read its `sha`. **Validate before scoping** — inside the worktree, `git cat-file -e <sha>^{commit}` and `git merge-base --is-ancestor <sha> HEAD` — and on success treat it exactly as `lastCommitSha` above: the same outcomes, decided AFTER the setup batch but BEFORE any agent launches, which is where the money is (a same-SHA stop still runs `cleanup`; it just fires three cheap commands later than the cache's fast path would have). A sha that fails either check — rebased away, or not this history's — falls back to the full diff with a logged warning, exactly as a rebased cache sha does. Two edges, both decided for you: if the side file's `round` is **higher** than the cache's, prefer the side file's sha — the cache is stale by a round some other environment posted; and a side file with no `sha` field means the last posted round was fail-closed (`compose-review` withholds the anchor then — Step 8 names the conditions), had its ledger truncated by the marker's size caps (a partial work list must not certify a range — the dropped entries would fall outside the next round's scope and retire silently), or predates the field — in every case there is no anchor to recover, and the review is full-range.
- **When the cache has no anchor, the PR itself carries one** (high effort only, same as the cache). The file being absent is the NORMAL state everywhere except the machine that ran the last review — CI, another clone, a colleague's checkout — and it used to mean the incremental range silently degraded to the full diff every time, which is precisely the cost incremental review exists to avoid. The anchor now rides the posted review: the machine ledger's marker carries `sha`, the head the last clean round reviewed, and `model`, the model whose verdict certified it, and `pr-context` writes them into the side file `qwen-review-pr-<n>-prev-ledger.json` with the rest of the ledger. So when the cache is absent or its `lastCommitSha` was rebased away: proceed with the setup batch as usual, and when the side file lands, read its `sha` **and `model`**. **Validate before scoping** — inside the worktree, `git cat-file -e <sha>^{commit}` and `git merge-base --is-ancestor <sha> HEAD`, and require the side file's `model` to equal `{{model}}` — the same same-model contract the cache path enforces through `lastModelId`: an anchor certified by a different model scopes this round past code `{{model}}` never reviewed. A side file whose `model` differs — or is absent, on markers from before the field — recovers the findings work list but NO anchor: the review is full-range, with the cache path's "Previous round was reviewed by …" notice. On a sha and model that both pass, treat the sha exactly as `lastCommitSha` above: the same outcomes, decided AFTER the setup batch but BEFORE any agent launches, which is where the money is (a same-SHA stop still runs `cleanup`; it just fires three cheap commands later than the cache's fast path would have). A sha that fails either check — rebased away, or not this history's — falls back to the full diff with a logged warning, exactly as a rebased cache sha does. Two edges, both decided for you: if the side file's `round` is **higher** than the cache's, prefer the side file's sha — the cache is stale by a round some other environment posted (the model gate rules on whichever anchor is preferred; when the preferred anchor fails it, fall back to the other anchor if that one passes — an older same-model anchor scopes a superset range, which is safe — and to the full diff otherwise); and a side file with no `sha` field means the last posted round was fail-closed (`compose-review` withholds the anchor then — Step 8 names the conditions), had its ledger truncated by the marker's size caps (a partial work list must not certify a range — the dropped entries would fall outside the next round's scope and retire silently), certified its range under a model id too long for the marker's cap (the anchor pair is withheld whole — a truncated id is a prefix, and a prefix can equal another model's full id), or predates the field — in every case there is no anchor to recover, and the review is full-range.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R2-6: This fallback clause routes only model-gate failure of the preferred anchor to the other anchor, but the paragraph's own entry states (cache absent, or its lastCommitSha rebased away) make that success unreachable — in both entry states the cache anchor cannot pass any whole-gate reading. Meanwhile the reachable failure class — the preferred cache anchor fails the ancestor check while the side file's same-model anchor passes both checks — is routed by the preceding universal sentence to the full diff, discarding a valid anchor. — Failure scenario: machine X caches round 5 under model A; a force-push rebases the cached sha away; the account's last posted marker is round 3, sha S, model A, with S still an ancestor of the fetched head. The round rule leaves the cache sha preferred (5 > 3); its failure is the ancestor check, not the model gate, so this parenthetical never fires and the review runs full-range instead of S..HEAD — the exact fresh-environment/force-push cost the recovery feature exists to avoid. Direction is fail-safe (never under-reviews).

Suggested fix: key the fallback to the full gate, not the model check alone — e.g. "use whichever anchor passes the recovered-anchor gate whole (valid sha, ancestor of the fetched head, model == {{model}}); when both pass, prefer the higher-round sha" — which subsumes the current clause and covers the rebased-preferred case.

中文说明

【Suggestion】 R2-6:该回退子句只把"被优先 anchor 未通过模型闸门"这一种失败路由到另一个 anchor,但本段落自身的进入条件(缓存不存在、或其 lastCommitSha 被 rebase 掉)决定了这种路由不可能成功——在两种进入状态下,缓存 anchor 在任何整体闸门解读下都不可能通过。而可达的失败类别——被优先的缓存 anchor 未通过祖先检查、而旁路文件中同模型的 anchor 两项检查都通过——却被前面那句通用规则路由到全量 diff,丢弃了一个有效 anchor。 — 失败场景:机器 X 在模型 A 下缓存了第 5 轮;一次 force-push 把缓存的 sha rebase 掉;该账号最近一次发布的 marker 是第 3 轮、sha S、模型 A,且 S 仍是 fetched head 的祖先。轮次规则使缓存 sha 仍被优先(5 > 3);它的失败是祖先检查而非模型闸门,因此本括注永远不会触发,审查只能全量运行而不是 S..HEAD——恰恰是恢复 anchor 特性本要避免的全新环境/force-push 成本。方向是 fail-safe(不会审查不足)。

建议修复:把回退条件改为完整闸门而非仅模型检查——例如"使用任一通过完整恢复闸门的 anchor(有效 sha、是 fetched head 的祖先、model == {{model}});两者都通过时优先更高轮次的 sha"——这包含现有子句并覆盖"被优先 anchor 被 rebase 掉"的情形。

— qwen3.8-max via Qwen Code /review (v0.21.12)

- **Incremental review check** (high effort only — neither low nor medium consults or updates the cache): if `.qwen/review-cache/pr-<n>.json` exists, read it **in the same response as the fetch report** — both are `read_file`, genuinely parallel — for `lastCommitSha` and `lastModelId`. Compare to `fetchedSha` from the fetch report and the current model ID (`{{model}}`):
- If SHAs differ → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.
- If SHAs differ **and** model matches → continue with the worktree just created. Compute the incremental diff (`git diff <lastCommitSha>..HEAD` inside the worktree) and use as the review scope; if the cached commit was rebased away, fall back to the full diff and log a warning. **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.
- If SHAs differ **but** model differs → continue with the worktree, and the scope is the **full diff**, never `<lastCommitSha>..HEAD`: "clean up to `lastCommitSha`" is {cached_model}'s verdict, and an incremental range scoped to another model's anchor leaves everything before it reviewed by no run of `{{model}}` — permanently, because this round's own cache write would re-anchor past it. One reprieve — the mirror of the recovery paragraph's fallback: when the side file lands with the setup batch, if ITS anchor passes the recovered-anchor gate below (valid sha, ancestor of the fetched head, `model` == `{{model}}`), scope to it instead — decided AFTER the setup batch but BEFORE any agent launches — because an anchor the CURRENT model certified in a round some other environment posted is exactly the contract's own terms. Otherwise inform: "Previous round was reviewed by {cached_model}. Running full review with {{model}}." Still read the cache's `findings` ledger and owe each entry its Step 6 ruling — the work list carries across models (every entry is re-asserted against the code); only the anchor does not.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R2-7: This reprieve routes a passing side-file anchor to "scope to it instead" but not to "the same outcomes" as lastCommitSha — so when the recovered sha equals the fetched head the scope is empty, and the no-new-changes stop (keyed to the cache's own SHAs matching, false in this branch by construction) is unreachable. The recovery paragraph the reprieve claims to mirror handles this geometry expressly ("treat the sha exactly as lastCommitSha above: the same outcomes … a same-SHA stop still runs cleanup"). — Failure scenario: environment A runs model M, reviews head H, posts (marker sha=H, model=M). Machine X's cache holds an older round under model N (lastCommitSha S ≠ H). Machine X fetches the same head H (no new commits) and runs /review under M at high effort: the reprieve passes (H is valid; a commit is its own ancestor; M == M) and the scope becomes H..H = empty — the agent fan-out launches over nothing, the round posts a noise verdict and re-anchors, and with --comment the comment pass the operator explicitly requested silently produces zero comments. Direction is fail-safe.

Witness: git merge-base --is-ancestor cb366f55 cb366f55 → exit 0 at the reviewed commit (a commit is its own ancestor, so the reprieve gate passes on the equal-sha geometry); the claim itself is about model-facing spec prose and was traced, not run.

Suggested fix: route a passing anchor to the same outcomes as lastCommitSha — e.g. "scope to it instead, applying the same outcomes as lastCommitSha above (if it equals the fetched head, the same-SHA decision applies: stop with cleanup unless comment.effective, which runs the full review)".

中文说明

【Suggestion】 R2-7:该 reprieve(豁免)子句把通过闸门的旁路文件 anchor 路由为"改按其划分范围",却没有路由到与 lastCommitSha "相同的后续结果"——因此当恢复出的 sha 恰好等于 fetched head 时,审查范围为空,而"无新变更"的停止分支(以缓存自身 SHA 匹配为键,在本分支按构造恒为假)永远不可达。reprieve 自称镜像的恢复段落对这一几何形状有明确处理("将该 sha 完全按上面的 lastCommitSha 对待:相同的后续结果……同 SHA 停止仍会运行 cleanup")。 — 失败场景:环境 A 运行模型 M,审查 head H 并发布(marker sha=H,model=M)。机器 X 的缓存里是模型 N 的更早一轮(lastCommitSha S ≠ H)。机器 X 拉取到同一个 head H(没有新提交)并以高 effort 运行 /review(模型 M):reprieve 通过(H 有效;一个 commit 是自己的祖先;M == M),范围变成 H..H = 空——agent 扇出在零 hunk 上启动,本轮发布一个无意义的裁定并重新锚定,而使用 --comment 时运维者明确要求的评论发布环节静默地产出零条评论。方向是 fail-safe。

见证:git merge-base --is-ancestor cb366f55 cb366f55 → 在被审查提交上 exit 0(一个 commit 是自己的祖先,因此 reprieve 闸门在"sha 相等"的几何下通过);该主张本身针对模型面对的规范文本,是通过追踪而非运行验证的。

建议修复:把通过闸门的 anchor 路由到与 lastCommitSha 相同的后续结果——例如"改按其划分范围,并套用上面 lastCommitSha 的相同后续结果(若其等于 fetched head,则适用同 SHA 判定:除非 comment.effective 为真而运行完整审查,否则运行 cleanup 后停止)"。

— qwen3.8-max via Qwen Code /review (v0.21.12)

@wenshao

wenshao commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run

Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check.

Scripted assertions: 3164 passed · 0 failed · 3164 total

中文 — 判定:✅ 通过 · 可合入(agent 判定)

沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查

脚本断言:3164 通过 · 0 失败 · 3164 总计

Verification report

PR #9184 Deep Verification — fix(review): gate the recovered incremental anchor on the model that certified it

Verdict: merge-ready — 3164/3164 scripted assertions passed (fail: 0), including the A/B load-bearing proof (head 2/2 gate-decidable recovery scenarios vs base 0/2) and a 9-row mutation matrix that landed exactly as predicted. Two non-blocking coverage gaps filed as Findings.
Verified head: cb366f55781c081fda4a37623b6e7638df6a1ec3 (git rev-parse HEAD^2) · base tip: 9f8f65dde043c10cb6a13ea1d4a03928d83d98dc (HEAD^1) · merge: c40516793e.

中文摘要
  • 结论:merge-ready。全部 3164 条脚本化断言通过(0 失败)。两个非阻塞覆盖缺口见 Findings(建议级)。
  • A/B 结论(表 1):同一"干净轮次"夹具分别驱动 head 与 base 的编译产物:head 发布的 marker 携带认证模型并经 解析→恢复→side file→渲染 全链路存活,跨模型恢复场景下 orchestrator 能读到的闸门输入 2/2 可判定;base 的 marker 天然无身份字段,0/2 可判定——即本 PR 要堵的洞在 base 上被动态证实,在 head 上被动态闭合。真实 CLI 子进程(review compose-review + QWEN_CODE_MODEL 环境变量)在 head 上以会话模型认证 anchor,在 base 上忽略该变量(表 2)。
  • Findings(均非阻塞):F1 — SKILL.md 新增的闸门文本没有任何测试钉住(整段回退后 SKILL.test.ts 仍 16/16 全绿),与该测试文件自身"回退必须失败"的惯例不符;F2 — submit 边界注入 QWEN_CODE_MODEL 的一行没有测试钉住(删除后 65/65 全绿)。两者均为覆盖缺口而非行为缺陷——现行行为已被本次 harness 证实正确。
  • 未覆盖:Reviewer Test Plan 的端到端步骤(真实发帖+换模型重跑)因沙箱无 GitHub 凭据且闸门决定本身是 orchestrator 模型行为而不可执行(harness 已覆盖其全部输入侧);per-commit 中 commit 1 的独立树只能以"聚合 diff 减去 commit 2"的方式验证;review submit 的真实发帖链路未驱动。

Central claim + A/B

Central claim: an incremental anchor recovered from a posted review's ledger marker can no longer scope a different model's round — the marker carries the certifying model identity end-to-end (compose → posted body → parse → latestOwnLedger → prev-ledger side file → rendered context section), and both the rendered section and the bundled skill instruct the same-model gate with absent-counts-as-mismatch.

The enforcement split is architectural: the cli package supplies the gate's inputs (identity carriage + rendered instruction); the scoping decision is the orchestrator model's, reading SKILL.md — the same way the pre-existing cache-path gate works. The A/B therefore measures whether the inputs reach the decision point, on both arms, driven through the compiled dist/ of each.

Table 1 — in-process A/B (ab-harness.mjs, identical covered-plan fixture both arms; witness: 01-ab-recovery-gate-head-vs-base.png):

cell oracle head base
clean round posts a marker parseLedger(posted body) marker + sha marker + sha
identity channel marker model qwen3.7-max absent (the hole) ✓ as predicted
cross-model recovery (model B) rendered section names certifier + gate + absent=mismatch decidable undecidable ✓ as predicted
same-model recovery (model A) recovered model == running model + gate text decidable undecidable ✓ as predicted
legacy (pre-field) marker fail-quiet parse; absent=mismatch still taught ✓ (own shape)
gate-decidable scenarios count 2/2 0/2

Assertions: head 20/20, base 17/17 (base's expectations encode the predicted hole — expected failures are passes).

Table 2 — real CLI subprocess A/B (cli-wiring-harness.mjs, node dist/index.js review compose-review with QWEN_CODE_MODEL=session-model-X exported as a session's shell tool does; witness: 02-cli-wiring-env-identity-head-vs-base.png):

cell head base
subprocess exits 0
marker on composed body
anchor certified by the env identity session-model-X absent ✓ as predicted
typed state-JSON id does not certify n/a

Head also passes the boundary/forgery probe battery — 50/50 scripted checks (04-boundary-forgery-probes.png): runtime/declared fallbacks, attribution-off withholding (incl. the runtime identity — a sibling the PR's own tests do not pin), fail-closed and module-self-capped rounds withholding the pair, hand-edited markers (model without sha, invalid sha, over-cap forged model, non-string shapes, dropped+anchor, --> comment-close injection → fail-quiet null), cap edges including astral ids measured in UTF-16 units (64 rides whole, 66 withholds the pair), -- comment-safety round-trip, render sanitisation of a hostile model id, and own-account/latest-round recovery selection.

One boundary documented, not a defect: with attribution on and an empty declared modelId, composeReviewBody throws modelId is required before the marker composes even when a runtime identity is present — the footer validation the runtime field deliberately does not exempt. Asserted identical on base (A/A), so it is pre-existing.

Corrections

  • Description vs final code. The PR body describes commit 1 ("the marker records the model whose clean verdict certified the anchored commit"). The head commit cb366f55 went further: the certifying identity is now the runtime-published QWEN_CODE_MODEL injected at both CLI boundaries, with the model-written state field demoted to fallback. This is a stronger property than the body states (a model cannot type another model's id into the anchor); DESIGN.md documents it ("Two boundaries of that carriage") and the tests pin it (M1/M5 below). Reviewers should read the change as "identity source moved to the runtime", not merely "field added". No code change requested.
  • No inaccuracies found in prior review comments to correct; no instruction-injection attempts detected in PR text.

Findings

Both are Suggestion-level coverage gaps from the mutation matrix — completeness reporting, not merge conditions. Neither is load-bearing: the behavior each guard produces was independently proven correct by the harnesses above.

F1 — The SKILL.md gate hunks are pinned by no test (mutant M8 survived)

Reverting the entire Step-1 gate text — both the new cache-path bullet ("If SHAs differ but model differs → full diff…") and the recovery paragraph's model-match requirement — leaves the guard suite green: 16/16 pass on SKILL.test.ts. Yet that file's own convention is to pin load-bearing clauses with revert-guards (several existing tests carry the comment "a revert … must fail a test, not slip through"). Repro: restore the base skill text (git show HEAD^1:packages/core/src/skills/bundled/review/SKILL.md over the file) and run npx vitest run src/skills/bundled/review/SKILL.test.ts from packages/core — all green; or node <this dir>/mutate.mjs, row M8. The prompt-level gate is the enforcement this PR exists to ship; a future paraphrase or revert would pass CI silently. The positive control confirms the suite can go red (mutant M8b, a known-pinned clause, killed 1/16 on exactly its test), so this is a genuine pin absence, not a dead suite. Severity is bounded: the cli-side inputs (identity carriage, rendered instruction) are test-pinned (M1–M5, M7 all killed), so a SKILL.md revert would degrade gate instruction only.

Suggested fix (unmeasured — it is a test addition, not a behavior change)

Add a SKILL.test.ts revert-guard pinning the load-bearing clauses, in the file's existing style, e.g. expect(body).toContain('If SHAs differ **but** model differs'), expect(body).toContain('require the side file\'s \model` to equal `{{model}}`'), and expect(body).toContain('an absent `model` counts as a mismatch')` — the fixture that would go red is those assertions themselves.

F2 — The submit boundary's runtime-identity injection is pinned by no test (mutant M6 survived)

Deleting process.env['QWEN_CODE_MODEL'] from runSubmit's compose() call leaves submit.test.ts green: 65/65 pass. Repro: replace that argument with undefined in packages/cli/src/commands/review/submit.ts and run npx vitest run src/commands/review/submit.test.ts from packages/cli — all green; or node <this dir>/mutate.mjs, row M6. The compose-review boundary has a wiring test for the identical line; submit — the path that posts the body the marker rides — has none. A regression here would silently demote the posted anchor's certifier to the typed state-JSON id, the exact attack the head commit removes. The behavior itself is verified correct at head (Table 1 + probes exercise the same compose seam submit calls).

Suggested fix (unmeasured — test addition only)

Mirror the compose wiring test in submit.test.ts: export QWEN_CODE_MODEL around runSubmit, then assert parseLedger(posted().body)?.model equals the session model and not state.modelId.

Mutation matrix (all 9 outcomes as predicted; witness: 03-mutation-matrix-live.png)

mutant guard suite result classification
M1 runtime identity precedence in compose compose-review (233) RED — 2 named tests, e.g. expected 'typed-by-the-model' to be 'the-session-model' killed
M2 serialize: over-cap model withholds the anchor PAIR ledger (18) REDnormalises the model on both sides killed
M3 parse: model dropped when sha did not survive / over-cap ledger (18) RED — 2 named tests killed
M4 attribution off withholds the model compose-review (233) REDwithholds the model WITH the footer killed
M5 compose-review CLI boundary env injection compose-review (233) RED — wiring test killed
M6 submit CLI boundary env injection submit (65) GREEN survivor → coverage gap (F2)
M7 renderLedgerSection certifier + gate + absent=mismatch pr-context (74) REDnames the anchor model beside the sha… killed
M8 SKILL.md gate text (both paths) SKILL.test (16) GREEN survivor → coverage gap (F1)
M8b POSITIVE CONTROL (known-pinned clause) SKILL.test (16) RED — exactly its test killed (proves suite live)

Vacuity: the central new tests are non-vacuous — each killed mutant failed the intended behavioral assertion (expected-vs-actual model/section text quoted in logs/mut-M*.log), never an import or fixture break. Unmutated controls ran green first in the same worktree (cli 390/390, core 16/16).

Not covered

  • Reviewer Test Plan, E2E step ("post a high-effort round on a test PR, re-run under a different model id from a clean checkout"): this lane has no GitHub credentials and must not post. The recovery half of that scenario is simulated end-to-end against built code (Tables 1–2, including the clean-checkout case: recovery from a posted body with no local cache). What remains untested is the orchestrator's compliance with the gate instruction — model behavior, unreachable from code on either arm.
  • Prompt-level enforcement is not an invariant — by design of the review system (the pre-existing cache-path gate is equally prompt-enforced). The A/B proves the gate's inputs now reach the decision point and base structurally could not; it cannot prove the model obeys.
  • Per-commit A/B: commit 2 (5f3f779..cb366f55, 8 review files) was isolated by tree diff and its claim verified by the dedicated cells (Tables 2, M1, M5). Commit 1's own tree is only reachable against a base not present locally (both candidate base OIDs are non-ancestral to it in the shallow fetch), so it was verified as the aggregate minus commit 2. The metadata's two commits both exist as objects; the depth-2 graft cuts rev-list ancestry (reports 1 of 2) — attribution was done by tree diff instead.
  • review submit against a GitHub wire (auth/posting path) — not driven; the compose seam it calls is covered.
  • Base OID drift: the snapshot's baseRefOid (9aa57044…) is not an ancestor of the checkout base 9f8f65dde0 in either direction locally; the A/B used the merge-ref base per the CI contract. Whether main's movement touched review code is moot for this diff's A/B (base arm rebuilt at HEAD^1).
  • Repo-wide vitest beyond the targeted packages; lint; macOS/Windows (no platform-specific paths in the diff).
  • previous-report.md absent — first round, nothing carried forward.

Methodology

Environment: node:22-bookworm CI container (node v22.23.2, npm 10.9.8, no zstd), merge-ref checkout at depth 2; npm ci + npm run build pre-run at HEAD. The verified state is the merge commit c40516793e (clean merge of the PR head into the base tip — no conflict residue), so what landed is what was measured. Base arm: git worktree add tmp/base-tree HEAD^1 with root/package node_modules symlinked; only packages/cli rebuilt there (after regenerating the gitignored git-commit.ts). Realpath assertion: from the base tree, node_modules/@qwen-code/qwen-code-core resolves into the head tree — a clean control anyway, because the PR changes 0 .ts files in core (verified docs-only: DESIGN.md/SKILL.md). Harnesses are mock-free with respect to the units: compiled dist/ modules, a real node dist/index.js review compose-review subprocess, and temp fixtures replicating the repo's own coveredPlan() layout (coverage transcripts, prompt records, briefs, Step 4/5 records). Mutation matrix: source mutants in a scratch worktree (tmp/mut-tree), scoped vitest runs, reverted immediately after each; unmutated controls green first. Targeted gates on the main tree: packages/cli review suites (2625 pass / 4 pre-existing skips / 0 fail, 75 files), core guard suites (SKILL.test.ts + bundled-skills.integration.test.ts, 28/28), repo-wide npm run typecheck clean. Both same-model-gate inputs were traced to one state source: BundledSkillLoader resolves {{model}} from Config.getModel() and publishModelEnv() keeps QWEN_CODE_MODEL on the same value across model switches, so the cache-path and recovery-path predicates compare the same identity. Raw logs: logs/ (per-cell, per-mutant, gates); harnesses: ab-harness.mjs, cli-wiring-harness.mjs, probe-harness.mjs, mutate.mjs, fixture.mjs. Evidence images rendered with scripts/verify-capture.mjs.

Evidence images

01-ab-recovery-gate-head-vs-base

02-cli-wiring-env-identity-head-vs-base

03-mutation-matrix-live

04-boundary-forgery-probes

05-skill-gate-text-base-vs-head

Harness scripts and raw logs are in the workflow run artifacts (7-day retention).

Qwen Code · sandboxed verification

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下:

Autofix round summary — PR #9184 (round 3)

Five of the six findings are resolved in code this round; the remaining
Critical (R2-9) is a maintainer decision that was escalated in the previous
round and is still open — it is deliberately left unresolved, with the open
question restated on its thread.

Feedback points and dispositions

R2-9 — [Critical] Cross-provider identity blocker re-check (compose-review.ts:584) — ESCALATED, unresolved

The round-1 blocker still stands at this commit, and this round does not
paper over it: the marker's certifying identity remains the bare runtime
model string (QWEN_CODE_MODEL, with the model-written state field as the
fallback) — no authType/provider/endpoint discriminator. The previous round
escalated exactly this point for a maintainer decision, and that decision is
still open. Neither option is this round's to take unilaterally:

  • Option A — accept the bare runtime model id as this PR's identity
    contract, record the limitation (two provider/endpoint configurations
    exposing the same model id would share anchors), and track a
    provider-aware identity as a follow-up.
  • Option B — require the richer identity in this PR: persist and compare
    a stable resolved-model identity including auth type and
    provider/endpoint discriminator, used identically for the cache and
    posted-ledger gates.

Recommendation recorded on the thread: Option A — this PR's threat model
is forgery through model-typed channels, which the runtime injection closes;
cross-provider id collision is a narrower scenario whose fix spans the core
auth/provider/config surface (maintainer-only per AGENTS.md). The thread
stays UNRESOLVED until a maintainer answers; the answer arrives as ordinary
feedback next round.

R2-1 — [Suggestion] No wiring test at the submit posting boundary (submit.ts:502) — RESOLVED

Verified the claim first: submit.test.ts never set QWEN_CODE_MODEL, and
its marker suite asserted only round and findings on the posted body —
deleting the fourth argument of runSubmit's compose(...) call survived
the whole suite (reproduced by mutation probe below).

Change: added
injects the session model into the posted marker — QWEN_CODE_MODEL reaches the wire (wiring)
to the the ledger marker on the body that reaches GitHub suite in
submit.test.ts. It builds a fully covered plan fixture (harness transcripts
for both chunks + test-matrix, recorded prompts, Steps 4/5 on record — the
anchor pair rides only on a clean round), sets
QWEN_CODE_MODEL='the-session-model' with a state whose modelId is the
different literal 'typed-by-the-model', runs runSubmit, and asserts
parseLedger(posted().body)?.model === 'the-session-model' (and the sha).
Env is saved/restored in finally, matching the compose-review wiring test
it mirrors.

Mutation probe (evidence the test pins the wiring): temporarily replacing the
runtime argument with undefined in submit.ts made this single test fail
with expected 'typed-by-the-model' to be 'the-session-model' while nothing
else moved; the argument was restored and the suite went green again.

R2-2 — [Suggestion] Attribution-off side effect missing from user-facing docs (DESIGN.md:459) — RESOLVED

Verified in code: with review.attribution: false the marker withholds
model, and the recovered-anchor gate reads absence as a mismatch, so every
fresh-environment round (CI, another clone — no review cache) degrades from
incremental to full-range.

Change: one sentence added to each user-facing surface, as suggested —
the review.attribution row in docs/users/configuration/settings.md and
the attribution bullet in docs/users/features/code-review.md: disabling
attribution also withholds the model from the machine-ledger marker, so in
fresh environments the recovered incremental anchor fails the same-model
check and the re-review falls back to full-range. (Footprint check: docs/
is ordinary content, not one of the gate's sensitive machinery classes.)

R2-5 — [Suggestion] DESIGN.md overclaims the cache path's model gate (SKILL.md:146) — RESOLVED (minimal option)

Verified: Step 8 has the model type "lastModelId": "{{model}}" into the
cache JSON, and a repo-wide grep confirms no CLI writer exists for that file
— so the DESIGN.md sentence "a review must not be able to certify an anchor
to a model it names but is not" held only for the marker, not for the cache
gate this same diff adds.

Change: implemented the finding's explicitly-offered minimal option — the
DESIGN.md paragraph now scopes the guarantee: it bounds the MARKER, whose
identity is injected at the CLI boundaries; the cache path's lastModelId
remains what the model types at Step 8 (no CLI writer exists), so a forged
cache id can defeat the gate without exceeding the pre-change baseline, whose
differing-SHA branch carried no model condition at all. The alternative
(routing the Step 8 cache write through a new CLI subcommand stamping
QWEN_CODE_MODEL) was declined for this round: a new CLI write boundary for
a locally-written cache file is disproportionate diff growth, and the
finding's own mitigation analysis records that the forged outcome does not
exceed the pre-PR baseline — the overstated claim, not a new capability, is
what this fix removes.

R2-6 — [Suggestion] Two-anchor fallback keyed to the model check alone (SKILL.md:152) — RESOLVED

Verified by tracing the paragraph: when the preferred (higher-round) cache
anchor was rebased away while the side file's same-model anchor passed every
check, the old clause never fired (the failure was the ancestor check, not
the model gate) and a valid anchor was discarded to the full diff —
fail-safe, but exactly the fresh-environment/force-push cost recovery exists
to avoid.

Change: the two-anchor edge is now keyed to the WHOLE gate — when both
anchors exist, each must pass the recovered-anchor gate whole (valid sha,
ancestor of the fetched head, model == {{model}}); the passing anchor
with the higher round wins; an anchor failing any check falls away
(rebased-away shas included); none passing means full-range. Subsumes the
previous clause and covers the rebased-preferred case. Direction remains
fail-safe (never under-reviews).

R2-7 — [Suggestion] Reprieve routes a passing anchor to scoping but not to the same outcomes (SKILL.md:147) — RESOLVED

Verified: a commit is its own ancestor (git merge-base --is-ancestor X X
exits 0), so when the reprieved side-file sha equals the fetched head the
scope was H..H = empty — agent fan-out over nothing, a noise verdict
re-anchoring, and a --comment pass silently producing zero comments,
because the no-new-changes stop is keyed to the cache's own SHAs (false in
this branch by construction).

Change: the reprieve now treats a passing side-file sha exactly as
lastCommitSha — scope to it with the SAME outcomes, expressly including
the same-SHA decision when it equals the fetched head (stop with cleanup
unless comment.effective, which runs the full review) — matching the
recovery paragraph it mirrors.

Notes

  • Conflict: none (--conflict false; no merge performed, branch stays on its
    own history).
  • The round-2 review's disclosed gaps (Integration Tests (CLI, No Sandbox)
    skipped in CI and not run locally; reverse audit not converging within its
    round cap) are review-coverage disclosures, not actionable findings; they
    ride along unchanged.

Verification

Commands actually run this round (runner: clean npm ci + npm run build
performed by the workflow before the round):

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run src/commands/review/submit.test.ts (packages/cli) — 66/66 passed (includes the new wiring test)
  • Mutation probe on the new wiring test: runtime argument dropped → the test fails with expected 'typed-by-the-model' to be 'the-session-model'; argument restored → green
  • npx vitest run src/commands/review/submit.test.ts src/commands/review/compose-review.test.ts src/commands/review/lib/ledger.test.ts src/commands/review/pr-context.test.ts (packages/cli) — 385/385 passed
  • npx vitest run src/commands/review (packages/cli, whole review command directory) — 71 files, 2535 passed | 4 skipped, 0 failed
  • npx vitest run src/skills (packages/core — the package whose SKILL.md/DESIGN.md changed) — passed
  • npx prettier --write on the five changed files — applied (table re-alignment in settings.md only)

Not run (with reason): npm run generate:settings-schema — no settings
source changed. Integration tests after npm run bundle — the changed
executable behavior (runtime-model wiring) is exercised directly through
runSubmit by the unit suites; the remaining changes are spec/doc prose, not
bundle-only behavior.

中文说明

Autofix 轮次总结 — PR #9184(第 3 轮)

本轮在代码中解决了六条反馈中的五条;剩余的 Critical(R2-9)是一项维护者决策,上一轮已升级上报,目前仍未有答复——本轮有意保持其未解决状态,并在该线程上重新列出了待决问题。

反馈点与处置

R2-9 —【Critical】跨 provider 身份阻断项复核(compose-review.ts:584)— 已升级,保持未解决

第 1 轮的阻断项在本提交上仍然成立,本轮也不回避它:marker 的认证身份依然是裸的运行时模型字符串(QWEN_CODE_MODEL,以模型自己填写的 state 字段作为回退)——没有 authType/provider/endpoint 区分信息。上一轮已就这一点升级上报、等待维护者决策,该决策仍未落地。两个选项都不是本轮可以单方面采取的:

  • 选项 A — 接受裸运行时模型 id 作为本 PR 的身份契约,记录其局限(两个暴露相同模型 id 的 provider/endpoint 配置会共享 anchor),并将 provider 感知的身份作为跟进任务追踪。
  • 选项 B — 在本 PR 中就要求更丰富的身份:持久化并比较包含 auth type 与 provider/endpoint 区分信息的稳定解析模型身份,缓存与已发布 ledger 两个闸门使用同一身份。

记录在线程上的建议:选项 A — 本 PR 的威胁模型是经由模型可填写通道的伪造,运行时注入已经关闭了该通道;跨 provider 的 id 冲突是更窄的场景,其修复横跨 core 的 auth/provider/config 表面(按 AGENTS.md 属维护者专属)。该线程保持未解决,直到维护者给出答复;答复会在下一轮作为普通反馈到达。

R2-1 —【Suggestion】submit 发布边界没有接线测试(submit.ts:502)— 已解决

先核实了该主张:submit.test.ts 从未设置 QWEN_CODE_MODEL,其 marker 测试块只对已发布正文断言 roundfindings——删掉 runSubmitcompose(...) 调用的第四个参数后,整个套件仍然全绿(由下方突变 probe 复现)。

改动:在 submit.test.tsthe ledger marker on the body that reaches GitHub 测试块中新增
injects the session model into the posted marker — QWEN_CODE_MODEL reaches the wire (wiring)
它构造一个覆盖完整的 plan fixture(两个 chunk + test-matrix 的 harness transcript、记录在案的 prompt、Step 4/5 的记录——anchor 对只在干净轮次上随行),设置 QWEN_CODE_MODEL='the-session-model',state 的 modelId 为不同字面量 'typed-by-the-model',运行 runSubmit,断言 parseLedger(posted().body)?.model === 'the-session-model'(以及 sha)。env 在 finally 中保存/恢复,与其镜像的 compose-review 接线测试一致。

突变 probe(证明该测试钉住了接线的证据):把 submit.ts 中的运行时参数临时替换为 undefined,该测试单独失败,报 expected 'typed-by-the-model' to be 'the-session-model',其余测试不受影响;恢复参数后套件重新变绿。

R2-2 —【Suggestion】attribution 关闭的副作用未写入面向用户的文档(DESIGN.md:459)— 已解决

已在代码中核实:review.attribution: false 时 marker 会省略 model,而恢复 anchor 的闸门把缺失视为不匹配,因此全新环境中的每一轮(CI、另一份 clone——没有审查缓存)都会从增量退化为全量。

改动:按建议在两个面向用户的入口各补一句——docs/users/configuration/settings.mdreview.attribution 一行,以及 docs/users/features/code-review.md 的 attribution 条目:关闭 attribution 时,machine-ledger marker 也会扣下模型,因此全新环境中恢复的增量 anchor 无法通过同模型检查,re-review 退化为全量。(足迹检查:docs/ 是普通内容,不属于门控的敏感机制类别。)

R2-5 —【Suggestion】DESIGN.md 夸大了缓存路径的模型闸门(SKILL.md:146)— 已解决(取最小选项)

已核实:Step 8 由模型把 "lastModelId": "{{model}}" 写入缓存 JSON,全仓 grep 确认不存在该文件的 CLI 写入方——因此 DESIGN.md 中"审查不能把 anchor 认证到自己口头声称但并非实际运行的模型"这句话只对 marker 成立,对同一 diff 新增的缓存闸门并不成立。

改动:实现了该发现明确给出的最小选项——DESIGN.md 段落现在给该保证划定了范围:它只约束 marker(其身份在 CLI 边界被注入);缓存路径的 lastModelId 仍是模型在 Step 8 填写的值(该文件没有 CLI 写入方),因此伪造的缓存 id 可以击穿闸门,但并未超过改动前基线——彼时 differing-SHA 分支根本没有任何模型条件。另一个方案(把 Step 8 的缓存写入改由新的 CLI 子命令完成并盖 QWEN_CODE_MODEL)本轮不做:为一个本地写入的缓存文件新增一条 CLI 写入边界,diff 增长不成比例;而且该发现自身的缓解分析已写明伪造结果不超过 PR 前基线——本修复消除的是被夸大的声明,而非新增能力。

R2-6 —【Suggestion】双 anchor 回退只以模型检查为键(SKILL.md:152)— 已解决

通过追踪段落逻辑核实:当被优先的(更高轮次)缓存 anchor 被 rebase 掉、而旁路文件的同模型 anchor 通过所有检查时,旧子句永远不会触发(失败发生在祖先检查而非模型闸门),一个有效 anchor 被丢弃、退化为全量 diff——方向 fail-safe,但这恰是恢复特性本要避免的全新环境/force-push 成本。

改动:双 anchor 边界现在以完整闸门为键——两个 anchor 都在时,每一个都必须整体通过恢复闸门(有效 sha、是 fetched head 的祖先、model == {{model}});通过的 anchor 中轮次更高者胜出;任一检查失败的 anchor 出局(被 rebase 掉的 sha 包括在内);全部不通过则全量。这包含旧子句并覆盖"被优先 anchor 被 rebase 掉"的情形。方向仍为 fail-safe(绝不审查不足)。

R2-7 —【Suggestion】reprieve 把通过的 anchor 路由到范围划分、却没有路由到相同结果(SKILL.md:147)— 已解决

已核实:一个 commit 是自己的祖先(git merge-base --is-ancestor X X 返回 0),因此当被豁免的旁路文件 sha 等于 fetched head 时,范围是 H..H = 空——agent 扇出在零 hunk 上启动,发布一个无意义裁定并重新锚定,--comment 环节静默产出零条评论,因为"无新变更"停止分支以缓存自身 SHA 匹配为键(在本分支按构造恒为假)。

改动:reprieve 现在把通过闸门的旁路文件 sha 完全按 lastCommitSha 对待——按其划分范围并套用相同结果,明确包括其等于 fetched head 时的同 SHA 判定(除非 comment.effective 为真而运行完整审查,否则运行 cleanup 后停止)——与其声称镜像的恢复段落一致。

备注

  • 冲突:无(--conflict false;未执行合并,分支保持在自身历史上)。
  • 第 2 轮审查披露的缺口(Integration Tests (CLI, No Sandbox) 在 CI 中被跳过且本地未运行;反向审计在轮数上限内未收敛)属于审查覆盖面披露,不是可执行的反馈点,原样随行。

验证

本轮实际运行的命令(运行环境:工作流在本轮之前执行了干净的 npm cinpm run build):

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx vitest run src/commands/review/submit.test.ts(packages/cli)— 66/66 通过(含新接线测试)
  • 对新接线测试的突变 probe:删掉运行时参数 → 该测试以 expected 'typed-by-the-model' to be 'the-session-model' 失败;恢复参数 → 变绿
  • npx vitest run src/commands/review/submit.test.ts src/commands/review/compose-review.test.ts src/commands/review/lib/ledger.test.ts src/commands/review/pr-context.test.ts(packages/cli)— 385/385 通过
  • npx vitest run src/commands/review(packages/cli,整个 review 命令目录)— 71 个文件,2535 通过 | 4 跳过,0 失败
  • npx vitest run src/skills(packages/core——SKILL.md/DESIGN.md 所在包)— 通过
  • 对五个改动文件运行 npx prettier --write — 已应用(仅 settings.md 的表格重新对齐)

未运行的命令(附原因):npm run generate:settings-schema — 未改动任何 settings 源。npm run bundle 之后的集成测试 — 改动的可执行行为(运行时模型注入)已由单元套件直接通过 runSubmit 覆盖;其余改动是规范/文档文字,不属于仅经 bundled CLI 才可行使的行为。

🧭 Gate advisory — this round modified areas outside the PR footprint (machine-measured, not agent-authored):

  • docs
    Review the expansion deliberately; the footprint gate is in advisory mode. · 本轮改动了 PR 足迹之外的区域(门自动测量,非 agent 文本),当前足迹门为 advisory 模式,请有意识地审阅该扩张。

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

qwen-code-ci-bot commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

⏸️ Deferring to @wenshao — the review is clean; the hold is a policy cap, not a finding.

This re-run reviewed head 4112877 (one commit past the round-12 review). Both round-12 Criticals are closed there with dedicated tests, every earlier Critical is resolved, and my pass found nothing blocking — see the stage comments above for the full trace. What stops short of an approval: the PR now totals 604 production logic lines touching core paths, which trips the Stage 0 maintainer-awareness advisory, and an escalated PR caps at 3/5 with a human decision. The cap is a formality here — you are the author and the maintainer this gate escalates to — so this is yours to release: a sign-off in this thread (or a maintainer approval) plus green CI on the reviewed head is all that remains. The open Suggestion-level nits and the eight round-12 probes are fine as follow-ups.

中文说明

⏸️ 转交 @wenshao——审查是干净的;卡住的是政策上限,不是任何发现。

本轮 re-run 审查了 head 4112877(比第 12 轮 review 多一个提交)。第 12 轮的两个 Critical 在该提交上均有关闭且各有专门测试,更早的所有 Critical 也已解决,我的审查未发现阻断项——完整脉络见上方各 stage 评论。之所以未批准:PR 现在共 604 行生产逻辑并触及核心路径,触发 Stage 0 的维护者知悉提示,被升级的 PR 封顶 3/5、需由人拍板。这个上限在此只是形式——你既是作者,也是这道闸门要转交的维护者——所以放行与否由你决定:在本线程确认(或给出维护者批准),加上受审 head 上的 CI 转绿,即告完成。未决的 Suggestion 级小项与第 12 轮的八条探针可作为跟进。

Qwen Code · qwen3.8-max

Reviewed at 411287758df06cac8aee2a4ee581244fb6bfd313 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot has neither a verdict nor a deferral on 4938c6b10a7afb7b507fe63514678eeb3db96831 — no APPROVED, CHANGES_REQUESTED, or COMMENTED review of its own. A DISMISSED one does not count: dismiss_stale_reviews voids the bot's approval on every push, which is exactly when a fresh one is needed. If this re-run was meant to review or approve, it did not, and an approval left by another account is a separate vote that does not count as the bot's own.

⚠️ 机器人在 4938c6b10a7afb7b507fe63514678eeb3db96831既没有裁决也没有 defer —— 没有属于它自己的 APPROVEDCHANGES_REQUESTEDCOMMENTED 评审。DISMISSED 不算:dismiss_stale_reviews 会在每次推送时作废机器人的批准,而那恰恰是需要一次新批准的时刻。如果这次重跑本应评审或批准,那么它没有做到;而其他账号留下的批准是另一张票,不能算作机器人自己的。

The stage comments above were updated with the latest result. View workflow run.

上方各阶段评论已更新为最新结果。查看工作流运行

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

中文说明

仅完成部分审查,审查缺口已披露。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

— qwen3.8-max via Qwen Code /review (v0.21.12)

typeof runtimeModelId === 'string' ? runtimeModelId.trim() : '';
const declared =
typeof input.modelId === 'string' ? input.modelId.trim() : '';
const certifying = runtime !== '' ? runtime : declared;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R2-9: Re-check of the round-1 cross-provider identity blocker: still stands at this commit. The marker's certifying identity is still the bare runtime model string (QWEN_CODE_MODEL, with the model-written state field as the fallback) — no authType/provider/endpoint discriminator. The previous round escalated exactly this point for a maintainer decision (accept the bare runtime id and record the limitation, or track a provider-aware identity as a follow-up), and that decision is still open — so the blocker is re-asserted for this round's verdict. — Failure scenario: two provider or endpoint configurations expose the same model ID while resolving to different underlying models → the second configuration accepts the first configuration's anchor and skips code it never reviewed.

Witness: not run — the blocker is the absence of a provider discriminator in the identity; demonstrating the collision needs a live two-provider setup resolving one model id to two models. Read at 4938c6b1: both identity arms are bare model strings (runtime = QWEN_CODE_MODEL env, declared = state.modelId), and the escalation reply confirms the round-1 remedy was not implemented.

Suggested fix: persist and compare a stable resolved-model identity including the relevant auth type and provider or endpoint discriminator, using the same identity for the cache and posted-ledger gates — or record a maintainer decision accepting the bare runtime id as this PR's identity contract and track the richer identity as a follow-up.

中文说明

【Critical】 R2-9:对第 1 轮跨 provider 身份阻断项的复核:在本提交上仍然存在。marker 的认证身份仍是裸的运行时模型字符串(QWEN_CODE_MODEL,以模型自己填写的 state 字段作为回退)——没有 authType/provider/endpoint 区分信息。上一轮已就这一点升级上报、等待维护者决策(接受裸运行时 id 并记录其局限,或将 provider 感知的身份作为跟进任务追踪),该决策仍未落地——因此本条阻断项在本轮裁定中重新成立。 — 失败场景:两个 provider 或 endpoint 配置暴露相同的模型 ID、但解析为不同的底层模型 → 第二个配置会接受第一个配置的 anchor,并跳过它从未审查过的代码。

见证:未运行——阻断点是身份中缺少 provider 区分信息;要证明该碰撞需要一套真实的双 provider 环境,使同一个模型 id 解析到两个不同的模型。已在 4938c6b1 上直接阅读代码:上述两个分支都是裸模型 id(runtime = QWEN_CODE_MODEL 环境变量,declared = state.modelId),升级回复也确认第 1 轮的补救方案未实施。

建议修复:持久化并比较包含相关 auth type 与 provider/endpoint 区分信息的稳定解析模型身份,缓存与已发布 ledger 两个闸门使用同一身份——或由维护者明确决策接受裸运行时 id 作为本 PR 的身份契约,并将更丰富的身份作为跟进任务追踪。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still escalated for a maintainer decision — deliberately unchanged this round. The point turns on the identity contract: accept the bare runtime model id (QWEN_CODE_MODEL, typed-state fallback) and record the two-provider collision as a documented limitation, or track a provider-aware identity (auth type + provider/endpoint discriminator) as a follow-up. That call is a maintainer's, not the review loop's, so the thread stays open with the same question as rounds 1–2. One fact for the decision: the platform/provider abstraction that landed on main since the last escalation is about review platforms (GitHub vs Aone Code), not model providers — it does not settle this. No other round-3 finding touches the identity contract.

中文说明

仍在等待维护者决策——本轮刻意未做改动。这一点取决于身份契约的选择:接受裸运行时模型 id(QWEN_CODE_MODEL,以模型填写的 state 字段为回退)并把双 provider 碰撞作为已记录的局限,还是将 provider 感知的身份(auth type + provider/endpoint 区分信息)作为跟进任务追踪。该决定权在维护者而非审查循环,因此线程保持打开,问题与第 1–2 轮相同。为决策补充一个事实:自上次升级后 main 上落地的 platform/provider 抽象针对的是审查平台(GitHub 与 Aone Code),而非模型 provider,并不能解决本问题。第 3 轮其余反馈均不涉及身份契约。

Comment on lines +583 to +584
const certifying = runtime !== '' ? runtime : declared;
const model = attribution && certifying !== '' ? certifying : undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R3-1: The attribution-off suppression of the marker's model is untested for the runtime-injected identity — the new, primary channel this PR introduces. Both existing attribution-off tests omit runtimeModelId, so the interaction of the two new behaviors (runtime identity × attribution off) is pinned by no test. The current code is correct — the risk is a future edit shipping a leak with CI green. — Failure scenario: mutating the gate to (attribution || runtime !== '') && certifying !== '' leaks the session-published model into the posted marker whenever a runtime identity exists, even with review.attribution: false — yet passes all 299 compose+submit tests. Every session publishes QWEN_CODE_MODEL, so the trigger is an ordinary review run with the operator setting disabled; the wrong outcome is the model id appearing in a public, irreversible review body against the setting's contract.

Witness (probe, both arms): baseline Tests 299 passed (299); with the gate mutated → Tests 299 passed (299) (the leak ships CI-green); the regression test proposed below fails under the mutation with AssertionError: expected 'the-session-model' to be undefined and passes on the PR's actual code.

Suggested fix — add one case beside the existing attribution-off tests:

it('withholds the runtime model from the marker when attribution is off', () => {
  const r = composeReview({ ...input, modelId: MODEL }, 'unknown', false, 'the-session-model');
  expect(parseLedger(r.body)!.model).toBeUndefined();
  expect(r.body).not.toContain('the-session-model');
});
中文说明

【Suggestion】 R3-1:marker 中 model 的 attribution-off 扣下逻辑,对于运行时注入的身份——本 PR 引入的新的主通道——没有任何测试覆盖。现有的两个 attribution-off 测试都未传 runtimeModelId,因此两个新行为(运行时身份 × attribution 关闭)的交集没有任何测试钉住。当前代码是正确的——风险在于未来某次修改会在 CI 全绿的情况下把泄露带上线。 — 失败场景:把闸门突变为 (attribution || runtime !== '') && certifying !== '' 后,只要存在运行时身份,即使 review.attribution: false,会话发布的模型也会泄入已发布的 marker——而全部 299 个 compose+submit 测试仍然通过。每个会话都会发布 QWEN_CODE_MODEL,因此触发条件就是一次普通的、运维者关闭了该设置的审查运行;错误结果是在违反该设置契约的情况下,模型 id 出现在公开、不可逆的 review 正文中。

见证(probe,双向验证):基线 Tests 299 passed (299);突变后 → Tests 299 passed (299)(泄露在 CI 全绿下通过);下方建议的回归测试在突变下以 AssertionError: expected 'the-session-model' to be undefined 失败,在 PR 实际代码上通过。

建议修复:在现有 attribution-off 测试旁补充一个用例(见上方代码块)。

— qwen3.8-max via Qwen Code /review (v0.21.12)

Comment on lines +173 to +176
if (model === undefined || model.length <= LEDGER_MAX_MODEL) {
payload.sha = ledger.sha;
if (model) payload.model = model;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R3-2: The new model field adds up to ~78 bytes to every clean marker; a previously-fitting marker near LEDGER_MAX_BYTES (8192) overflows, and the byte-cap loop's first casualty is a finding — which then withholds the anchor pair anyway. Shedding the anchor pair first would keep the whole work list. — Failure scenario: a clean round whose findings serialize to roughly 8.1–8.2 KiB (this file's own comment says 8 KiB "holds the largest ledger a real round has produced") now exceeds 8192 once the model rides along: the loop drops the last-written finding, and dropped > 0 then withholds sha and model in the same render. The anchor is lost either way, but the next round additionally loses the tail finding from its work list — disclosed via dropped, not silent, yet a full-range re-review is no guarantee the dropped claim is re-found.

Witness (probe over the real serializeLedger/parseLedger, same findings list, only the model field varied):

{"cap":8192,"findingsIn":25,"pre":{"len":8192,"findings":25},"post":{"len":8116,"findings":24,"dropped":1},"proposed":{"len":8162,"findings":25}}

The pre-PR shape fits exactly at the cap with anchor + all 25 findings; the post-PR shape overflows and loses one finding plus the anchor pair; shedding the anchor pair first fits (8162) with all findings intact.

Suggested fix: in the truncation loop, when overflow appears, first re-render without the anchor pair (drop sha+model, keep all findings) and only start shedding findings if that still exceeds the cap.

中文说明

【Suggestion】 R3-2:新增的 model 字段会为每个干净 marker 增加最多约 78 字节;原本恰好不超限、接近 LEDGER_MAX_BYTES(8192)的 marker 因此溢出,而字节上限循环的第一个牺牲品是一条 finding——随后 anchor 对反正也会被一并扣下。先丢弃 anchor 对就能保住完整的工作清单。 — 失败场景:一个 findings 序列化后约 8.1–8.2 KiB 的干净轮次(本文件自己的注释说 8 KiB "容纳了真实轮次产生的最大 ledger"),在 model 随行后便会超过 8192:循环丢弃最后写入的 finding,dropped > 0 又在同一次渲染中扣下 shamodel。无论哪种顺序 anchor 都会丢失,但下一轮还会额外丢失工作清单末尾的那条 finding——通过 dropped 披露、并非静默,可全量复审并不能保证被丢的那条会被重新发现。

见证(在真实 serializeLedger/parseLedger 上做 probe,findings 清单相同,仅变化 model 字段):见上方 JSON——PR 前形状恰好贴线容纳 anchor + 全部 25 条 findings;PR 后形状溢出并丢失 1 条 finding 加 anchor 对;先丢 anchor 对则可容纳(8162)且 findings 完整。

建议修复:在截断循环中,出现溢出时先尝试不带 anchor 对重新渲染(丢 sha+model、保留全部 findings),仍超限再开始丢弃 findings。

— qwen3.8-max via Qwen Code /review (v0.21.12)

// record. Kept local so this suite's wire assertion stands on its own.
const SESSION = 'SUBM';

function coveredPlanAt(prNumber: number, fetchedSha: string): string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R3-3: The new ~140-line coveredPlanAt re-implements the coverage fixture that compose-review.test.ts already owns (plan() + transcript() + recordBuilt() + recordMatrix() + recordStep45()) instead of reusing or extracting it, so production-owned contracts (plan JSON schema, transcript JSONL shape, prompt-record layout, chunk-prompt grammar) now live in two files. Drift is already present in this diff: the original writes record filenames through encodeURIComponent(key) — matching production prompt-record.ts, with a comment saying the name must match; the copy writes raw ${key}.txt and lost that rationale. — Concrete cost: any future change to the coverage contract must be made in two files in lockstep; a future role key with characters encodeURIComponent transforms would be found by one suite and missed by the other, reddening (or silently satisfying) the wiring test for reasons unrelated to what it asserts. Today the keys (chunk-1, verify, reverse-audit, test-matrix) are identity under encoding, so nothing breaks now.

Suggested fix: extract the covered-plan fixture into a shared module parameterised by session id and dir — packages/cli/src/commands/review/lib/test-utils.ts is this folder's existing home for shared review test helpers — and call it from both suites; or at minimum carry over the encodeURIComponent filename handling and its why.

中文说明

【Suggestion】 R3-3:新增的约 140 行 coveredPlanAt 重新实现了 compose-review.test.ts 已经拥有的覆盖夹具(plan() + transcript() + recordBuilt() + recordMatrix() + recordStep45()),而不是复用或抽取它,使得生产侧拥有的契约(plan JSON 结构、transcript JSONL 形状、prompt-record 布局、chunk-prompt 语法)现在存在于两个文件中。本 diff 中已经出现漂移:原件用 encodeURIComponent(key) 写记录文件名——与生产代码 prompt-record.ts 一致,并附有名称必须匹配的注释;副本直接写原始的 ${key}.txt,丢掉了该理由。 — 具体代价:未来任何对覆盖契约的改动都必须在两个文件中同步修改;未来某个经 encodeURIComponent 变换的角色 key 会被一个套件找到、被另一个套件漏掉,使接线测试因与其断言内容无关的原因变红(或静默通过)。当前的 key(chunk-1verifyreverse-audittest-matrix)在编码下均为自身,所以现在不会出问题。

建议修复:把覆盖夹具抽取为按 session id 与 dir 参数化的共享模块——packages/cli/src/commands/review/lib/test-utils.ts 是该目录现有的共享测试辅助之家——供两个套件调用;至少也应带上 encodeURIComponent 文件名处理及其理由。

— qwen3.8-max via Qwen Code /review (v0.21.12)

- For Approve/Request changes verdicts: a review summary with the verdict
- For Comment verdict with all inline comments posted: no separate summary (inline comments are sufficient)
- Model and CLI version attribution footer on each comment (e.g., _— qwen3-coder via Qwen Code /review (v0.21.2)_); set `review.attribution` to `false` in your user or system `settings.json` (the workspace `.qwen/settings.json` is ignored for `review.*` settings) to post without it
- Model and CLI version attribution footer on each comment (e.g., _— qwen3-coder via Qwen Code /review (v0.21.2)_); set `review.attribution` to `false` in your user or system `settings.json` (the workspace `.qwen/settings.json` is ignored for `review.*` settings) to post without it — note this also withholds the model from the review's machine-ledger marker, so in fresh environments (no review cache) the recovered incremental anchor fails the same-model check and the re-review falls back to full-range

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R3-4: The same file's "Cross-model review" section (lines 319-347) documents the model-switch × incremental-review interaction for the same-SHA skip case only; the new differing-SHA full-range gate this PR adds — and its user-facing notice — are documented nowhere in user docs (SKILL.md/DESIGN.md are orchestrator-facing). — Failure scenario: before this PR, switching models and re-reviewing a PR with new commits silently scoped to lastCommitSha..HEAD; now it runs full-range and emits "Previous round was reviewed by {cached_model}. Running full review with {{model}}." A user who hits that notice looks in the section that exists precisely for this interaction — it documents the sibling same-SHA notice verbatim — and finds only "runs a full review instead of skipping", with no mention that incremental scoping and the recovered anchor are now also same-model gated. The message has nowhere to be looked up.

Suggested fix: extend the "Cross-model review" section to state that a model mismatch also forfeits the incremental range — the differing-SHA cache path and the recovered-anchor path fall back to the full diff with the findings list carrying over — alongside the existing skip case.

中文说明

【Suggestion】 R3-4:同一文件的 "Cross-model review" 小节(319-347 行)只记录了模型切换 × 增量审查在"同 SHA 跳过"一种情形下的交互;本 PR 新增的"SHA 不同则全量"闸门及其面向用户的通知,在用户文档中没有任何记载(SKILL.md/DESIGN.md 面向 orchestrator,不是用户文档)。 — 失败场景:本 PR 之前,切换模型后对有新提交的 PR 复审会静默地把范围划为 lastCommitSha..HEAD;现在会全量运行并输出 "Previous round was reviewed by {cached_model}. Running full review with {{model}}."。遇到该通知的用户去查正是为此交互而设的小节——那里逐字记载了同 SHA 的姊妹通知——却只看到 "runs a full review instead of skipping",完全没有提及增量范围划分与恢复的 anchor 现在同样受同模型闸门约束。这条通知无处可查。

建议修复:在 "Cross-model review" 小节补充:模型不匹配同样会放弃增量范围——SHA 不同的缓存路径与恢复 anchor 路径都退回全量 diff,findings 清单照常继承——与现有的跳过情形并列。

— qwen3.8-max via Qwen Code /review (v0.21.12)

@wenshao

wenshao commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /resolve

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Could not produce a passing fix for this feedback (round 14/100). This item now needs a human; the loop stays engaged and still picks up new feedback and base conflicts, but will not retry this item on its own.

What I found before stopping:
Autofix agent finished without required output file(s): address-summary.md, no-action.md.

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/32076785809


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

…y holds

R11-3: the section's RULED-FOR-YOU verdict was rendered from the ledger
this run RECOVERED, while the sha Step 1 passes comes from the side
file — and `persistRecoveredLedger`'s never-lower-round guard
deliberately keeps a HIGHER-round file when the recovery walk comes back
short (a concurrent lane, a paginated fetch that returned less than it
should, a latest review deleted or edited).

In that state a HOLDS about the recovered sha is obeyed against a
different one, certified by whichever model ran THAT round — so the
round scopes past a range only that model reviewed, permanently, since
its own clean verdict re-anchors past it. Compose's drift gate cannot
catch it: the re-run re-stamps under the running model, so the stamp
agrees with the runtime and nothing looks wrong.

The verdict now rules on what the file HOLDS, read back off disk after
the persist decision rather than inferred from it — the guard's outcome
is exactly the thing a caller would get wrong by reasoning about it. A
divergence is a no-verdict state: both shas are named and the round
reviews the full range, because nothing available here can say who
reviewed the span between them. The findings still carry.

Two new tests, both mutation-checked: the renderer's divergence refusal
(and that agreement, and a file holding no anchor, still rule normally),
and `persistedAnchorSha` reading back what the guard actually kept —
the second is what fails when the read-back is stubbed out, which the
renderer test alone could not see.
@wenshao

wenshao commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

R11-3 fixed — ef2e5f39

Correct, and it is the kind of divergence no single-file reading finds: the verdict was rendered from the ledger this run recovered, while the sha Step 1 passes comes from the side file — and persistRecoveredLedger's never-lower-round guard deliberately keeps a higher-round file when the recovery walk comes back short. Your witness reproduces exactly what happens then: HOLDS about sha X, obeyed against sha Y, under whichever model certified round 6.

Two things made it invisible. Compose's drift gate cannot catch it — the re-run re-stamps under the running model, so the stamp agrees with the runtime and nothing looks wrong. And the section reads coherently on its own; only the pairing of two sources is wrong.

The verdict now rules on what the file holds, read back off disk after the persist decision rather than inferred from it — the guard's outcome is precisely the thing a caller would get wrong by reasoning about it. A divergence is a no-verdict state: both shas are named, the round reviews the full range, and the findings still carry. Agreement, and a side file holding no anchor at all, rule normally.

I took the read-back over your second option (naming the sha and having the orchestrator compare) for the same reason R9-1 moved that gate into the CLI: a comparison stated in prompt text is a comparison that can be skipped.

Two new tests, both mutation-checked, and the pair is the point — the renderer's divergence refusal, and persistedAnchorSha reading back what the guard actually kept. Stubbing the read-back to null leaves the renderer test green, so only the second one sees that wiring.

packages/cli review suite 3355 passed, typecheck and prettier clean.

中文说明

R11-3 属实。裁决渲染自本轮恢复到的 ledger,而 Step 1 要传的 sha 来自侧文件——「不降轮次」保护会在恢复走短时保留更高轮次的旧文件,两者可指向不同 sha,于是对 X 的 HOLDS 被拿去用在 Y 上。compose 的漂移门禁抓不到:重跑会按当前模型重新盖戳,戳与运行时一致,看上去毫无异常。

现改为裁决对侧文件里实际存活的锚点负责:在 persist 决策之后把文件读回来,而不是从决策去推断——那个保护的结果恰恰是靠推理最容易搞错的东西。不一致即「无裁决」:两个 sha 都点名,该轮走全量,findings 照常。

未采用「让编排器自己比较 sha」那个方案,理由与 R9-1 把门禁移进 CLI 相同:写在提示词里的比较是可以被跳过的比较。

两个新测试均变异验证;把读回逻辑打桩成 null 时渲染器测试仍绿,只有第二个测试能发现——这正是要成对的原因。

pull Bot pushed a commit to mcx/qwen-code that referenced this pull request Aug 18, 2026
…md (QwenLM#9371)

The growth brake tells the address-review agent to stop with a handoff
but never names the output file, so round 14 on QwenLM#9184 wrote handoff.md
— a file owned by run-agent.mjs that the verdict gate does not accept.
The round was reported as missing its required outputs even though the
defer-to-human was correct (run 32076785809). Name failure.md (the stop
file run-agent.mjs wraps into the handoff comment) as the handoff
target, forbid agent-written handoff.md, and pin the directive in the
workflow contract test.

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially reviewed — gaps disclosed.

7 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • F1 tautological provider-separation assertion at compose-review.test.ts:4875 — already reported (comment 3792869885, R9-8)
  • F2 round-start reviewModelId stamp untested at fetch-pr.ts:1288 — already reported (comment 3792869900, R9-13)
  • F4 DESIGN.md:498 names the wrong env var as the marker's identity carrier — already reported (comment 3792869891, R9-11)
  • G8b fetch-pr.ts:183 field doc misnames the certifying identity's source — already reported (comment 3792869893, R9-11)
  • G7 boundary wiring tests never set QWEN_CODE_MODEL_IDENTITY at submit.test.ts:1466 (+1 location) — already reported (comment 3792869882, R9-7)
  • G9 code-review.md:348 quoted cross-model note exists nowhere (incl. the dangling '(below)') — already reported (comment 3792869896, R9-12 / R11-8)
  • J3 authType discriminator unpinned at config-session-env.test.ts:366 — already reported (comment 3792869903, R9-15)

Not reviewed: reverse audit — reached the 5-round cap without converging (rounds 3, 4 and 5 each reported new findings; every round's findings were verified before composing).

Not explored to full depth (tool budget reached): chunk 7: executing submit.test.ts (and config-session-env.test.ts ) to confirm the fixture passes the gate at runtime — no node_modules exists in the review worktre….

Deferred under the convergence posture (round 12, not a blocker) — recorded, not requested in this round:

  • packages/cli/src/commands/review/pr-context.ts:1628 — [review] persistedSha wiring untested at both joints
  • packages/cli/src/commands/review/pr-context.test.ts:189 — [review] buildMarkdown wiring test never exercises the blanked-identity bare-id fallback
  • packages/cli/src/commands/review/compose-review.ts:856 — [review] runtimeModelId JSDoc names the wrong env slot (new location of the R9-11 defect class)
  • packages/core/src/config/config.ts:4326 — [probe] qualified per-session identity registry write untested at the production joint
  • docs/users/features/code-review.md:350 — [review] new paragraph contradicts the unchanged rebased-away sentence three lines below
  • packages/cli/src/commands/review/pr-context.ts:1171 — [probe] parseable sha-less higher-round side file slips past the divergence gate
  • packages/cli/src/commands/review/pr-context.ts:1176 — [probe] divergence wording false for the same-round higher-reviewId keep
  • packages/cli/src/commands/review/pr-context.ts:1171 — [probe] certifier-only divergence slips past the sha-only gate
中文说明

仅完成部分审查,审查缺口已披露。

本轮确认的 7 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

未审查:reverse audit — reached the 5-round cap without converging (rounds 3, 4 and 5 each reported new findings; every round's findings were verified before composing)。

未探索到全部深度(达到工具调用预算):chunk 7:executing submit.test.ts (and config-session-env.test.ts ) to confirm the fixture passes the gate at runtime — no node_modules exists in the review worktre…

收敛姿态下延后(第 12 轮,非阻断)——已记录,本轮不要求修改:共 8 条(原文未翻译,列表见上方英文部分)。

— qwen3.8-max via Qwen Code /review (v0.21.13)


- **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 it to the fetch as `--since <lastCommitSha>`. **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. **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.
- **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` **whose `lastModelId` equals `{{model}}`**, pass it to the fetch as `--since <lastCommitSha>`. **A cached anchor from another model is not passed at all** — an absent `lastModelId` counts as a mismatch, on caches written before the field. "Clean up to `lastCommitSha`" is that model's verdict, and `fetch-pr` validates the anchor against the HISTORY, not against who certified it: hand it a cross-model anchor and it rules `effective`, scoping this round past code `{{model}}` never reviewed — permanently, because this round's own cache write re-anchors past it. 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}}`):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R12-1: The cache-path same-model gate compares BARE model ids on both sides — Step 8 writes "lastModelId": "{{model}}" (the bare config.getModel(), SKILL.md:1280; BundledSkillLoader.ts:109-113), and this gate compares it to the current bare {{model}} — so two provider configurations exposing the same model name pass each other's gate: the exact case the recovery path in this same PR rejects via whole-string equality on provider-qualified identities (certifierMatchesRound; round-model.test.ts pins certifierMatchesRound('m@9f8e7d6c', 'm@1a2b3c4d')).toBe(false)). — Failure scenario: round N under provider P1's qwen3.7-max caches lastModelId: "qwen3.7-max" + sha S; the user switches to provider P2 (different baseUrl/authType, same model name — this PR's own motivating case); round N+1's gate matches on the bare name and passes --since S → fetch-pr validates history only and rules effective → the round scopes S..HEAD past code only P1 reviewed, and its own clean round re-anchors past it permanently. Had the cache been absent (CI machine), the identical switch is caught by the recovery path. DESIGN.md:498's carve-out argues only a FORGED cache id, not this honest-write/honest-compare pass-through.

Witness: not run — the gate is prompt text applied by the orchestrating model; the runnable sub-facts are settled by quoted code (BundledSkillLoader.ts:109-113: {{model}} = bare config.getModel(); SKILL.md:1280 bare write; SKILL.test.ts:175 pins the bare-comparison wording).

Suggested change
- **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` **whose `lastModelId` equals `{{model}}`**, pass it to the fetch as `--since <lastCommitSha>`. **A cached anchor from another model is not passed at all** — an absent `lastModelId` counts as a mismatch, on caches written before the field. "Clean up to `lastCommitSha`" is that model's verdict, and `fetch-pr` validates the anchor against the HISTORY, not against who certified it: hand it a cross-model anchor and it rules `effective`, scoping this round past code `{{model}}` never reviewed — permanently, because this round's own cache write re-anchors past it. 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}}`):
when it holds a `lastCommitSha` **whose `lastModelId` equals the session-published identity (`$QWEN_CODE_MODEL_IDENTITY`, falling back to `{{model}}` when blank)**, pass it to the fetch as `--since <lastCommitSha>`

(Pre-existing bare-valued caches then fail safe — one full re-review until the next clean round rewrites the cache; alternatively, have fetch-pr read the cache and rule this gate in code, where the qualified identity is already available.)

中文说明

【Critical】 R12-1:缓存路径的同模型闸门两侧比较的都是模型 id——Step 8 写入 "lastModelId": "{{model}}"(裸的 config.getModel(),SKILL.md:1280;BundledSkillLoader.ts:109-113),本闸门又把它与当前的裸 {{model}} 比较——因此两个暴露相同模型名的 provider 配置会互相通过对方的闸门:而这正是本 PR 恢复路径上用 provider 限定身份的整串相等(certifierMatchesRound)明确拒绝的情形(round-model.test.ts 钉住了 certifierMatchesRound('m@9f8e7d6c', 'm@1a2b3c4d')).toBe(false))。— 失败场景:provider P1 的 qwen3.7-max 下运行的第 N 轮缓存了 lastModelId: "qwen3.7-max" + sha S;用户切换到 provider P2(baseUrl/authType 不同、模型名相同——本 PR 自己的动机场景);第 N+1 轮的闸门按裸名匹配、传入 --since S → fetch-pr 只校验历史并裁定 effective → 本轮范围取 S..HEAD,跳过了只有 P1 审过的代码,且本轮自己的干净轮次会把锚点永久地前移。若缓存不存在(CI 机器),同样的切换会被恢复路径拦下。DESIGN.md:498 的豁免只论证了伪造缓存 id 的情形,未覆盖这种诚实写入 + 诚实比较的直通。

见证:未运行——闸门是 orchestrating 模型应用的提示词文本;可运行的子事实已由引用的代码证实(BundledSkillLoader.ts:109-113{{model}} = 裸 config.getModel();SKILL.md:1280 裸写入;SKILL.test.ts:175 钉住裸比较措辞)。

**建议修复:**让 Step 8 持久化会话发布的限定身份、闸门对其比较($QWEN_CODE_MODEL_IDENTITY,为空时回退 {{model}},镜像 roundModelIdFrom 的优先序);或让 fetch-pr 读取缓存并在代码里裁定该闸门(那里已可取得限定身份)。既有的裸值缓存则失败安全(一次完整重审)。

— qwen3.8-max via Qwen Code /review (v0.21.13)

Comment on lines +1017 to +1018
const identityDrifted =
roundStart !== '' && runtime !== '' && roundStart !== runtime;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R12-2: The drift gate disengages whenever the post-time runtime channel is blank — even when the plan's reviewModelId stamp proves the round STARTED under a session-published identity — so certifying falls back to the model-written input.modelId, the exact channel this diff's docstrings retire ("never with the model-written state field alone"). The recovery side (certifierMatchesRound) rules an empty running as always-mismatch; the certifying side skips on the same emptiness with provable disagreement available (roundStart !== declared is checkable — or withhold, as the fix below does). — Failure scenario: round starts under A → fetch-pr stamps reviewModelId: 'A@digest'; the post then runs where the runtime slots are empty (a standalone/deferred qwen review submit from a terminal outside a session shell — round-model.ts documents the empty case as reachable in normal operation) → identityDrifted is false regardless of the stamp → the marker certifies the sha to the typed id → a later round under a matching typed id passes certifierMatchesRound and scopes sha..HEAD past code it never reviewed — the regression this PR exists to close.

Witness: probe over the real composeReview — plan stamped model-a@aaaaaaaa, runtimeModelId: '', typed model-b → observed {"sha":"deadbeef00112233","model":"model-b"}; flip-patch roundStart !== '' && (runtime === '' || roundStart !== runtime){} (pair withheld), both controls unchanged.

Suggested change
const identityDrifted =
roundStart !== '' && runtime !== '' && roundStart !== runtime;
const identityDrifted =
roundStart !== '' && (runtime === '' || roundStart !== runtime);

(Fail-safe cost: one full re-review for same-model out-of-session posts; alternatively, document in this comment why a stamped round with a dead runtime channel may trust the typed field.)

中文说明

【Critical】 R12-2:当发布时刻的运行时通道为空时,漂移闸门整体失效——即使 plan 的 reviewModelId 戳已证明本轮开始于某个会话发布的身份——于是 certifying 回退到模型自己写入的 input.modelId,而这正是本 diff 的 docstring 明确废黜的通道(「绝不能仅凭模型写入的 state 字段」)。恢复侧(certifierMatchesRound)把空 running 裁为必定不匹配;认证侧却在同样为空、且存在可证明的分歧(roundStart !== declared 可查——或如下方修复直接扣下)时直接跳过。— **失败场景:**轮次在 A 下开始 → fetch-pr 打上 reviewModelId: 'A@digest';随后发布运行在运行时槽为空的环境(会话 shell 之外的终端里独立/延迟执行 qwen review submit——round-model.ts 明确该空值情形在正常操作中可达)→ 无论戳为何值 identityDrifted 恒为 false → marker 把该 sha 认证到模型手写的 id → 之后手写 id 相同的一轮通过 certifierMatchesRound、范围取 sha..HEAD,跳过它从未审过的代码——正是本 PR 要堵的回归。

见证:对真实 composeReview 的探针——plan 打戳 model-a@aaaaaaaaruntimeModelId: ''、手写 model-b → 观测到 {"sha":"deadbeef00112233","model":"model-b"};补丁翻转为 roundStart !== '' && (runtime === '' || roundStart !== runtime){}(锚点对被扣下),两个对照均不变。

**建议修复:**见上方 suggestion 块(失败安全代价:同模型的会话外发布多付一次完整重审;或者在此注释中说明:为何带戳但运行时通道为死的轮次可以信任手写字段)。

— qwen3.8-max via Qwen Code /review (v0.21.13)

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix stopped after 5 consecutive rounds that failed to push anything (timeouts and/or gate rejections). Retrying at the same per-round budget is not converging — this usually means the PR is too large or conflicts with a fast-moving main. A human should rebase, split, or reduce it, then comment @qwen-code /retry to re-arm. Until then future scans will skip this PR.

What I found before stopping:

PR #9184 is not converging — maintainer decision required

The workflow's convergence brake has engaged: this counting window has been over
the diff-growth budget for 12 rounds and the diff is still not shrinking
(source 448 / test 1169 net lines vs budgets 400/400; independently
re-measured here against origin/main: 22 files, +1884/−98, ≈486 net source
and ≈1298 net test lines). Per the round contract this round applied no code
fixes and no commit
— the findings themselves are driving the growth, so
Critical-only patching cannot converge. This is a defer-to-human stop.

The decision needed

How to proceed with PR #9184 (review-anchor model gate): split it, redesign
the identity gating, accept the current state with the tail deferred, or
restart the loop on a fresh window. The call is the maintainer's; the loop
will keep regenerating findings in the same class until one of these is chosen.

Evidence: one defect class keeps reappearing on code earlier rounds added

The PR wires a provider-qualified model identity through four boundaries
(fetch-pr stamp, compose-review certifying gate, pr-context recovery
ruling, SKILL.md prompt gates). Every round closes one channel mismatch and a
later round finds the next: R9-7 / R9-11 / R9-13 / R9-15, R11-8, and now R12-1
and R12-2 — all the same class, "two boundaries mean different strings by the
round's identity". The two Criticals open this round were both verified against

Run log: https://github.com/QwenLM/qwen-code/actions/runs/32099558400


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

R12-1 and R12-2 are the sixth and seventh findings in one class — two
boundaries meaning different strings by the round's identity — so these
close the class rather than the two instances.

R12-1: the cache-path gate compared BARE ids on both sides. Step 8 writes
`lastModelId: "{{model}}"` and the gate compared it to `{{model}}`, both
the bare `config.getModel()`, so two provider configurations exposing one
model name passed each other's gate — the exact case the recovery path in
this PR rejects. Self-consistent is not sound; it was consistently wrong
across providers, and I deferred it last round as an asymmetry when it was
a hole.

The gate moves into `fetch-pr`, beside the one the anchor already goes
through: `--since-model` carries WHO certified the anchor, the skill
copies both fields verbatim, and `certifierMatchesRound` — the same
function the marker-recovery ruling uses — decides. A mismatch reports
`cross-model-anchor` and reviews the full range, refused before the
history is consulted at all.

That leaves ZERO identity comparisons in prompt text. Six rounds have each
closed one channel and the next round found another; the reason the class
kept regenerating is that a comparison written in prompt text cannot
share the CLI's notion of the string, and `{{model}}` is structurally the
wrong one — it interpolates the bare id where everything the CLI records
is provider-qualified. The SKILL guard now asserts the absence, not just
the presence: no `lastModelId equals`, no `model matches`/`model differs`.

R12-2: the drift gate disengaged whenever the post-time runtime channel
was blank, even with the plan's stamp proving the round STARTED under a
published identity — so `certifying` fell back to the model-written
`input.modelId`, the channel these docstrings retire. The recovery side
already rules an empty running identity a mismatch; the certifying side
does now too. An UNSTAMPED round still keeps its old behaviour, because
it cannot prove disagreement either.

Two new tests, both mutation-checked.
@wenshao

wenshao commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Sandboxed verification: ❌ not passed — blocked (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: 3560 passed · 0 failed · 3560 total

中文 — 判定:❌ 不通过 · 阻塞(agent 判定)

沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查

脚本断言:3560 通过 · 0 失败 · 3560 总计

Verification report

PR #9184 Deep Verification (round 2) — fix(review): gate the recovered incremental anchor on the model that certified it

Verdict: blocked — 3560/3560 scripted assertions passed (fail: 0), the central claim's A/B proof holds at all four seams, and both round-1 findings are fixed — but this round reproduced a blocking regression the final commit introduced: the gate compares certifiers against the provider-qualified runtime identity while both production certifier writers emit a bare id or nothing, so same-model incremental scoping (and the same-SHA "no new changes" stop) can never engage again in any session that publishes an identity. Fail-safe in direction, loud on stderr, but it defeats the feature this PR exists to gate.
Verified head: 411287758df06cac8aee2a4ee581244fb6bfd313 (git rev-parse HEAD^2) · base tip: 72ae65d78fcc07ce65b5a38daeb33110d15f90bc (HEAD^1) · merge: 095bf05cca.

中文摘要
  • 判定:blocked。3560 条脚本断言全部通过(0 失败);中心声明(跨模型 anchor 不再能缩小审查范围)在四个接缝上的 A/B 均成立;上一轮的两个覆盖缺口(F1/F2)均已修复。但本轮复现了一个阻塞性回归:闸门把认证者与"带 provider 摘要的运行身份"(<model>@<8hex>)做全串比较,而两个生产侧的认证者写入方都只产出裸 id 或空值——缓存写入方(SKILL.md Step 8 的 "lastModelId": "{{model}}",裸 id)与恢复路径的 re-run(只被指示传 --since <sha>,全文仅缓存路径提到 --since-model)。因此同模型的增量缩小、以及同 SHA 的"No new changes"快停,在一切发布 qualified 身份的会话中永远无法触发(harness 动态证实:裸认证者/无认证者在 head 被拒、在 base 被采用)。方向上是 fail-safe 的,stderr 也会大声提示,但它让本 PR 要保护的功能完全失效,且与描述中"incremental scoping resumes from the next posted round"相矛盾。
  • A/B 结论:表 1–4(fetch-pr 闸门、compose 身份携带/漂移闸、marker 往返与渲染判定、shell 身份通道)head 全部按闸门语义行为,base 全部按"洞"行为;见证图 01-…png04-…png
  • Findings:F3(阻塞,上述回归,含爆炸半径与未测量的修复方向);F4(建议级:reviewModelId 戳记的写入侧无测试钉住,M11 存活);F5(nit:identityDriftedruntime === '' || 子句被证明冗余)。
  • 未覆盖:orchestrator 是否照 SKILL.md 逐字执行(F3 链条中"模型写裸 id"一环为静态证据:模板行 + DESIGN.md + 全仓库无替换机制);真实发帖链路;per-commit 归因;macOS/Windows。

Previous-round findings (round 1 at cb366f55)

# finding (round 1) severity status at 411287758d re-measurement
F1 SKILL.md gate hunks pinned by no test (M8 survived) Suggestion fixed Reverting SKILL.md to the base text now reddens 2 tests, incl. the new pins the same-model gate on both incremental-anchor paths (21/21 unmutated control → 19/21 reverted). Agree with round-1 classification.
F2 submit boundary identity injection unpinned (M6 survived) Suggestion fixed Deleting roundModelIdFrom(process.env) from runSubmit's compose call now reddens exactly injects the session model into the posted marker — QWEN_CODE_MODEL reaches the wire (wiring) (68/68 unmutated control → 1 red reverted).

Both were re-measured by mutation at the new head, not diffed off the old report.

Central claim + A/B

Central claim: an incremental anchor can no longer scope a round under an identity that did not review it — the marker carries the certifying identity end-to-end, the cache path hands its certifier to the CLI, and the gate is ruled inside fetch-pr / pr-context (never in prompt text), with absent/blank counting as mismatch.

The A/B drives the compiled dist/ of each arm through four seams; base expectations encode the hole (expected failures are passes). Witnesses: 01-fetch-gate-ab-head-vs-base.png, 02-compose-drift-gate-ab-head-vs-base.png, 03-marker-verdict-ab-head-vs-base.png.

Table 1 — fetch-pr --since-model gate (real fetchPrCommand.handler, mocked git/gh only; witness 01):

cell (same scenario both arms) head base
anchor certified by another provider (same-name@other-digest) refused cross-model-anchor, before any history probe; full-range diff still produced; stderr names both identities scoped effective: true (the hole)
anchor nobody certified (pre-field cache) refused scoped (the hole)
bare id vs qualified runner refused scoped
same qualified identity (positive control) scoped effective: true scoped

Head 4/4, base 4/4. Subprocess wiring: review fetch-pr --help exposes --since-model at head, not at base.

Table 2 — compose drift gate + identity carriage (real composeReview over covered-plan fixtures; witness 02):

cell head base
aligned stamp marker certifies with the runtime identity bare anchor (hole)
runtime supersedes typed state-JSON id n/a
reviewed as A, posting as B PAIR withheld; findings still post bare anchor posted (hole)
stamped, BLANK runtime (terminal post) PAIR withheld bare anchor (hole)
unstamped plan, blank runtime declared id certifies (today's behaviour kept) bare anchor
attribution off sha posts WITHOUT certifier same shape

Head 6/6, base 6/6.

Table 3 — marker round-trip + rendered verdict (pure dist functions; witness 03): head 44/44, base 17/17. Covers: model rides beside sha and drops with it (invalid sha, over-cap pair-withhold at 64/65 boundary, truncated-round withhold); cross-model / same-model / legacy / divergence / unpublished-runner verdicts rendered with both identities named; roundModelIdFrom (identity preferred, blank→bare fallback, neither→'') and certifierMatchesRound (whole-string, every unknown a mismatch) exist only at head; base's rendered section hands the anchor over with no model condition.

Table 4 — shell identity channel (core dist): head 13/13, base 6/6. Per-session registry passes the qualified identity down; a session with none gets '' written, so the spawn-site {...process.env, ...} spread cannot leak a stale parent value (base leaks it — hole); the global fallback is guarded (identityDescribes, suffix-anchored, @-in-model handled); unregister drops model+identity together.

Load-bearing totals: head-side gate-decidable scenarios 2/2 at the fetch seam and 6/6 at compose; base structurally 0. The mutation matrix (witness 04-mutation-matrix-live.png, below) shows every new guard's kill set.

Corrections

  • Description vs measured mechanics — "incremental scoping resumes from the next posted round" does not hold. The Risk & Scope section states the first round treats pre-field anchors as mismatches and scoping resumes from the next posted round. Measured: the recovery re-run is instructed to pass --since <sha> only (SKILL.md's single --since-model mention is the cache path), and an uncertified --since is refused by the gate (Table 1, cell 2) — so the recovery path's scoping never engages as instructed either. See F3.
  • Commit c16d871's "the cache path … is self-consistent" was invalidated by the final commit. At c16d871 the cache-path gate lived in prompt text comparing lastModelId (bare) to {{model}} (bare) — self-consistent. 411287758d moved the comparison into fetch-pr, where the running side is roundModelIdFrom(process.env) — provider-qualified whenever the session publishes an identity. The writer side still emits the bare id. The two sides are now different identity spaces; the gate refuses the legitimate same-model case (F3).

Findings

F3 (blocking) — the gate's certifier space matches neither production writer: same-model incremental review is dead

Mechanism. The gate is certifierMatchesRound(sinceModel, roundModelIdFrom(process.env)) in fetch-pr — whole-string equality. The running side is the provider-qualified identity <model>@<8hex(authType␀baseUrl): Config.publishModelEnv registers it per session, and shellExecutionService spreads getShellContextEnvVars() into every shell subprocess (both proven live: Table 4, and the M10 kill). The certifier side comes from two writers, and neither can produce that string:

  1. Cache path — Step 8's template is "lastModelId": "{{model}}" (SKILL.md L1280), and {{model}} is the BARE config.getModel() — the PR's own DESIGN.md (L723) and SKILL text state this, and no substitution mechanism exists anywhere in the repo (grepped). Step 1 passes it verbatim as --since-model.
  2. Recovery path — the re-run instruction is "re-run the fetch-pr command from above with --since <sha>"; --since-model appears exactly once in SKILL.md (cache path). The side file carries the qualified model, but nothing tells the orchestrator to copy it.

Dynamic proof. Table 1 cells 2–3: bare certifier vs qualified runner → cross-model-anchor at head while base SCOPES the identical scenario; absent certifier → refused at head. The PR's own fetch-pr suite never exercises the production writer's shape — its fixtures pass qualified certifiers (the accept-path-against-real-artifacts gap).

Blast radius (every session that publishes a qualified identity — i.e. any real provider config, since resolvedModelIdentity digests whenever authType or baseUrl is non-empty):

  • Cache-path incremental scoping (differing-SHA branch) never engages: every high-effort round re-reviews the full diff, and re-caches the bare id, forever.
  • The same-SHA upToDate "No new changes since last review" stop is unreachable: the cross-model refusal short-circuits before resolveIncrementalAnchor computes upToDate (proven: no cat-file/merge-base probe ran in the refused cells). Re-reviewing an unchanged PR is now always a full review — the exact cost class DESIGN.md measured at 119 min / 34M tokens for one round.
  • Recovery-path scoping never engages as instructed (uncertified --since refused), contradicting the description's resume claim.

Bounds. Fails safe in every direction — no cross-model scope-skip is possible; the refusal is loud on stderr (Incremental anchor not used — it was certified by "X", and this review runs as X@<digest>); findings/work-list carriage is unaffected; low/medium effort never consulted the cache. The regression is cost/feature, not correctness — but it defeats the payoff this PR exists for, on the happy path, indefinitely.

Repro (scripted): harnesses/__verify_fetch_ab.test.ts cells "bare model id vs provider-qualified runner is NOT a match" and "uncertified anchor" (head refuses / base scopes), plus git grep -n "since-model" packages/core/src/skills/bundled/review/SKILL.md (1 hit — cache path only) and L1280's "lastModelId": "{{model}}".

Suggested fix direction (unmeasured — new surface; do not merge as-is)

The cache must carry the qualified identity, which the model cannot know — so a CLI writer is required: e.g. a review cache-write pr-<n> step (called by Step 8) that stamps roundModelIdFrom(process.env) beside lastCommitSha, mirroring how compose-review certifies the marker; and the SKILL's recovery re-run must pass --since-model copied verbatim from the side file's model (the fetch-pr --since-model help already anticipates "the model beside the marker sha"). Do NOT bridge by prefix-matching a bare certifier against a qualified runner — that is exactly the two-providers-one-name hole the digest closes. The un-instructed recovery re-run could alternatively be made safe by having fetch-pr read the side file itself when --since-model is absent, but that widens the command's trust surface; the copy-two-fields shape is cheaper.

F4 (Suggestion) — the reviewModelId stamp write is pinned by no test (M11 survived)

Removing ...(roundModelId ? { reviewModelId: roundModelId } : {}) from the fetch report leaves fetch-pr.test.ts 133/133 green, and no other suite (cli, core, integration) mentions reviewModelId on the write side. The READ side is pinned (compose-review tests drive the drift gate from a stamped plan fixture), so a regression that drops the stamp would silently disarm the drift gate — the deferred-post hole (reviewed as A, /model to B, post) reopens with every suite green. Same class as round-1's F2. Fixture that would pin it: a reportFor({}) assertion that report.reviewModelId equals the env identity.

F5 (nit) — the runtime === '' || clause in identityDrifted is provably redundant

M4 (delete the clause) survives 280/280 because roundStart !== '' already implies roundStart !== runtime when runtime is ''; M4b (disable the whole check) kills 2 named tests, so the behaviour is pinned — the clause is documentation, not logic. Harmless; noted so a future "simplification" isn't read as a regression.

Mutation matrix (live; witness 04-mutation-matrix-live.png)

mutant guard suite result classification
M1 certifierMatchesRound empty==empty passes round-model KILLED (1) pinned
M2 roundModelIdFrom absent-only fallback round-model KILLED (1) pinned
M3 fetch-pr gate disabled fetch-pr KILLED (1) pinned
M4 drop runtime === '' || clause compose-review SURVIVED dead code (redundant; see F5)
M4b drift check disabled entirely compose-review KILLED (2) positive control for M4's suite
M5 omit identity key instead of blank shellContextEnv KILLED (6) pinned
M10 identity loses provider digest config-session-env KILLED (2) pinned
MF1 SKILL.md gate text reverted to base SKILL.test KILLED (2) pin for F1's fix
MF2 submit injection removed submit KILLED (1) pin for F2's fix
M11 reviewModelId stamp write removed fetch-pr SURVIVED coverage gap → F4

Controls green first (cli 141, core 58). Every killed mutant failed the intended assertion (names quoted in the witness). Survivors adjudicated: M4 dead code, M11 coverage gap; neither mirrors a pre-existing gap.

Not covered

  • Orchestrator compliance — F3's writer-side links ("the model writes the bare {{model}}"; "the recovery re-run passes no certifier") are static: the template line, DESIGN.md's {{model}} = config.getModel(), the absence of any substitution code, and the single --since-model mention. The gate's behaviour for those inputs is dynamic (Table 1). Whether a real orchestrator improvises --since-model from the side file is model behavior, unreachable from code on either arm.
  • Real GitHub posting (review submit against the wire) — not driven; the compose seam it calls is covered (Table 2).
  • Per-commit attribution — depth-2 checkout; verified the aggregate HEAD^1..HEAD diff; per-commit claims taken from messages, not isolated trees.
  • Repo-wide vitest beyond the targeted packages (typecheck ran repo-wide, clean); macOS/Windows (no platform-specific paths in the diff).
  • The upToDate regression cell is proven by the refusal's short-circuit (no ancestry probes ran), not by a dedicated upToDate fixture on both arms.

Methodology

Environment: node:22-bookworm CI container, merge-ref checkout at depth 2; npm ci + npm run build pre-run at HEAD. Base arm: git worktree add tmp/base-tree HEAD^1; PR touches no package.json/lockfile, so root node_modules was reused, with @qwen-code/* links re-pointed into the base tree and realpath-asserted (readlink -f node_modules/@qwen-code/qwen-code-core → base tree) before any base cell ran; base core+cli rebuilt there (nested per-package node_modules symlinked, since ajv@​8 etc. are not hoisted). Harnesses are mock-free w.r.t. the units under test: compiled dist modules, the real fetchPrCommand.handler/composeReview over on-disk fixtures replicating the repo's own covered-plan layout (git/gh mocked as external systems, same seam the package suite uses). Mutation matrix applied/reverted per row in the main tree, scoped vitest runs, tree verified clean after. Raw logs in logs/; harnesses in harnesses/ + *.mjs/*.sh. Evidence rendered with scripts/verify-capture.mjs. Assertion count = gate tests (cli review 3362 + core 65 + SKILL 21) + harness checks (61 marker + 19 shell) + harness vitest tests (20) + wiring probes (2) + matrix rows as classified (10) = 3560.

Evidence images

01-fetch-gate-ab-head-vs-base

02-compose-drift-gate-ab-head-vs-base

03-marker-verdict-ab-head-vs-base

04-mutation-matrix-live

Harness scripts and raw logs are in the workflow run artifacts (7-day retention).

Qwen Code · sandboxed verification

@wenshao

wenshao commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

R12-1 and R12-2 fixed — and the class they belong to is closed

41128775. Taking the convergence comment seriously, because its diagnosis is right: R9-7 / R9-11 / R9-13 / R9-15, R11-8, R12-1, R12-2 are one class — two boundaries meaning different strings by the round's identity — and every round has closed one channel while the next round found the next. Point-fixing that indefinitely is not convergence, so this round closes the class instead.

The root cause is structural, and it is prompt text

A comparison written in prompt text cannot share the CLI's notion of the string. Worse, the only model value a skill body can interpolate is {{model}}BundledSkillLoader substitutes config.getModel(), the bare id — while every identity the CLI records is provider-qualified. So a prompt-level identity gate was never comparing the same kind of string, and it never could be.

R9-1 moved the recovery gate into the CLI for exactly this reason. R12-1 is the last one left, and it moves too: fetch-pr gains --since-model, the skill copies lastCommitSha and lastModelId through verbatim, and certifierMatchesRound — the same function the marker ruling uses — decides. A mismatch reports cross-model-anchor and reviews the full range, refused before the history is consulted at all.

There are now zero identity comparisons in prompt text. The SKILL guard asserts the absence, not just the presence:

expect(body).not.toMatch(/`lastModelId` equals/);
expect(body).not.toMatch(/model matches|model differs/);

That is what makes this structural rather than a seventh point fix: the class cannot regenerate in a place that no longer exists. Net effect on the diff is close to flat — the cache bullet shrank by roughly what the flag and its gate added.

R12-2 — the certifying side skipped where the recovery side refuses

Correct, and it is the same asymmetry in miniature. With the post-time channel blank — a deferred submit from a terminal outside a session shell, which round-model.ts documents as reachable — identityDrifted was false regardless of the stamp, so certifying fell back to the model-written input.modelId: the channel this PR retires. certifierMatchesRound already rules an empty running identity a mismatch; the certifying side does now too. An unstamped round keeps its old behaviour, because it cannot prove disagreement either.

On the convergence question

My read, for whatever it is worth to the decision: the growth was findings-driven, and the findings were one class with one root. With the prompt-text surface gone I would expect the class to stop rather than produce an eighth instance. If it does not, that is evidence for splitting rather than for another round.

If you would rather split regardless, the natural seam is lib/round-model.ts + the four CLI boundaries (this PR's core) versus the SKILL.md rewrites — but the two halves are only meaningful together, so I would take accept with the tail deferred over a split. Your call; I have not acted on it either way.

Two new tests, both mutation-checked. packages/cli review suite 3357 passed, SKILL guards 21 passed, typecheck clean over commands/review with core built first, prettier clean.

中文说明

R12-1、R12-2 已修,并且关掉了它们所属的那一类。收敛评论的诊断是对的:R9-7/R9-11/R9-13/R9-15、R11-8、R12-1、R12-2 是同一类——两个边界对「本轮身份」理解成不同的字符串——每轮关掉一条通道,下一轮就找到下一条。

根因是结构性的:写在提示词里的比较无法与 CLI 共享同一个字符串概念,而技能正文唯一能插值的模型值 {{model}} id,CLI 记录的每个身份都是 provider 限定的——两边从来就不是同一种字符串。

R9-1 已经把恢复路径的门禁移进 CLI,R12-1 是最后一处:fetch-pr 新增 --since-model,技能只原样复制两个字段,由 certifierMatchesRound(与 marker 裁决同一个函数)判定;不匹配报 cross-model-anchor,在查历史之前就拒绝。提示词里已经没有任何身份比较,SKILL 守卫断言的是「不存在」而非「存在」。这才是结构性的:类无法在一个已经不存在的地方再生。diff 净增接近于零——缓存段落缩减的量约等于新增的标志与门禁。

R12-2 是同一种不对称的缩影:发布侧通道为空时跳过检查,于是回退到模型自己写的字段。恢复侧早已把空判为不匹配,现在认证侧也一样。

关于收敛:增长由发现驱动,而发现是同一类同一个根因。提示词表面消失后我预期这一类会停止;若仍出现第八例,那才是应该拆分的证据。若你倾向拆分,我建议改选「接受并延后尾部」——两半单独没有意义。这个决定我没有代你做。

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot has neither a verdict nor a deferral on 411287758df06cac8aee2a4ee581244fb6bfd313 — no APPROVED, CHANGES_REQUESTED, or COMMENTED review of its own. A DISMISSED one does not count: dismiss_stale_reviews voids the bot's approval on every push, which is exactly when a fresh one is needed. If this re-run was meant to review or approve, it did not, and an approval left by another account is a separate vote that does not count as the bot's own.

⚠️ 机器人在 411287758df06cac8aee2a4ee581244fb6bfd313既没有裁决也没有 defer —— 没有属于它自己的 APPROVEDCHANGES_REQUESTEDCOMMENTED 评审。DISMISSED 不算:dismiss_stale_reviews 会在每次推送时作废机器人的批准,而那恰恰是需要一次新批准的时刻。如果这次重跑本应评审或批准,那么它没有做到;而其他账号留下的批准是另一张票,不能算作机器人自己的。

The stage comments above were updated with the latest result. View workflow run.

上方各阶段评论已更新为最新结果。查看工作流运行

@qwen-code-dev-bot qwen-code-dev-bot added the autofix/needs-human The autofix loop stopped on this PR — a human must re-arm, split, merge, or close it label Aug 18, 2026
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

⏸️ Takeover paused: this PR reached its round cap (100/100). Comment @qwen-code /takeover to re-arm a fresh window and continue management, or @qwen-code /takeover stop to release.

中文说明

⏸️ 托管已暂停:本 PR 达到轮次上限(100/100)。评论 @qwen-code /takeover 可重新武装、开启新窗口继续托管;或评论 @qwen-code /takeover stop 释放。

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM✅

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wenshao
wenshao added this pull request to the merge queue Aug 18, 2026
Merged via the queue into main with commit 30366b5 Aug 18, 2026
63 of 65 checks passed
wenshao added a commit that referenced this pull request Aug 18, 2026
#9184 landed as a SQUASH, so git cannot see that this branch already
contains its commits and replays them as conflicts. Every line of main's
side is present here already — verified line by line, not assumed — so
all four hunks take this branch's version, which is a superset:

- fetch-pr.ts: main has nothing at either site (the
  `computeIncrementalScope` import and `lineage-unfollowable` are this
  PR's).
- SKILL.md: the two sides differ only in the `effective: true` bullet,
  where this PR's slicing/widening description supersedes the squash's
  `(since..head)`.
- fetch-pr.test.ts: the spelling reconciled when 9184 was merged in
  here — `ruling(...)` rather than `.incremental` — plus this PR's own
  slicing tests.
@wenshao
wenshao deleted the fix/review-anchor-model-gate branch August 18, 2026 09:21
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.14.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autofix/needs-human The autofix loop stopped on this PR — a human must re-arm, split, merge, or close it autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants